Compare commits
92 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fba7f0ee81 | |||
| e0da2a4c46 | |||
| f588ece7c3 | |||
| 9ad5b76542 | |||
| 3d2c699964 | |||
| f95c3c5fcf | |||
| 4654ecacaf | |||
| 1be27746e3 | |||
| c51190feef | |||
| c4ce97f20c | |||
| 837317c84c | |||
| df852ef36e | |||
| c00722823a | |||
| e31f1c59e1 | |||
| 5d0d7a6d94 | |||
| b372c6ac1c | |||
| 124dea2e58 | |||
| eaef00ff54 | |||
| 892ba5fff0 | |||
| 628f1631e8 | |||
| 0b815950e1 | |||
| f10e7e6d72 | |||
| 700ecf3e5d | |||
| f7c53fc6c3 | |||
| 9764ec6db1 | |||
| b21faa30fc | |||
| 87f8b8799e | |||
| 769f1bb677 | |||
| 5623fdc020 | |||
| dfd91b5f8b | |||
| 3c43978c55 | |||
| fb7b51a971 | |||
| 56c360104b | |||
| e414da3369 | |||
| 5f1f698530 | |||
| 729e88bc6d | |||
| bffc7f9f1c | |||
| 011b272af6 | |||
| ee359da751 | |||
| 6025e17186 | |||
| 93d7aca9e6 | |||
| 677c784b6d | |||
| e69a367c33 | |||
| 14d0475d59 | |||
| 762d344e42 | |||
| be5591f7dc | |||
| 7193f5a646 | |||
| f46c2ad0f7 | |||
| b0f7a264c2 | |||
| 4f3164a48a | |||
| be55d661cb | |||
| 3de9fde672 | |||
| a0582e918b | |||
| 18429d9cf9 | |||
| b65df7c390 | |||
| 22d1be5ea4 | |||
| 18fc82f036 | |||
| f5b843ec11 | |||
| bad5d26969 | |||
| 951d741d90 | |||
| fe6c9858a2 | |||
| 1df354d5f1 | |||
| 6119bc92ed | |||
| e8140b3160 | |||
| 75789e574e | |||
| c0c46e197f | |||
| a0e6df7cfd | |||
| 1643412f1b | |||
| 3ed6edc323 | |||
| fa7a331a66 | |||
| 939d402b1e | |||
| 492cbe48e9 | |||
| a17e1f473a | |||
| 359f3e68ab | |||
| 5c62191f3b | |||
| b04201de42 | |||
| a15cbcba7b | |||
| 9019d90b1e | |||
| d07b2bdf0a | |||
| d05054755c | |||
| 1a89920430 | |||
| 54a836b734 | |||
| 8b3b07e32c | |||
| d55b402269 | |||
| 24900b8fcc | |||
| 2368a087c0 | |||
| 994a1571b7 | |||
| aed1d3848b | |||
| 93cf39cfe9 | |||
| bdaf578f86 | |||
| 6079e96efa | |||
| 41d8e223ce |
File diff suppressed because it is too large
Load Diff
@@ -54,12 +54,8 @@ http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<version>3.11.0</version>
|
||||
<configuration>
|
||||
<compilerArgs>--enable-preview</compilerArgs>
|
||||
<<<<<<< HEAD
|
||||
<source>20</source>
|
||||
<target>20</target>
|
||||
=======
|
||||
<release>20</release>
|
||||
>>>>>>> patternMatching
|
||||
<source>21</source>
|
||||
<target>21</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
@@ -89,6 +85,7 @@ http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
@@ -127,11 +124,6 @@ http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
</repository>
|
||||
</repositories>
|
||||
<properties>
|
||||
<<<<<<< HEAD
|
||||
<maven.compiler.source>20</maven.compiler.source>
|
||||
<maven.compiler.target>20</maven.compiler.target>
|
||||
=======
|
||||
>>>>>>> patternMatching
|
||||
<mainClass>de.dhbwstuttgart.core.ConsoleInterface</mainClass>
|
||||
</properties>
|
||||
<distributionManagement>
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
class Pair<U, T> {
|
||||
U a;
|
||||
T b;
|
||||
Pair(U x, T y) {
|
||||
a = x; b = y;
|
||||
}
|
||||
}
|
||||
|
||||
class Complex {
|
||||
m(b) {
|
||||
var c = b;
|
||||
var d = c;
|
||||
var e;
|
||||
d = e;
|
||||
var r1 = e;
|
||||
var f = e;
|
||||
var g;
|
||||
f = g;
|
||||
var r2 = g;
|
||||
return new Pair<>(r1, r2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
public class InfReturn {
|
||||
m(a) {
|
||||
var ret;
|
||||
a = ret;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
public class InfReturnII {
|
||||
m(a, b) {
|
||||
var ret;
|
||||
a = ret;
|
||||
b = ret;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
class InnerInf {
|
||||
m(a, b) {
|
||||
var i;
|
||||
a = i;
|
||||
b = i;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
/*
|
||||
class Pair<T, U> {
|
||||
T x;
|
||||
U y;
|
||||
@@ -17,7 +17,7 @@ class Pair<T, U> {
|
||||
return y;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
public class Iteration {
|
||||
id(x) {
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import java.lang.Integer;
|
||||
import java.lang.Double;
|
||||
|
||||
class Overloading {
|
||||
m(x) { return x + x; }
|
||||
m(x) { return x || x; }
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
class RecursionCond {
|
||||
m(a, b, c) {
|
||||
if (1 == 2) {
|
||||
b = m(a, b);
|
||||
c = m(a, b);
|
||||
} else return a;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import java.lang.Boolean;
|
||||
import java.lang.Integer;
|
||||
|
||||
public class Test {
|
||||
fac = (x) -> {
|
||||
if (x == 1) { return 1; }
|
||||
return x * fac.apply(x - 1);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
class Triple<U, T, S> {
|
||||
U a;
|
||||
T b;
|
||||
S c;
|
||||
|
||||
Triple(U x, T y, S z) {
|
||||
a = x; b = y; c = z;
|
||||
}
|
||||
|
||||
U fst() { return a; }
|
||||
T snd() { return b; }
|
||||
S thrd() { return c; }
|
||||
}
|
||||
|
||||
public class TripleTest {
|
||||
m() {
|
||||
return new Triple<>(m().thrd(), m().thrd(), m().thrd());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
class Twice2 {
|
||||
id1inst = new Id<>();
|
||||
id1 = id1inst.id;
|
||||
id2inst = new Id<>();
|
||||
id2 = id2inst.id;
|
||||
twice = id1.apply(id2);
|
||||
|
||||
}
|
||||
|
||||
class Id<T> {
|
||||
id = (T x) -> x;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import java.lang.Integer;
|
||||
|
||||
public class Chain {
|
||||
x = 5;
|
||||
|
||||
chain() {
|
||||
return this;
|
||||
}
|
||||
|
||||
m() {
|
||||
return this.chain().chain().chain().x;
|
||||
}
|
||||
}
|
||||
Regular → Executable
@@ -1,8 +1,8 @@
|
||||
import java.lang.Integer;
|
||||
import java.lang.Double;
|
||||
import java.lang.String;
|
||||
|
||||
public class Fac {
|
||||
|
||||
getFac(n) {
|
||||
var res = 1;
|
||||
var i = 1;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import java.lang.String;
|
||||
|
||||
public class FieldTph2 {
|
||||
a;
|
||||
|
||||
|
||||
@@ -4,20 +4,20 @@ 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;
|
||||
// }
|
||||
Boolean b = true;
|
||||
c = 5;
|
||||
c++;
|
||||
++c;
|
||||
c--;
|
||||
--c;
|
||||
while(x<2){
|
||||
x = x +1;
|
||||
b = false;
|
||||
}
|
||||
for(int i = 0; i<10; i++) {
|
||||
x = x + 5;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
// m2(Integer x){
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import java.lang.Integer;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class FunctionalInterface {
|
||||
Integer accept(Function<Integer, Integer> f) {
|
||||
return f.apply(20);
|
||||
}
|
||||
|
||||
Integer m() {
|
||||
var v = accept(i -> {
|
||||
return i * 10;
|
||||
});
|
||||
return v;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import java.lang.System;
|
||||
import java.lang.String;
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class HelloWorld {
|
||||
static hello() {
|
||||
System.out.println("Hello World!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import java.lang.Number;
|
||||
import java.lang.Integer;
|
||||
import java.lang.Double;
|
||||
import java.lang.String;
|
||||
|
||||
public class InstanceOf {
|
||||
main(n) {
|
||||
if (n instanceof Integer i) {
|
||||
takes(i);
|
||||
return "Integer";
|
||||
} else if (n instanceof Double d) {
|
||||
takes(d);
|
||||
return "Double";
|
||||
}
|
||||
}
|
||||
|
||||
takes(i) {} // Should be overloaded
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import java.lang.Integer;
|
||||
|
||||
interface A {
|
||||
void method1();
|
||||
default method2() {
|
||||
}
|
||||
}
|
||||
|
||||
interface B {
|
||||
void method3();
|
||||
}
|
||||
|
||||
interface C {
|
||||
Integer myInt();
|
||||
}
|
||||
|
||||
class ClassX implements A {
|
||||
}
|
||||
|
||||
record ClassY(Integer myInt) implements C {}
|
||||
|
||||
public class Interfaces implements A, B {
|
||||
public void method1() {
|
||||
}
|
||||
public void method3() {
|
||||
var intf = new Interfaces();
|
||||
intf = new ClassX();
|
||||
intf.method1();
|
||||
|
||||
C c = new ClassY(10);
|
||||
c.myInt();
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,16 @@
|
||||
import java.lang.Runnable;
|
||||
import java.lang.String;
|
||||
import java.lang.System;
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class LamRunnable{
|
||||
public class LambdaRunnable {
|
||||
|
||||
public LamRunnable(){
|
||||
public LambdaRunnable(){
|
||||
|
||||
|
||||
Runnable lam = () -> {System.out.println("lambda");};
|
||||
Runnable lam = () -> {
|
||||
System.out.println("Runnable is running");
|
||||
};
|
||||
lam.run();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import java.lang.Integer;
|
||||
import java.lang.Number;
|
||||
import java.lang.Float;
|
||||
|
||||
record Point(Number x, Number y) {}
|
||||
|
||||
public class OverloadPattern {
|
||||
m(Point(Integer x, Integer y)) {
|
||||
return x + y;
|
||||
}
|
||||
|
||||
m(Point(Float x, Float y)) {
|
||||
return x * y;
|
||||
}
|
||||
|
||||
m(Integer x) {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
public class OverloadPattern {
|
||||
Integer m$Point$_$java$lang$Integer$_$java$lang$Integer$_$(Point point) {
|
||||
var x = point.x();
|
||||
var y = point.y();
|
||||
return x + y;
|
||||
}
|
||||
|
||||
Float m$Point$_$java$lang$Float$_$java$lang$Float$_$(Point point) {
|
||||
var x = point.x();
|
||||
var y = point.y();
|
||||
return x * y;
|
||||
}
|
||||
|
||||
Number m(Point point) {
|
||||
return switch(point) {
|
||||
case Point(Integer x, Integer y) ->
|
||||
m$Point$_$java$lang$Integer$_$java$lang$Integer$_$(point);
|
||||
case Point(Float x, Float y) ->
|
||||
m$Point$_$java$lang$Float$_$java$lang$Float$_$(point);
|
||||
default -> throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
Integer m(Integer x) {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
@@ -0,0 +1,22 @@
|
||||
import java.lang.Integer;
|
||||
|
||||
record Rec(Integer a, Integer b) {}
|
||||
|
||||
/*public class Rec {
|
||||
x; y;
|
||||
Rec(Integer a, Integer b) {
|
||||
x = a;
|
||||
y = b;
|
||||
}
|
||||
}*/
|
||||
|
||||
public class RecordTest {
|
||||
a = new Rec(10, 20);
|
||||
b = new Rec(10, 20);
|
||||
c = new Rec(20, 40);
|
||||
|
||||
doesEqual() { return a.equals(b); }
|
||||
doesNotEqual() { return b.equals(c); }
|
||||
hashCode() { return a.hashCode(); }
|
||||
toString() { return a.toString(); }
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import java.lang.Integer;
|
||||
|
||||
class Other {
|
||||
static field = 20;
|
||||
}
|
||||
|
||||
public class Static {
|
||||
static i = 20;
|
||||
|
||||
static {
|
||||
var x = 30;
|
||||
i = x;
|
||||
}
|
||||
|
||||
static m() {
|
||||
return i + Other.field;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import java.lang.Integer;
|
||||
import java.lang.Object;
|
||||
import java.lang.Float;
|
||||
|
||||
record Rec(Integer a, Object b) {}
|
||||
|
||||
public class Switch {
|
||||
main(o) {
|
||||
return switch (o) {
|
||||
case Rec(Integer a, Integer b) -> a + b;
|
||||
case Rec(Integer a, Float b) -> a + 10;
|
||||
case Rec(Integer a, Rec(Integer b, Integer c)) -> a + b + c;
|
||||
case Integer i -> i;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import java.lang.Integer;
|
||||
|
||||
record Point(x, y) {}
|
||||
|
||||
class Switch2 {
|
||||
m() {
|
||||
var pt = new Point(10, 20);
|
||||
return switch (pt) {
|
||||
case Point(x, y) -> 10;
|
||||
default -> 20;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import java.lang.Integer;
|
||||
import java.lang.String;
|
||||
import java.lang.Object;
|
||||
|
||||
public class SwitchString {
|
||||
main(o) {
|
||||
return switch (o) {
|
||||
case "AaAaAa" -> 1; // These two have the same hash code!
|
||||
case "AaAaBB" -> 2;
|
||||
case "test", "TEST" -> 3;
|
||||
default -> 4;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -3,16 +3,4 @@ public class Tph2 {
|
||||
id3 (x) {
|
||||
return id.apply(x);
|
||||
}
|
||||
|
||||
/*
|
||||
m(a,b){
|
||||
var c = m2(a,b);
|
||||
//m2(a,b);
|
||||
return a;
|
||||
}
|
||||
|
||||
m2(a,b){
|
||||
return b;
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package pkg.sub;
|
||||
|
||||
import java.lang.Integer;
|
||||
import pkg.sub2.Cycle2;
|
||||
|
||||
public class Cycle1 {
|
||||
test() {
|
||||
var cycle2 = new Cycle2();
|
||||
cycle2.test();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package pkg.sub;
|
||||
|
||||
import pkg.sub2.Test2;
|
||||
|
||||
public class Test1 {
|
||||
|
||||
main() {
|
||||
var t2 = new Test2();
|
||||
t2.test();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package pkg.sub2;
|
||||
|
||||
import java.lang.Integer;
|
||||
import pkg.sub.Cycle1;
|
||||
|
||||
public class Cycle2 {
|
||||
test() {
|
||||
var cycle1 = new Cycle1();
|
||||
cycle1.test();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package pkg.sub2;
|
||||
|
||||
public class Test2 {
|
||||
|
||||
test() {}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
class Instanceof {
|
||||
|
||||
Instanceof(){
|
||||
super(());
|
||||
}
|
||||
void checkInstanceof(){
|
||||
TPH a;
|
||||
a = 4;
|
||||
return a instanceof java.lang.Integer;
|
||||
}
|
||||
|
||||
void checkInstanceOfWithPattern(){
|
||||
TPH b;
|
||||
b = 4.0;
|
||||
if(b instanceof d)
|
||||
{
|
||||
return d;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Kein Double;
|
||||
};
|
||||
}
|
||||
|
||||
void checkInstanceOfWithGuardedPattern(){
|
||||
TPH obj;
|
||||
obj = test;
|
||||
TPH flag;
|
||||
if(obj instanceof s op s.length Signature: [TPH]() op 5)
|
||||
{
|
||||
flag = s.contains Signature: [TPH, TPH](jdk);
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
java.lang.Boolean equals(java.lang.Object o){
|
||||
return o instanceof other op x op other.x op y op other.y;
|
||||
}
|
||||
|
||||
Instanceof(){
|
||||
super(());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
class Point {
|
||||
|
||||
java.lang.Integer x;
|
||||
java.lang.Integer y;
|
||||
Point(java.lang.Integer x, java.lang.Integer y){
|
||||
super(());
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
java.lang.Integer x(){
|
||||
return this.x;
|
||||
}
|
||||
|
||||
java.lang.Integer y(){
|
||||
return this.y;
|
||||
}
|
||||
|
||||
Point(java.lang.Integer x, java.lang.Integer y){
|
||||
super(());
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
}class Shape {
|
||||
|
||||
}class ColoredPoint {
|
||||
|
||||
Point pt;
|
||||
java.lang.String color;
|
||||
ColoredPoint(Point pt, java.lang.String color){
|
||||
super(());
|
||||
this.pt = pt;
|
||||
this.color = color;
|
||||
}
|
||||
Point pt(){
|
||||
return this.pt;
|
||||
}
|
||||
|
||||
java.lang.String color(){
|
||||
return this.color;
|
||||
}
|
||||
|
||||
ColoredPoint(Point pt, java.lang.String color){
|
||||
super(());
|
||||
this.pt = pt;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
}class Rectangle {
|
||||
|
||||
ColoredPoint upperLeft;
|
||||
ColoredPoint lowerRight;
|
||||
Rectangle(ColoredPoint upperLeft, ColoredPoint lowerRight){
|
||||
super(());
|
||||
this.upperLeft = upperLeft;
|
||||
this.lowerRight = lowerRight;
|
||||
}
|
||||
ColoredPoint upperLeft(){
|
||||
return this.upperLeft;
|
||||
}
|
||||
|
||||
ColoredPoint lowerRight(){
|
||||
return this.lowerRight;
|
||||
}
|
||||
|
||||
Rectangle(ColoredPoint upperLeft, ColoredPoint lowerRight){
|
||||
super(());
|
||||
this.upperLeft = upperLeft;
|
||||
this.lowerRight = lowerRight;
|
||||
}
|
||||
|
||||
}class Color {
|
||||
|
||||
Color(){
|
||||
super(());
|
||||
}
|
||||
Color(){
|
||||
super(());
|
||||
}
|
||||
|
||||
}class Blue {
|
||||
|
||||
Blue(){
|
||||
super(());
|
||||
}
|
||||
Blue(){
|
||||
super(());
|
||||
}
|
||||
|
||||
}class Red {
|
||||
|
||||
Red(){
|
||||
super(());
|
||||
}
|
||||
Red(){
|
||||
super(());
|
||||
}
|
||||
|
||||
}class PatternMatching {
|
||||
|
||||
PatternMatching(){
|
||||
super(());
|
||||
}
|
||||
void printColorOfUpperLeftPoint(Shape shape){
|
||||
switch(shape){
|
||||
case Rectangle(ColoredPoint(Point pt, java.lang.String color), ColoredPoint lowerRight):
|
||||
System.out.println Signature: [TPH, TPH](x: op pt.x Signature: [TPH]() op / color: op color op / lowerRight: op lowerRight);
|
||||
|
||||
default:
|
||||
System.out.println Signature: [TPH, TPH](not a rectangle);
|
||||
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
PatternMatching(){
|
||||
super(());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
class Point {
|
||||
|
||||
TPH x;
|
||||
TPH y;
|
||||
Point(TPH x, TPH y){
|
||||
super(());
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
TPH x(){
|
||||
return this.x;
|
||||
}
|
||||
|
||||
TPH y(){
|
||||
return this.y;
|
||||
}
|
||||
|
||||
Point(TPH x, TPH y){
|
||||
super(());
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
}class Line {
|
||||
|
||||
TPH pt1;
|
||||
TPH pt2;
|
||||
Line(TPH pt1, TPH pt2){
|
||||
super(());
|
||||
this.pt1 = pt1;
|
||||
this.pt2 = pt2;
|
||||
}
|
||||
TPH pt1(){
|
||||
return this.pt1;
|
||||
}
|
||||
|
||||
TPH pt2(){
|
||||
return this.pt2;
|
||||
}
|
||||
|
||||
Line(TPH pt1, TPH pt2){
|
||||
super(());
|
||||
this.pt1 = pt1;
|
||||
this.pt2 = pt2;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
class Shape {
|
||||
|
||||
Shape(){
|
||||
super(());
|
||||
}
|
||||
Shape(){
|
||||
super(());
|
||||
}
|
||||
|
||||
}class Circle {
|
||||
|
||||
Circle(){
|
||||
super(());
|
||||
}
|
||||
Circle(){
|
||||
super(());
|
||||
}
|
||||
|
||||
}class Rectangle {
|
||||
|
||||
Rectangle(){
|
||||
super(());
|
||||
}
|
||||
Rectangle(){
|
||||
super(());
|
||||
}
|
||||
|
||||
}class TransparentRectangle {
|
||||
|
||||
TransparentRectangle(){
|
||||
super(());
|
||||
}
|
||||
TransparentRectangle(){
|
||||
super(());
|
||||
}
|
||||
|
||||
}class FilledRectangle {
|
||||
|
||||
FilledRectangle(){
|
||||
super(());
|
||||
}
|
||||
FilledRectangle(){
|
||||
super(());
|
||||
}
|
||||
|
||||
}class Square {
|
||||
|
||||
Square(){
|
||||
super(());
|
||||
}
|
||||
Square(){
|
||||
super(());
|
||||
}
|
||||
|
||||
}class WeirdShape {
|
||||
|
||||
WeirdShape(){
|
||||
super(());
|
||||
}
|
||||
WeirdShape(){
|
||||
super(());
|
||||
}
|
||||
|
||||
}class Expr {
|
||||
|
||||
}class ConstantExpr {
|
||||
|
||||
java.lang.Integer i;
|
||||
ConstantExpr(java.lang.Integer i){
|
||||
super(());
|
||||
this.i = i;
|
||||
}
|
||||
java.lang.Integer i(){
|
||||
return this.i;
|
||||
}
|
||||
|
||||
ConstantExpr(java.lang.Integer i){
|
||||
super(());
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
}class PlusExpr {
|
||||
|
||||
Expr a;
|
||||
Expr b;
|
||||
PlusExpr(Expr a, Expr b){
|
||||
super(());
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
}
|
||||
Expr a(){
|
||||
return this.a;
|
||||
}
|
||||
|
||||
Expr b(){
|
||||
return this.b;
|
||||
}
|
||||
|
||||
PlusExpr(Expr a, Expr b){
|
||||
super(());
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
}class TimesExpr {
|
||||
|
||||
Expr a;
|
||||
Expr b;
|
||||
TimesExpr(Expr a, Expr b){
|
||||
super(());
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
}
|
||||
Expr a(){
|
||||
return this.a;
|
||||
}
|
||||
|
||||
Expr b(){
|
||||
return this.b;
|
||||
}
|
||||
|
||||
TimesExpr(Expr a, Expr b){
|
||||
super(());
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
}class NegExpr {
|
||||
|
||||
Expr e;
|
||||
NegExpr(Expr e){
|
||||
super(());
|
||||
this.e = e;
|
||||
}
|
||||
Expr e(){
|
||||
return this.e;
|
||||
}
|
||||
|
||||
NegExpr(Expr e){
|
||||
super(());
|
||||
this.e = e;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
class SwitchStatement {
|
||||
|
||||
SwitchStatement(){
|
||||
super(());
|
||||
}
|
||||
TPH switchStandard(){
|
||||
str = SwitchMe;
|
||||
switch(str){
|
||||
case java.lang.String s:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
TPH switchInteger(){
|
||||
i = 5;
|
||||
switch(i){
|
||||
case java.lang.Integer j:
|
||||
case java.lang.String s:
|
||||
i = 6;
|
||||
break;
|
||||
|
||||
default:
|
||||
i = 0;
|
||||
break;
|
||||
|
||||
};
|
||||
return i op 0;
|
||||
}
|
||||
|
||||
TPH guardedPattern(){
|
||||
TPH i;
|
||||
i = 1;
|
||||
switch(i){
|
||||
case java.lang.Integer j:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
TPH recordPattern(java.lang.Object obj){
|
||||
switch(obj){
|
||||
case Coordinates(java.lang.Double lat, java.lang.Double lon):
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
SwitchStatement(){
|
||||
super(());
|
||||
}
|
||||
|
||||
}class SwitchExpression {
|
||||
|
||||
java.lang.Integer x;
|
||||
java.lang.Integer y;
|
||||
SwitchExpression(java.lang.Integer x, java.lang.Integer y){
|
||||
super(());
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
java.lang.Integer x(){
|
||||
return this.x;
|
||||
}
|
||||
|
||||
java.lang.Integer y(){
|
||||
return this.y;
|
||||
}
|
||||
|
||||
java.lang.Boolean switchStandard(TPH str){
|
||||
return switch(str){
|
||||
case java.lang.String s:
|
||||
yield true;
|
||||
|
||||
default:
|
||||
yield false;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
SwitchExpression(java.lang.Integer x, java.lang.Integer y){
|
||||
super(());
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import java.lang.Integer;
|
||||
import java.lang.Double;
|
||||
import java.lang.String;
|
||||
import java.lang.Object;
|
||||
|
||||
public class Instanceof{
|
||||
void checkInstanceof() {
|
||||
var a = 4;
|
||||
return (a instanceof java.lang.Integer);
|
||||
}
|
||||
|
||||
void checkInstanceOfWithPattern(){
|
||||
var b = 4.0;
|
||||
if(b instanceof java.lang.Double d){
|
||||
return d;
|
||||
}else{
|
||||
return "Kein Double";
|
||||
}
|
||||
}
|
||||
|
||||
void checkInstanceOfWithGuardedPattern(){
|
||||
var obj = "test";
|
||||
var flag;
|
||||
if (obj instanceof String s && s.length() > 5) {
|
||||
flag = s.contains("jdk");
|
||||
}
|
||||
}
|
||||
|
||||
record Point(int x, int y){ }
|
||||
|
||||
boolean equals(Object o) {
|
||||
return (o instanceof Point other)
|
||||
&& x == other.x
|
||||
&& y == other.y;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import java.lang.String;
|
||||
|
||||
record Point(int x, int y) {}
|
||||
interface Shape {}
|
||||
record ColoredPoint(Point pt, String color) {}
|
||||
record Rectangle(ColoredPoint upperLeft, ColoredPoint lowerRight) implements Shape {}
|
||||
sealed class Color permits Blue, Red {}
|
||||
class Blue extends Color {}
|
||||
class Red extends Color {}
|
||||
|
||||
class PatternMatching {
|
||||
void printColorOfUpperLeftPoint(Shape shape)
|
||||
{
|
||||
switch (shape) {
|
||||
case Rectangle(ColoredPoint(Point pt, String color), ColoredPoint lowerRight) -> System.out.println("x: " + pt.x() + " / color: " + color + " / lowerRight: " + lowerRight);
|
||||
default -> System.out.println("not a rectangle");
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
// Simple records
|
||||
record Point(x, y){ }
|
||||
|
||||
//Combination of records
|
||||
record Line(pt1, pt2){}
|
||||
@@ -0,0 +1,21 @@
|
||||
public abstract sealed class Shape
|
||||
permits Circle, Rectangle, Square, WeirdShape { }
|
||||
|
||||
public final class Circle extends Shape { }
|
||||
|
||||
public sealed class Rectangle extends Shape
|
||||
permits TransparentRectangle, FilledRectangle { }
|
||||
public final class TransparentRectangle extends Rectangle { }
|
||||
public final class FilledRectangle extends Rectangle { }
|
||||
|
||||
public final class Square extends Shape { }
|
||||
|
||||
public non-sealed class WeirdShape extends Shape { }
|
||||
|
||||
public sealed interface Expr
|
||||
permits ConstantExpr, PlusExpr, TimesExpr, NegExpr { }
|
||||
|
||||
public record ConstantExpr(int i) implements Expr { }
|
||||
public record PlusExpr(Expr a, Expr b) implements Expr { }
|
||||
public record TimesExpr(Expr a, Expr b) implements Expr { }
|
||||
public record NegExpr(Expr e) implements Expr { }
|
||||
@@ -0,0 +1,52 @@
|
||||
import java.lang.Integer;
|
||||
import java.lang.Boolean;
|
||||
import java.lang.String;
|
||||
import java.lang.Object;
|
||||
|
||||
class SwitchStatement {
|
||||
|
||||
switchStandard(){
|
||||
str = "SwitchMe";
|
||||
switch(str){
|
||||
case String s: return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
switchInteger(){
|
||||
i = 5;
|
||||
switch(i){
|
||||
case Integer j:
|
||||
case String s: i = 6; break;
|
||||
default: i = 0; break;
|
||||
}
|
||||
return (i==0);
|
||||
}
|
||||
|
||||
guardedPattern(){
|
||||
var i = 1;
|
||||
switch(i){
|
||||
case Integer j && j == 1: return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
record Coordinates(double x, double y) {}
|
||||
|
||||
recordPattern(Object obj){
|
||||
switch(obj){
|
||||
case Coordinates(double lat, double lon): return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
record SwitchExpression(int x, int y){
|
||||
|
||||
boolean switchStandard(str){
|
||||
return switch(str){
|
||||
case String s -> yield true;
|
||||
default -> yield false;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -165,7 +165,7 @@ methodBody
|
||||
;
|
||||
|
||||
refType
|
||||
: typeType # reftype
|
||||
: typeType # refType2
|
||||
| VOID # refvoid
|
||||
;
|
||||
|
||||
@@ -199,11 +199,7 @@ interfaceMemberDeclaration
|
||||
: constDeclaration # interfaceconst
|
||||
| interfaceMethodDeclaration # interfacemethod
|
||||
| genericInterfaceMethodDeclaration # genericinterfacemethod
|
||||
| interfaceDeclaration # subinterface
|
||||
| annotationTypeDeclaration # interfaceannotationtype
|
||||
| classDeclaration # interfaceclass
|
||||
| enumDeclaration # interfaceenum
|
||||
| recordDeclaration # interfacerecord // Java17
|
||||
| classOrInterface # subclassorinterface
|
||||
;
|
||||
|
||||
constDeclaration
|
||||
@@ -308,6 +304,7 @@ formalParameterList
|
||||
|
||||
formalParameter
|
||||
: variableModifier* typeType? variableDeclaratorId
|
||||
| pattern // Pattern matching for Methods
|
||||
;
|
||||
|
||||
lastFormalParameter
|
||||
@@ -391,11 +388,7 @@ annotationTypeElementDeclaration
|
||||
|
||||
annotationTypeElementRest
|
||||
: typeType annotationMethodOrConstantRest ';'
|
||||
| classDeclaration ';'?
|
||||
| interfaceDeclaration ';'?
|
||||
| enumDeclaration ';'?
|
||||
| annotationTypeDeclaration ';'?
|
||||
| recordDeclaration ';'? // Java17
|
||||
| classOrInterface ';'?
|
||||
;
|
||||
|
||||
annotationMethodOrConstantRest
|
||||
@@ -538,7 +531,6 @@ statement
|
||||
| YIELD expression ';' #yieldstmt // Java17
|
||||
| SEMI #semistmt
|
||||
| statementExpression=expression ';' #stmtexpression
|
||||
| switchExpression ';'? #switchexpressionstmt // Java17
|
||||
| identifierLabel=identifier ':' statement #labeledstmt
|
||||
;
|
||||
|
||||
@@ -575,8 +567,10 @@ switchBlockStatementGroup
|
||||
;
|
||||
|
||||
switchLabel
|
||||
: CASE (constantExpression=expression | enumConstantName=IDENTIFIER | pattern) ':'
|
||||
| DEFAULT ':'
|
||||
: CASE constantExpression=expression ':' #switchLabelConst
|
||||
| CASE enumConstantName=IDENTIFIER ':' #switchLabelEnum
|
||||
| CASE pattern ':' #switchLabelPattern
|
||||
| DEFAULT ':' #switchLabelDefault
|
||||
;
|
||||
|
||||
forControl
|
||||
@@ -610,7 +604,7 @@ methodCall
|
||||
;
|
||||
|
||||
expression
|
||||
: primary #primaryexpression
|
||||
: primary #primaryExpression2
|
||||
| expression bop='.'
|
||||
(
|
||||
identifier
|
||||
@@ -641,8 +635,8 @@ expression
|
||||
| <assoc=right> expression
|
||||
bop=('=' | '+=' | '-=' | '*=' | '/=' | '&=' | '|=' | '^=' | '>>=' | '>>>=' | '<<=' | '%=')
|
||||
expression #assignexpression
|
||||
| lambdaExpression #lambdaexpression // Java8
|
||||
| switchExpression #switchexpression // Java17
|
||||
| lambdaExpression #lambdaExpression2 // Java8
|
||||
| switchExpression #switchExpression2 // Java17
|
||||
|
||||
// Java 8 methodReference
|
||||
| expression '::' typeArguments? identifier #methodreferenceexpression
|
||||
@@ -652,14 +646,14 @@ expression
|
||||
|
||||
// Java17
|
||||
pattern
|
||||
: primaryPattern
|
||||
| guardedPattern
|
||||
: primaryPattern #pPattern
|
||||
| guardedPattern #gPattern
|
||||
;
|
||||
|
||||
primaryPattern
|
||||
: typePattern
|
||||
| recordPattern
|
||||
| '(' pattern ')'
|
||||
: typePattern #tPattern
|
||||
| recordPattern #rPattern
|
||||
| '(' pattern ')' #enclosedPattern
|
||||
;
|
||||
|
||||
recordPattern
|
||||
@@ -667,13 +661,18 @@ recordPattern
|
||||
;
|
||||
|
||||
typePattern
|
||||
: variableModifier* typeType? identifier
|
||||
: variableModifier* typeType identifier
|
||||
;
|
||||
|
||||
recordStructurePattern
|
||||
: '(' recordComponentPatternList? ')'
|
||||
;
|
||||
|
||||
recordComponentPatternElement
|
||||
: pattern
|
||||
| identifier
|
||||
;
|
||||
|
||||
recordComponentPatternList
|
||||
: pattern (',' pattern)*
|
||||
;
|
||||
@@ -714,20 +713,25 @@ switchExpression
|
||||
|
||||
// Java17
|
||||
switchLabeledRule
|
||||
: CASE (expressionList | NULL_LITERAL | pattern) (ARROW | COLON) switchRuleOutcome
|
||||
| DEFAULT (ARROW | COLON) switchRuleOutcome
|
||||
: switchLabelCase switchRuleOutcome
|
||||
;
|
||||
|
||||
// Java17
|
||||
switchLabelCase
|
||||
: CASE expressionList (ARROW | COLON) #labeledRuleExprList
|
||||
| CASE NULL_LITERAL (ARROW | COLON) #labeledRuleNull
|
||||
| CASE pattern (ARROW | COLON) #labeledRulePattern
|
||||
| DEFAULT (ARROW | COLON) #labeledRuleDefault
|
||||
;
|
||||
|
||||
// Java20
|
||||
guardedPattern
|
||||
: variableModifier* typeType? annotation* identifier ('&&' expression)*
|
||||
| guardedPattern '&&' expression
|
||||
: primaryPattern WITH expression
|
||||
;
|
||||
|
||||
// Java17
|
||||
switchRuleOutcome
|
||||
: block
|
||||
| blockStatement*
|
||||
| expression ';'
|
||||
;
|
||||
|
||||
classType
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
package de.dhbwstuttgart.bytecode;
|
||||
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||
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.lang.invoke.*;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.*;
|
||||
|
||||
import static org.objectweb.asm.Opcodes.*;
|
||||
@@ -16,16 +19,23 @@ 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 TargetStructure clazz;
|
||||
private final ClassWriter cw;
|
||||
public final String className;
|
||||
private int lambdaCounter = 0;
|
||||
private final HashMap<TargetLambdaExpression, TargetMethod> lambdas = new HashMap<>();
|
||||
private final JavaTXCompiler compiler;
|
||||
|
||||
public Codegen(TargetClass clazz) {
|
||||
public Codegen(TargetStructure clazz, JavaTXCompiler compiler) {
|
||||
this.clazz = clazz;
|
||||
this.className = clazz.qualifiedName();
|
||||
this.cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
|
||||
this.className = clazz.qualifiedName().getClassName();
|
||||
this.cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS) {
|
||||
@Override
|
||||
protected ClassLoader getClassLoader() {
|
||||
return compiler.getClassLoader();
|
||||
}
|
||||
};
|
||||
this.compiler = compiler;
|
||||
}
|
||||
|
||||
private record LocalVar(int index, String name, TargetType type) {
|
||||
@@ -55,11 +65,22 @@ public class Codegen {
|
||||
}
|
||||
}
|
||||
|
||||
private static class BreakEnv {
|
||||
String labelName; // TODO This is for labeled statements (Not implemented)
|
||||
Label startLabel;
|
||||
Label endLabel;
|
||||
}
|
||||
|
||||
private static class State {
|
||||
Scope scope = new Scope(null);
|
||||
int localCounter;
|
||||
MethodVisitor mv;
|
||||
TargetType returnType;
|
||||
// This is used to remember the type from lambda expressions
|
||||
TargetType contextType;
|
||||
|
||||
Stack<BreakEnv> breakStack = new Stack<>();
|
||||
Stack<Integer> switchResultValue = new Stack<>();
|
||||
|
||||
State(TargetType returnType, MethodVisitor mv, int localCounter) {
|
||||
this.returnType = returnType;
|
||||
@@ -81,6 +102,13 @@ public class Codegen {
|
||||
localCounter += 1;
|
||||
return local;
|
||||
}
|
||||
|
||||
void pushSwitch() {
|
||||
switchResultValue.push(this.localCounter++);
|
||||
}
|
||||
void popSwitch() {
|
||||
switchResultValue.pop();
|
||||
}
|
||||
}
|
||||
|
||||
private void popValue(State state, TargetType type) {
|
||||
@@ -282,7 +310,7 @@ public class Codegen {
|
||||
} else if (type.equals(TargetType.Double)) {
|
||||
mv.visitInsn(DADD);
|
||||
} else {
|
||||
throw new CodeGenException("Invalid argument to Add expression");
|
||||
throw new CodeGenException("Invalid argument to Add expression, type: " + add.type());
|
||||
}
|
||||
}
|
||||
if (add.type().equals(TargetType.String)) {
|
||||
@@ -432,6 +460,10 @@ public class Codegen {
|
||||
mv.visitInsn(IXOR);
|
||||
break;
|
||||
}
|
||||
case Instof instof: {
|
||||
// TODO
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
case Shl shl: {
|
||||
generate(state, shl.left());
|
||||
convertTo(state, shl.left().type(), op.type());
|
||||
@@ -547,6 +579,9 @@ public class Codegen {
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -564,11 +599,10 @@ public class Codegen {
|
||||
private void generateUnaryOp(State state, TargetUnaryOp op) {
|
||||
var mv = state.mv;
|
||||
switch (op) {
|
||||
case TargetUnaryOp.Add add:
|
||||
case TargetUnaryOp.Add add ->
|
||||
// This literally does nothing
|
||||
generate(state, add.expr());
|
||||
break;
|
||||
case TargetUnaryOp.Negate negate:
|
||||
case TargetUnaryOp.Negate negate -> {
|
||||
generate(state, negate.expr());
|
||||
if (negate.type().equals(TargetType.Double))
|
||||
mv.visitInsn(DNEG);
|
||||
@@ -578,8 +612,8 @@ public class Codegen {
|
||||
mv.visitInsn(LNEG);
|
||||
else
|
||||
mv.visitInsn(INEG);
|
||||
break;
|
||||
case TargetUnaryOp.Not not:
|
||||
}
|
||||
case TargetUnaryOp.Not not -> {
|
||||
generate(state, not.expr());
|
||||
if (not.type().equals(TargetType.Long)) {
|
||||
mv.visitLdcInsn(-1L);
|
||||
@@ -588,8 +622,8 @@ public class Codegen {
|
||||
mv.visitInsn(ICONST_M1);
|
||||
mv.visitInsn(IXOR);
|
||||
}
|
||||
break;
|
||||
case TargetUnaryOp.PreIncrement preIncrement:
|
||||
}
|
||||
case TargetUnaryOp.PreIncrement preIncrement -> {
|
||||
generate(state, preIncrement.expr());
|
||||
if (preIncrement.type().equals(TargetType.Float)) {
|
||||
mv.visitLdcInsn(1F);
|
||||
@@ -610,8 +644,8 @@ public class Codegen {
|
||||
}
|
||||
boxPrimitive(state, preIncrement.type());
|
||||
afterIncDec(state, preIncrement);
|
||||
break;
|
||||
case TargetUnaryOp.PreDecrement preDecrement:
|
||||
}
|
||||
case TargetUnaryOp.PreDecrement preDecrement -> {
|
||||
generate(state, preDecrement.expr());
|
||||
if (preDecrement.type().equals(TargetType.Float)) {
|
||||
mv.visitLdcInsn(1F);
|
||||
@@ -632,8 +666,8 @@ public class Codegen {
|
||||
}
|
||||
boxPrimitive(state, preDecrement.type());
|
||||
afterIncDec(state, preDecrement);
|
||||
break;
|
||||
case TargetUnaryOp.PostIncrement postIncrement:
|
||||
}
|
||||
case TargetUnaryOp.PostIncrement postIncrement -> {
|
||||
generate(state, postIncrement.expr());
|
||||
if (postIncrement.type().equals(TargetType.Float)) {
|
||||
mv.visitInsn(DUP);
|
||||
@@ -654,8 +688,8 @@ public class Codegen {
|
||||
}
|
||||
boxPrimitive(state, postIncrement.type());
|
||||
afterIncDec(state, postIncrement);
|
||||
break;
|
||||
case TargetUnaryOp.PostDecrement postDecrement:
|
||||
}
|
||||
case TargetUnaryOp.PostDecrement postDecrement -> {
|
||||
generate(state, postDecrement.expr());
|
||||
if (postDecrement.type().equals(TargetType.Float)) {
|
||||
mv.visitInsn(DUP);
|
||||
@@ -676,7 +710,7 @@ public class Codegen {
|
||||
}
|
||||
boxPrimitive(state, postDecrement.type());
|
||||
afterIncDec(state, postDecrement);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -689,7 +723,7 @@ public class Codegen {
|
||||
} else {
|
||||
var name = "lambda$" + lambdaCounter++;
|
||||
var parameters = new ArrayList<>(lambda.captures());
|
||||
parameters.addAll(lambda.params().stream().map(param -> param.type() instanceof TargetGenericType ? new MethodParameter(TargetType.Object, param.name()) : param).toList());
|
||||
parameters.addAll(lambda.params().stream().map(param -> param.pattern().type() instanceof TargetGenericType ? param.withType(TargetType.Object) : param).toList());
|
||||
|
||||
impl = new TargetMethod(0, name, lambda.block(), new TargetMethod.Signature(Set.of(), parameters, lambda.returnType() instanceof TargetGenericType ? TargetType.Object : lambda.returnType()), null);
|
||||
generateMethod(impl);
|
||||
@@ -712,15 +746,22 @@ public class Codegen {
|
||||
desugared += "V";
|
||||
|
||||
var params = new ArrayList<TargetType>();
|
||||
params.add(new TargetRefType(clazz.qualifiedName()));
|
||||
params.addAll(lambda.captures().stream().map(MethodParameter::type).toList());
|
||||
params.add(new TargetRefType(clazz.qualifiedName().getClassName()));
|
||||
params.addAll(lambda.captures().stream().map(mp -> mp.pattern().type()).toList());
|
||||
|
||||
var descriptor = TargetMethod.getDescriptor(lambda.type(), params.toArray(TargetType[]::new));
|
||||
var descriptor = TargetMethod.getDescriptor(state.contextType, params.toArray(TargetType[]::new));
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
for (var capture : lambda.captures())
|
||||
mv.visitVarInsn(ALOAD, state.scope.get(capture.name()).index);
|
||||
for (var capture : lambda.captures()) {
|
||||
var pattern = (TargetTypePattern) capture.pattern();
|
||||
mv.visitVarInsn(ALOAD, state.scope.get(pattern.name()).index);
|
||||
}
|
||||
|
||||
mv.visitInvokeDynamicInsn("apply", descriptor, bootstrap, Type.getType(desugared), handle, Type.getType(TargetMethod.getDescriptor(impl.signature().returnType(), lambda.params().stream().map(MethodParameter::type).toArray(TargetType[]::new))));
|
||||
String methodName;
|
||||
var intf = compiler.getClass(new JavaClassName(state.contextType.name()));
|
||||
if (intf == null) methodName = "apply"; // TODO Weird fallback logic here
|
||||
else methodName = intf.getMethods().stream().filter(m -> Modifier.isAbstract(m.modifier)).findFirst().orElseThrow().getName();
|
||||
|
||||
mv.visitInvokeDynamicInsn(methodName, descriptor, bootstrap, Type.getType(desugared), handle, Type.getType(TargetMethod.getDescriptor(impl.signature().returnType(), lambda.params().stream().map(mp -> mp.pattern().type()).toArray(TargetType[]::new))));
|
||||
}
|
||||
|
||||
private void generate(State state, TargetExpression expr) {
|
||||
@@ -747,39 +788,30 @@ public class Codegen {
|
||||
break;
|
||||
}
|
||||
case TargetCast cast:
|
||||
var ctx = state.contextType;
|
||||
state.contextType = cast.type();
|
||||
generate(state, cast.expr());
|
||||
state.contextType = ctx;
|
||||
convertTo(state, cast.expr().type(), cast.type());
|
||||
break;
|
||||
case TargetInstanceOf instanceOf:
|
||||
mv.visitTypeInsn(INSTANCEOF, instanceOf.right().getInternalName());
|
||||
generateInstanceOf(state, instanceOf);
|
||||
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:
|
||||
case IntLiteral intLiteral -> mv.visitLdcInsn(intLiteral.value());
|
||||
case FloatLiteral floatLiteral -> mv.visitLdcInsn(floatLiteral.value());
|
||||
case LongLiteral longLiteral -> mv.visitLdcInsn(longLiteral.value());
|
||||
case StringLiteral stringLiteral -> mv.visitLdcInsn(stringLiteral.value());
|
||||
case CharLiteral charLiteral -> mv.visitIntInsn(BIPUSH, charLiteral.value());
|
||||
case DoubleLiteral doubleLiteral -> mv.visitLdcInsn(doubleLiteral.value());
|
||||
case BooleanLiteral booleanLiteral -> {
|
||||
if (booleanLiteral.value()) {
|
||||
mv.visitInsn(ICONST_1);
|
||||
} else {
|
||||
mv.visitInsn(ICONST_0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TargetVarDecl varDecl: {
|
||||
@@ -802,19 +834,28 @@ public class Codegen {
|
||||
break;
|
||||
case TargetAssign assign: {
|
||||
switch (assign.left()) {
|
||||
case TargetLocalVar localVar: {
|
||||
case TargetLocalVar localVar -> {
|
||||
var ctype = state.contextType;
|
||||
state.contextType = localVar.type();
|
||||
generate(state, assign.right());
|
||||
state.contextType = ctype;
|
||||
|
||||
convertTo(state, assign.right().type(), localVar.type());
|
||||
boxPrimitive(state, localVar.type());
|
||||
var local = state.scope.get(localVar.name());
|
||||
mv.visitInsn(DUP);
|
||||
mv.visitVarInsn(ASTORE, local.index());
|
||||
break;
|
||||
}
|
||||
case TargetFieldVar dot: {
|
||||
case TargetFieldVar dot -> {
|
||||
var fieldType = dot.type();
|
||||
if (!(dot.left() instanceof TargetThis && dot.isStatic()))
|
||||
generate(state, dot.left());
|
||||
|
||||
var ctype = state.contextType;
|
||||
state.contextType = fieldType;
|
||||
generate(state, assign.right());
|
||||
state.contextType = ctype;
|
||||
|
||||
convertTo(state, assign.right().type(), fieldType);
|
||||
boxPrimitive(state, fieldType);
|
||||
if (dot.isStatic())
|
||||
@@ -822,10 +863,8 @@ public class Codegen {
|
||||
else
|
||||
mv.visitInsn(DUP_X1);
|
||||
mv.visitFieldInsn(dot.isStatic() ? PUTSTATIC : PUTFIELD, dot.owner().getInternalName(), dot.right(), fieldType.toSignature());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new CodeGenException("Invalid assignment");
|
||||
default -> throw new CodeGenException("Invalid assignment");
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -846,7 +885,8 @@ public class Codegen {
|
||||
state.enterScope();
|
||||
var localCounter = state.localCounter;
|
||||
if (_for.init() != null)
|
||||
generate(state, _for.init());
|
||||
_for.init().forEach(e -> generate(state, e));
|
||||
|
||||
Label start = new Label();
|
||||
Label end = new Label();
|
||||
mv.visitLabel(start);
|
||||
@@ -855,12 +895,22 @@ public class Codegen {
|
||||
else
|
||||
mv.visitInsn(ICONST_1);
|
||||
mv.visitJumpInsn(IFEQ, end);
|
||||
|
||||
var env = new BreakEnv();
|
||||
env.startLabel = start;
|
||||
env.endLabel = end;
|
||||
|
||||
state.breakStack.push(env);
|
||||
generate(state, _for.body());
|
||||
state.breakStack.pop();
|
||||
|
||||
if (_for.increment() != null) {
|
||||
generate(state, _for.increment());
|
||||
if (_for.increment().type() != null) {
|
||||
popValue(state, _for.increment().type());
|
||||
_for.increment().forEach(e -> {
|
||||
generate(state, e);
|
||||
if (e.type() != null) {
|
||||
popValue(state, e.type());
|
||||
}
|
||||
});
|
||||
}
|
||||
mv.visitJumpInsn(GOTO, start);
|
||||
mv.visitLabel(end);
|
||||
@@ -874,7 +924,15 @@ public class Codegen {
|
||||
mv.visitLabel(start);
|
||||
generate(state, _while.cond());
|
||||
mv.visitJumpInsn(IFEQ, end);
|
||||
|
||||
var env = new BreakEnv();
|
||||
env.startLabel = start;
|
||||
env.endLabel = end;
|
||||
|
||||
state.breakStack.push(env);
|
||||
generate(state, _while.body());
|
||||
state.breakStack.pop();
|
||||
|
||||
mv.visitJumpInsn(GOTO, start);
|
||||
mv.visitLabel(end);
|
||||
break;
|
||||
@@ -895,7 +953,10 @@ public class Codegen {
|
||||
}
|
||||
case TargetReturn ret: {
|
||||
if (ret.expression() != null && state.returnType != null) {
|
||||
var ctype = state.contextType;
|
||||
state.contextType = state.returnType;
|
||||
generate(state, ret.expression());
|
||||
state.contextType = ctype;
|
||||
convertTo(state, ret.expression().type(), state.returnType);
|
||||
boxPrimitive(state, state.returnType);
|
||||
mv.visitInsn(ARETURN);
|
||||
@@ -903,6 +964,32 @@ public class Codegen {
|
||||
mv.visitInsn(RETURN);
|
||||
break;
|
||||
}
|
||||
case TargetYield yield: {
|
||||
generate(state, yield.expression());
|
||||
try {
|
||||
yieldValue(state, yield.expression().type());
|
||||
mv.visitJumpInsn(GOTO, state.breakStack.peek().endLabel);
|
||||
} catch (EmptyStackException e) {
|
||||
throw new CodeGenException("Yield outside of switch expression");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TargetSwitch _switch: {
|
||||
generateSwitch(state, _switch);
|
||||
break;
|
||||
}
|
||||
case TargetBreak brk: {
|
||||
if (state.breakStack.isEmpty()) throw new CodeGenException("Break outside of switch or loop");
|
||||
mv.visitJumpInsn(GOTO, state.breakStack.peek().endLabel);
|
||||
break;
|
||||
}
|
||||
case TargetContinue cnt: {
|
||||
if (state.breakStack.isEmpty()) throw new CodeGenException("Continue outside of loop");
|
||||
var env = state.breakStack.peek();
|
||||
if (env.startLabel == null) throw new CodeGenException("Continue outside of loop");
|
||||
mv.visitJumpInsn(GOTO, env.startLabel);
|
||||
break;
|
||||
}
|
||||
case TargetThis _this: {
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
break;
|
||||
@@ -916,9 +1003,12 @@ public class Codegen {
|
||||
for (var i = 0; i < call.args().size(); i++) {
|
||||
var e = call.args().get(i);
|
||||
var arg = call.parameterTypes().get(i);
|
||||
var ctype = state.contextType;
|
||||
state.contextType = arg;
|
||||
generate(state, e);
|
||||
if (!(arg instanceof TargetPrimitiveType))
|
||||
boxPrimitive(state, e.type());
|
||||
state.contextType = ctype;
|
||||
}
|
||||
var descriptor = call.getDescriptor();
|
||||
if (call.owner() instanceof TargetFunNType) // Decay FunN
|
||||
@@ -951,8 +1041,294 @@ public class Codegen {
|
||||
}
|
||||
}
|
||||
|
||||
private void generateInstanceOf(State state, TargetInstanceOf instanceOf) {
|
||||
var mv = state.mv;
|
||||
|
||||
if (instanceOf.right() instanceof TargetTypePattern right && right.name() == null) {
|
||||
mv.visitTypeInsn(INSTANCEOF, right.type().getInternalName());
|
||||
return;
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private void yieldValue(State state, TargetType type) {
|
||||
boxPrimitive(state, type);
|
||||
state.mv.visitVarInsn(ASTORE, state.switchResultValue.peek());
|
||||
}
|
||||
|
||||
private void generateClassicSwitch(State state, TargetSwitch aSwitch) {
|
||||
// TODO Constant expressions are allowed, we need to evaluate them somehow...
|
||||
// For now we just assume we get literals...
|
||||
// TODO This always uses a lookupswitch, a tableswitch may be faster in some cases but we can't generate that every time
|
||||
// TODO We can't switch on Strings yet, the idea for this (like javac does it) would be to implement the hash code at compile time
|
||||
// and switch based on that, adding an equals check for every case and going to yet another tableswitch which finally decides which branch to take
|
||||
var mv = state.mv;
|
||||
if (aSwitch.isExpression())
|
||||
state.pushSwitch();
|
||||
|
||||
generate(state, aSwitch.expr());
|
||||
|
||||
state.enterScope();
|
||||
|
||||
var keys = new int[aSwitch.cases().stream().mapToInt(c -> c.labels().size()).sum()];
|
||||
var labels = new Label[keys.length];
|
||||
var bodyLabels = new Label[aSwitch.cases().size()];
|
||||
|
||||
var end = new Label();
|
||||
var env = new BreakEnv();
|
||||
env.endLabel = end;
|
||||
state.breakStack.push(env);
|
||||
|
||||
var i = 0;
|
||||
var j = 0;
|
||||
for (var case_ : aSwitch.cases()) {
|
||||
bodyLabels[j] = new Label();
|
||||
for (var label : case_.labels()) {
|
||||
if (!(label instanceof TargetLiteral literal))
|
||||
throw new CodeGenException("Labels may only be constants for now");
|
||||
keys[i] = (int) literal.value();
|
||||
labels[i] = bodyLabels[j];
|
||||
i += 1;
|
||||
}
|
||||
j += 1;
|
||||
}
|
||||
|
||||
var defaultLabel = end;
|
||||
if (aSwitch.default_() != null) {
|
||||
defaultLabel = new Label();
|
||||
}
|
||||
|
||||
mv.visitLookupSwitchInsn(defaultLabel, keys, labels);
|
||||
|
||||
for (var k = 0; k < aSwitch.cases().size(); k++) {
|
||||
mv.visitLabel(bodyLabels[k]);
|
||||
var cse = aSwitch.cases().get(k);
|
||||
generate(state, cse.body());
|
||||
if (cse.isSingleExpression() && aSwitch.isExpression())
|
||||
yieldValue(state, cse.body().statements().get(0).type());
|
||||
if (aSwitch.isExpression()) mv.visitJumpInsn(GOTO, end);
|
||||
}
|
||||
|
||||
if (aSwitch.default_() != null) {
|
||||
mv.visitLabel(defaultLabel);
|
||||
generate(state, aSwitch.default_().body());
|
||||
if (aSwitch.default_().isSingleExpression() && aSwitch.isExpression())
|
||||
yieldValue(state, aSwitch.default_().body().statements().get(0).type());
|
||||
}
|
||||
|
||||
mv.visitLabel(end);
|
||||
state.breakStack.pop();
|
||||
|
||||
if (aSwitch.isExpression()) {
|
||||
mv.visitVarInsn(ALOAD, state.switchResultValue.peek());
|
||||
unboxPrimitive(state, aSwitch.type());
|
||||
state.popSwitch();
|
||||
}
|
||||
|
||||
state.exitScope();
|
||||
}
|
||||
|
||||
private void generateEnhancedSwitch(State state, TargetSwitch aSwitch) {
|
||||
var mv = state.mv;
|
||||
generate(state, aSwitch.expr());
|
||||
var tmp = state.localCounter;
|
||||
mv.visitInsn(DUP);
|
||||
mv.visitVarInsn(ASTORE, tmp);
|
||||
|
||||
state.enterScope();
|
||||
// This is the index to start the switch from
|
||||
mv.visitInsn(ICONST_0);
|
||||
if (aSwitch.isExpression())
|
||||
state.pushSwitch();
|
||||
|
||||
// To be able to skip ahead to the next case
|
||||
var start = new Label();
|
||||
mv.visitLabel(start);
|
||||
|
||||
var end = new Label();
|
||||
var env = new BreakEnv();
|
||||
env.endLabel = end;
|
||||
state.breakStack.push(env);
|
||||
|
||||
var mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, Object[].class);
|
||||
var bootstrap = new Handle(H_INVOKESTATIC, "java/lang/runtime/SwitchBootstraps", "typeSwitch", mt.toMethodDescriptorString(), false);
|
||||
|
||||
var types = new ArrayList<Object>(aSwitch.cases().size());
|
||||
for (var cse : aSwitch.cases()) for (var label : cse.labels()) {
|
||||
if (label instanceof TargetTypePattern || label instanceof TargetComplexPattern)
|
||||
types.add(Type.getObjectType(label.type().getInternalName()));
|
||||
else if (label instanceof TargetLiteral lit)
|
||||
types.add(lit.value());
|
||||
else if (label instanceof TargetGuard guard)
|
||||
types.add(Type.getObjectType(guard.inner().type().getInternalName()));
|
||||
// TODO Same here we need to evaluate constant;
|
||||
else {
|
||||
System.out.println(label);
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
mv.visitInvokeDynamicInsn("typeSwitch", "(Ljava/lang/Object;I)I", bootstrap, types.toArray());
|
||||
|
||||
var caseLabels = new Label[aSwitch.cases().size()];
|
||||
var labels = new Label[aSwitch.cases().stream().mapToInt(c -> c.labels().size()).sum()];
|
||||
var j = 0;
|
||||
for (var i = 0; i < caseLabels.length; i++) {
|
||||
var cse = aSwitch.cases().get(i);
|
||||
var label = new Label();
|
||||
caseLabels[i] = label;
|
||||
for (var k = 0; k < cse.labels().size(); k++) {
|
||||
labels[j] = label;
|
||||
j += 1;
|
||||
}
|
||||
}
|
||||
|
||||
var defaultLabel = end;
|
||||
if (aSwitch.default_() != null) {
|
||||
defaultLabel = new Label();
|
||||
}
|
||||
|
||||
mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels);
|
||||
|
||||
for (var i = 0; i < aSwitch.cases().size(); i++) {
|
||||
mv.visitLabel(caseLabels[i]);
|
||||
var cse = aSwitch.cases().get(i);
|
||||
|
||||
if (cse.labels().size() == 1) {
|
||||
var label = cse.labels().get(0);
|
||||
if (label instanceof TargetGuard gd) {
|
||||
state.mv.visitVarInsn(ALOAD, tmp);
|
||||
bindPattern(state, aSwitch.expr().type(), gd.inner(), start, i, 1);
|
||||
} else if (label instanceof TargetPattern pat) {
|
||||
state.mv.visitVarInsn(ALOAD, tmp);
|
||||
bindPattern(state, aSwitch.expr().type(), pat, start, i, 1);
|
||||
}
|
||||
|
||||
if (label instanceof TargetGuard gd) {
|
||||
generate(state, gd.expression());
|
||||
var next = new Label();
|
||||
mv.visitJumpInsn(IFNE, next);
|
||||
mv.visitVarInsn(ALOAD, tmp);
|
||||
// Push the offset onto the stack (this is used by the invokedynamic call)
|
||||
mv.visitLdcInsn(i + 1);
|
||||
mv.visitJumpInsn(GOTO, start);
|
||||
mv.visitLabel(next);
|
||||
}
|
||||
}
|
||||
|
||||
generate(state, cse.body());
|
||||
if (cse.isSingleExpression() && aSwitch.isExpression())
|
||||
yieldValue(state, cse.body().statements().get(0).type());
|
||||
if (aSwitch.isExpression()) mv.visitJumpInsn(GOTO, end);
|
||||
}
|
||||
|
||||
if (aSwitch.default_() != null) {
|
||||
mv.visitLabel(defaultLabel);
|
||||
generate(state, aSwitch.default_().body());
|
||||
if (aSwitch.default_().isSingleExpression() && aSwitch.isExpression())
|
||||
yieldValue(state, aSwitch.default_().body().statements().get(0).type());
|
||||
}
|
||||
|
||||
mv.visitLabel(end);
|
||||
//mv.visitInsn(POP);
|
||||
|
||||
state.breakStack.pop();
|
||||
if (aSwitch.isExpression()) {
|
||||
mv.visitVarInsn(ALOAD, state.switchResultValue.peek());
|
||||
unboxPrimitive(state, aSwitch.type());
|
||||
state.popSwitch();
|
||||
}
|
||||
|
||||
state.exitScope();
|
||||
}
|
||||
|
||||
private void extractField(State state, TargetType type, int i, ClassOrInterface clazz) {
|
||||
if (i >= clazz.getFieldDecl().size())
|
||||
throw new CodeGenException("Couldn't find suitable field accessor for '" + type.name() + "'");
|
||||
var field = clazz.getFieldDecl().get(i);
|
||||
var fieldType = new TargetRefType(((RefType) field.getType()).getName().toString());
|
||||
state.mv.visitMethodInsn(INVOKEVIRTUAL, type.getInternalName(), field.getName(), "()" + fieldType.toDescriptor(), false);
|
||||
}
|
||||
|
||||
private void bindPattern(State state, TargetType type, TargetPattern pat, Label start, int index, int depth) {
|
||||
if (pat.type() instanceof TargetPrimitiveType)
|
||||
boxPrimitive(state, pat.type());
|
||||
|
||||
state.mv.visitInsn(DUP);
|
||||
state.mv.visitTypeInsn(INSTANCEOF, pat.type().getInternalName());
|
||||
|
||||
var cont = new Label();
|
||||
state.mv.visitJumpInsn(IFNE, cont);
|
||||
for (var i = 0; i < depth; i++) {
|
||||
state.mv.visitInsn(POP);
|
||||
}
|
||||
state.mv.visitVarInsn(ALOAD, state.switchResultValue.peek());
|
||||
state.mv.visitLdcInsn(index + 1);
|
||||
state.mv.visitJumpInsn(GOTO, start);
|
||||
state.mv.visitLabel(cont);
|
||||
|
||||
state.mv.visitTypeInsn(CHECKCAST, pat.type().getInternalName());
|
||||
|
||||
if (pat instanceof TargetTypePattern sp) {
|
||||
var local = state.createVariable(sp.name(), sp.type());
|
||||
state.mv.visitVarInsn(ASTORE, local.index);
|
||||
} else if (pat instanceof TargetComplexPattern cp) {
|
||||
if (cp.name() != null) {
|
||||
state.mv.visitInsn(DUP);
|
||||
var local = state.createVariable(cp.name(), cp.type());
|
||||
state.mv.visitVarInsn(ASTORE, local.index);
|
||||
}
|
||||
|
||||
var clazz = findClass(new JavaClassName(cp.type().name()));
|
||||
if (clazz == null) throw new CodeGenException("Class definition for '" + cp.type().name() + "' not found");
|
||||
// TODO Check if class is a Record
|
||||
|
||||
for (var i = 0; i < cp.subPatterns().size(); i++) {
|
||||
state.mv.visitInsn(DUP);
|
||||
|
||||
var subPattern = cp.subPatterns().get(i);
|
||||
extractField(state, cp.type(), i, clazz);
|
||||
bindPattern(state, subPattern.type(), subPattern, start, index, depth + 1);
|
||||
}
|
||||
state.mv.visitInsn(POP);
|
||||
}
|
||||
}
|
||||
|
||||
final Set<TargetType> wrapperTypes = Set.of(TargetType.Long, TargetType.Integer, TargetType.Byte, TargetType.Char, TargetType.Boolean, TargetType.Double, TargetType.Float);
|
||||
|
||||
private void generateSwitch(State state, TargetSwitch aSwitch) {
|
||||
if (!wrapperTypes.contains(aSwitch.expr().type())) {
|
||||
generateEnhancedSwitch(state, aSwitch);
|
||||
return;
|
||||
}
|
||||
else for (var case_ : aSwitch.cases()) {
|
||||
if (case_.labels().stream().anyMatch(c -> c instanceof TargetPattern)) {
|
||||
generateEnhancedSwitch(state, aSwitch);
|
||||
return;
|
||||
}
|
||||
}
|
||||
generateClassicSwitch(state, aSwitch);
|
||||
}
|
||||
|
||||
private void generateField(TargetField field) {
|
||||
cw.visitField(field.access() | ACC_PUBLIC, field.name(), field.type().toSignature(), field.type().toDescriptor(), null);
|
||||
var access = field.access();
|
||||
if ((access & ACC_PRIVATE) == 0 && (access & ACC_PROTECTED) == 0) // TODO Implement access modifiers properly
|
||||
access |= ACC_PUBLIC;
|
||||
|
||||
cw.visitField(access, field.name(), field.type().toSignature(), field.type().toDescriptor(), null);
|
||||
}
|
||||
|
||||
private void generateStaticConstructor(TargetMethod constructor) {
|
||||
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "<clinit>", "()V", null, null);
|
||||
mv.visitCode();
|
||||
|
||||
var state = new State(null, mv, 0);
|
||||
generate(state, constructor.block());
|
||||
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
private void generateConstructor(TargetConstructor constructor) {
|
||||
@@ -962,8 +1338,12 @@ public class Codegen {
|
||||
|
||||
mv.visitCode();
|
||||
var state = new State(null, mv, 1);
|
||||
for (var param : constructor.parameters())
|
||||
state.createVariable(param.name(), param.type());
|
||||
for (var param : constructor.parameters()) {
|
||||
var pattern = param.pattern();
|
||||
if (pattern instanceof TargetTypePattern tp)
|
||||
state.createVariable(tp.name(), tp.type());
|
||||
else throw new NotImplementedException();
|
||||
}
|
||||
|
||||
var stmts = constructor.block().statements();
|
||||
generate(state, stmts.get(0));
|
||||
@@ -981,48 +1361,160 @@ public class Codegen {
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
private int bindLocalVariables(State state, TargetPattern pattern, int offset, int field) {
|
||||
if (pattern instanceof TargetComplexPattern cp) {
|
||||
state.mv.visitVarInsn(ALOAD, offset);
|
||||
|
||||
var clazz = findClass(new JavaClassName(cp.type().name()));
|
||||
if (clazz == null) throw new CodeGenException("Class definition for '" + cp.type().name() + "' not found");
|
||||
|
||||
for (var i = 0; i < cp.subPatterns().size(); i++) {
|
||||
var subPattern = cp.subPatterns().get(i);
|
||||
|
||||
if (i < cp.subPatterns().size() - 1)
|
||||
state.mv.visitInsn(DUP);
|
||||
|
||||
extractField(state, cp.type(), i, clazz);
|
||||
state.mv.visitTypeInsn(CHECKCAST, subPattern.type().getInternalName());
|
||||
state.mv.visitVarInsn(ASTORE, offset);
|
||||
offset = bindLocalVariables(state, subPattern, offset, i);
|
||||
}
|
||||
} else if (pattern instanceof TargetTypePattern tp) {
|
||||
offset++;
|
||||
state.createVariable(tp.name(), tp.type());
|
||||
} else throw new NotImplementedException();
|
||||
return offset;
|
||||
}
|
||||
|
||||
private void generateMethod(TargetMethod method) {
|
||||
var access = method.access() | ACC_PUBLIC;
|
||||
if (method.block() == null)
|
||||
access |= ACC_ABSTRACT;
|
||||
|
||||
// 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);
|
||||
MethodVisitor mv = cw.visitMethod(access, method.name(), method.getDescriptor(), method.getSignature(), null);
|
||||
if (method.txSignature() != null) {
|
||||
mv.visitAttribute(new JavaTXSignatureAttribute(method.getTXSignature()));
|
||||
}
|
||||
|
||||
if (method.block() != null) {
|
||||
mv.visitCode();
|
||||
var state = new State(method.signature().returnType(), mv, method.isStatic() ? 0 : 1);
|
||||
for (var param : method.signature().parameters())
|
||||
state.createVariable(param.name(), param.type());
|
||||
for (var param : method.signature().parameters()) {
|
||||
bindLocalVariables(state, param.pattern(), 1, 0);
|
||||
}
|
||||
generate(state, method.block());
|
||||
if (method.signature().returnType() == null)
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(0, 0);
|
||||
}
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
private static String generateSignature(TargetClass clazz, Set<TargetGeneric> generics) {
|
||||
private static String generateSignature(TargetStructure clazz, Set<TargetGeneric> generics) {
|
||||
String ret = "";
|
||||
if (generics.size() > 0) {
|
||||
if (!generics.isEmpty()) {
|
||||
ret += "<";
|
||||
for (var generic : generics) {
|
||||
ret += generic.name() + ":" + generic.bound().toDescriptor();
|
||||
}
|
||||
ret += ">";
|
||||
}
|
||||
if (clazz.superType() != null)
|
||||
ret += clazz.superType().toDescriptor();
|
||||
for (var intf : clazz.implementingInterfaces()) {
|
||||
ret += intf.toSignature();
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.isEmpty() ? null : ret;
|
||||
}
|
||||
|
||||
public byte[] generate() {
|
||||
cw.visit(V1_8, clazz.modifiers() | ACC_PUBLIC | ACC_SUPER, clazz.qualifiedName(), generateSignature(clazz, clazz.generics()), clazz.superType() != null ? clazz.superType().getInternalName() : "java/lang/Object", clazz.implementingInterfaces().stream().map(TargetType::toSignature).toArray(String[]::new));
|
||||
if (clazz.txGenerics() != null)
|
||||
var access = clazz.modifiers();
|
||||
if ((access & ACC_PRIVATE) == 0 && (access & ACC_PROTECTED) == 0) // TODO Implement access modifiers properly
|
||||
access |= ACC_PUBLIC;
|
||||
if (!(clazz instanceof TargetInterface))
|
||||
access |= ACC_SUPER;
|
||||
|
||||
var signature = generateSignature(clazz, clazz.generics());
|
||||
var interfaces = clazz.implementingInterfaces().stream().map(TargetType::getInternalName).toArray(String[]::new);
|
||||
var superType = clazz.superType() != null ? clazz.superType().getInternalName() : "java/lang/Object";
|
||||
|
||||
cw.visit(V1_8, access, clazz.qualifiedName().toString().replaceAll("\\.", "/"), signature, superType, interfaces);
|
||||
if (clazz.txGenerics() != null && signature != null)
|
||||
cw.visitAttribute(new JavaTXSignatureAttribute(generateSignature(clazz, clazz.txGenerics())));
|
||||
|
||||
clazz.fields().forEach(this::generateField);
|
||||
clazz.constructors().forEach(this::generateConstructor);
|
||||
clazz.methods().forEach(this::generateMethod);
|
||||
|
||||
if (clazz.staticConstructor() != null)
|
||||
generateStaticConstructor(clazz.staticConstructor());
|
||||
|
||||
if (clazz instanceof TargetRecord)
|
||||
generateRecordMethods();
|
||||
|
||||
cw.visitEnd();
|
||||
return cw.toByteArray();
|
||||
}
|
||||
|
||||
private ClassOrInterface findClass(JavaClassName className) {
|
||||
try {
|
||||
for (var sf : compiler.sourceFiles.values()) {
|
||||
for (var clazz : compiler.getAvailableClasses(sf)) {
|
||||
if (clazz.getClassName().equals(className))
|
||||
return clazz;
|
||||
}
|
||||
for (var clazz : sf.KlassenVektor) {
|
||||
if (clazz.getClassName().equals(className))
|
||||
return clazz;
|
||||
}
|
||||
}
|
||||
} catch (ClassNotFoundException ignored) {}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void generateRecordMethods() {
|
||||
var mt = MethodType.methodType(Object.class, MethodHandles.Lookup.class, String.class, TypeDescriptor.class, Class.class, String.class, MethodHandle[].class);
|
||||
var bootstrap = new Handle(H_INVOKESTATIC, "java/lang/runtime/ObjectMethods", "bootstrap", mt.toMethodDescriptorString(), false);
|
||||
var bootstrapArgs = new Object[2 + clazz.fields().size()];
|
||||
|
||||
bootstrapArgs[0] = Type.getObjectType(clazz.getName());
|
||||
bootstrapArgs[1] = String.join(";", clazz.fields().stream().map(TargetField::name).toArray(String[]::new));
|
||||
for (var i = 0; i < clazz.fields().size(); i++) {
|
||||
var field = clazz.fields().get(i);
|
||||
var fieldRef = new Handle(H_GETFIELD, clazz.getName(), field.name(), field.type().toDescriptor(), false);
|
||||
bootstrapArgs[i + 2] = fieldRef;
|
||||
}
|
||||
|
||||
{ // hashCode
|
||||
var mv = cw.visitMethod(ACC_PUBLIC, "hashCode", "()I", null, null);
|
||||
mv.visitCode();
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitInvokeDynamicInsn("hashCode", "(L" + clazz.getName() + ";)I", bootstrap, bootstrapArgs);
|
||||
mv.visitInsn(IRETURN);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
{ // equals
|
||||
var mv = cw.visitMethod(ACC_PUBLIC, "equals", "(Ljava/lang/Object;)Z", null, null);
|
||||
mv.visitCode();
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitInvokeDynamicInsn("equals", "(L" + clazz.getName() + ";Ljava/lang/Object;)Z", bootstrap, bootstrapArgs);
|
||||
mv.visitInsn(IRETURN);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
{ // toString
|
||||
var mv = cw.visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null);
|
||||
mv.visitCode();
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitInvokeDynamicInsn("toString", "(L" + clazz.getName() + ";)Ljava/lang/String;", bootstrap, bootstrapArgs);
|
||||
mv.visitInsn(ARETURN);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,12 +28,15 @@ public class FunNGenerator {
|
||||
private static final String objectSuperType = Type.getInternalName(Object.class).replace('.','/');
|
||||
private static final String objectSignature = applySignature(TargetType.Object);
|
||||
|
||||
private static final String VOID = "Ljava/lang/Void;";
|
||||
|
||||
public static class GenericParameters {
|
||||
int start;
|
||||
public List<TargetType> parameters = new ArrayList<>();
|
||||
}
|
||||
|
||||
private static String applyDescriptor(TargetType type, GenericParameters gep) {
|
||||
if (type == null) return VOID;
|
||||
var res = "L" + type.getInternalName();
|
||||
if (type instanceof TargetSpecializedType a) {
|
||||
if (a.params().size() > 0) {
|
||||
@@ -59,7 +62,12 @@ public class FunNGenerator {
|
||||
}
|
||||
|
||||
private static String applySignature(TargetType a) { return a.toSignature(); }
|
||||
private static String applyNameDescriptor(TargetType a){ return a instanceof TargetGenericType ? "LTPH;" : String.format("%s;", applySignature(a)); }
|
||||
private static String applyNameDescriptor(TargetType a){ return a instanceof TargetGenericType ? "LTPH;" : String.format("%s", applySignature(a)); }
|
||||
|
||||
public static String encodeType(TargetType type) {
|
||||
if (type == null) return VOID;
|
||||
return applyNameDescriptor(type).replace("/", "$").replace(";", "$_$");
|
||||
}
|
||||
|
||||
public static byte[] generateSuperBytecode(int numberArguments) {
|
||||
StringBuilder superFunNClassSignature = new StringBuilder("<");
|
||||
@@ -130,11 +138,9 @@ public class FunNGenerator {
|
||||
argumentTypes.size(),
|
||||
argumentTypes
|
||||
.stream()
|
||||
.map(FunNGenerator::applyNameDescriptor)
|
||||
.map(FunNGenerator::encodeType)
|
||||
.collect(Collectors.joining()),
|
||||
applyNameDescriptor(returnType))
|
||||
.replace('/', '$')
|
||||
.replace(";", "$_$");
|
||||
encodeType(returnType));
|
||||
}
|
||||
|
||||
public static List<TargetType> getArguments(List<TargetType> list) {
|
||||
|
||||
@@ -12,12 +12,12 @@ import de.dhbwstuttgart.parser.scope.GenericsRegistry;
|
||||
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.SyntaxTreeGenerator;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.SourceFileContext;
|
||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||
import de.dhbwstuttgart.parser.scope.JavaClassRegistry;
|
||||
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.FormalParameter;
|
||||
import de.dhbwstuttgart.syntaxtree.GenericDeclarationList;
|
||||
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
|
||||
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
|
||||
@@ -31,6 +31,7 @@ import de.dhbwstuttgart.syntaxtree.type.TypeVisitor;
|
||||
import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter;
|
||||
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
|
||||
import de.dhbwstuttgart.target.generate.GenericsResult;
|
||||
import de.dhbwstuttgart.target.tree.expression.TargetBinaryOp;
|
||||
import de.dhbwstuttgart.typeinference.constraints.Constraint;
|
||||
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
||||
import de.dhbwstuttgart.typeinference.constraints.Pair;
|
||||
@@ -44,7 +45,6 @@ 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.util.BiRelation;
|
||||
import de.dhbwstuttgart.typeinference.unify.TypeUnifyTask;
|
||||
import de.dhbwstuttgart.typeinference.unify.UnifyResultListener;
|
||||
import de.dhbwstuttgart.typeinference.unify.UnifyResultListenerImpl;
|
||||
@@ -62,7 +62,6 @@ import java.util.Map.Entry;
|
||||
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 {
|
||||
@@ -71,10 +70,17 @@ public class JavaTXCompiler {
|
||||
final CompilationEnvironment environment;
|
||||
Boolean resultmodel = false;
|
||||
public final Map<File, SourceFile> sourceFiles = new HashMap<>();
|
||||
Boolean log = false; // gibt an ob ein Log-File nach System.getProperty("user.dir")+""/logFiles/"" geschrieben werden soll?
|
||||
|
||||
Boolean log = true; //gibt an ob ein Log-File nach System.getProperty("user.dir")+""/logFiles/"" geschrieben werden soll?
|
||||
public volatile UnifyTaskModel usedTasks = new UnifyTaskModel();
|
||||
private final DirectoryClassLoader classLoader;
|
||||
|
||||
private final List<File> classPath;
|
||||
|
||||
public DirectoryClassLoader getClassLoader() {
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
public JavaTXCompiler(File sourceFile) throws IOException, ClassNotFoundException {
|
||||
this(Arrays.asList(sourceFile), null);
|
||||
}
|
||||
@@ -95,12 +101,32 @@ public class JavaTXCompiler {
|
||||
}
|
||||
classLoader = new DirectoryClassLoader(contextPath, ClassLoader.getSystemClassLoader());
|
||||
environment = new CompilationEnvironment(sources);
|
||||
classPath = contextPath;
|
||||
|
||||
for (File s : sources) {
|
||||
sourceFiles.put(s, parse(s));
|
||||
parse(s);
|
||||
}
|
||||
// INSTANCE = this;
|
||||
}
|
||||
|
||||
private void addSourceFile(File file, SourceFile sf) {
|
||||
sourceFiles.put(file, sf);
|
||||
}
|
||||
|
||||
public ClassOrInterface getClass(JavaClassName name) {
|
||||
for (var sf : sourceFiles.values()) {
|
||||
for (var clazz : sf.KlassenVektor) {
|
||||
if (clazz.getClassName().equals(name)) return clazz;
|
||||
}
|
||||
}
|
||||
try {
|
||||
var clazz = classLoader.loadClass(name.toString());
|
||||
if (clazz != null)
|
||||
return ASTFactory.createClass(clazz);
|
||||
} catch (ClassNotFoundException ignored) {}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ConstraintSet<Pair> getConstraints() throws ClassNotFoundException, IOException {
|
||||
List<ClassOrInterface> allClasses = new ArrayList<>();// environment.getAllAvailableClasses();
|
||||
List<ClassOrInterface> importedClasses = new ArrayList<>();
|
||||
@@ -108,11 +134,9 @@ public class JavaTXCompiler {
|
||||
// Alle Importierten Klassen in allen geparsten Sourcefiles kommen ins FC
|
||||
for (Entry<File, SourceFile> source : sourceFiles.entrySet()) {
|
||||
for (JavaClassName name : source.getValue().getImports()) {
|
||||
// TODO: Hier werden imports von eigenen (.jav) Klassen nicht beachtet
|
||||
ClassOrInterface importedClass = ASTFactory.createClass(classLoader.loadClass(name.toString()));
|
||||
importedClasses.add(importedClass);
|
||||
importedClasses.addAll(getAvailableClasses(name));
|
||||
}
|
||||
for (Class c : CompilationEnvironment.loadDefaultPackageClasses(source.getValue().getPkgName(), source.getKey(), classLoader)) {
|
||||
for (Class c : CompilationEnvironment.loadDefaultPackageClasses(source.getValue().getPkgName(), source.getKey(), this)) {
|
||||
ClassOrInterface importedClass = ASTFactory.createClass(c);
|
||||
importedClasses.add(importedClass);
|
||||
}
|
||||
@@ -135,9 +159,6 @@ public class JavaTXCompiler {
|
||||
void addMethods(SourceFile sf, ClassOrInterface cl, List<ClassOrInterface> importedClasses, ClassOrInterface objectClass) {
|
||||
if (!cl.areMethodsAdded()) {
|
||||
ClassOrInterface superclass = null;
|
||||
if (cl.getSuperClass().getName().equals(new JavaClassName("java.lang.Object"))) {
|
||||
superclass = objectClass;
|
||||
} else {
|
||||
Optional<ClassOrInterface> optSuperclass = importedClasses.stream().filter(x -> x.getClassName().equals(cl.getSuperClass().getName())).findFirst();
|
||||
if (optSuperclass.isPresent()) {
|
||||
superclass = optSuperclass.get();
|
||||
@@ -147,10 +168,14 @@ public class JavaTXCompiler {
|
||||
superclass = optSuperclass.get();
|
||||
addMethods(sf, superclass, importedClasses, objectClass);
|
||||
} else {
|
||||
try {
|
||||
var className = cl.getSuperClass().getName().toString();
|
||||
superclass = ASTFactory.createClass(classLoader.loadClass(className));
|
||||
} catch (ClassNotFoundException ignored) {}
|
||||
// throw new ClassNotFoundException("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Iterator<RefTypeOrTPHOrWildcardOrGeneric> paraIt = cl.getSuperClass().getParaList().iterator();
|
||||
Iterator<GenericTypeVar> tvarVarIt = superclass.getGenerics().iterator();
|
||||
|
||||
@@ -163,7 +188,7 @@ public class JavaTXCompiler {
|
||||
// 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());
|
||||
ParameterList newParaList = new ParameterList(m.getParameterList().getFormalparalist().stream().map(fp -> fp.withType(fp.getType().acceptTV(new TypeExchanger(gtvs)))).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()),
|
||||
@@ -174,6 +199,19 @@ public class JavaTXCompiler {
|
||||
cl.setMethodsAdded();
|
||||
}
|
||||
|
||||
private List<ClassOrInterface> getAvailableClasses(JavaClassName name) throws ClassNotFoundException {
|
||||
Set<ClassOrInterface> allClasses = new HashSet<>();
|
||||
if (loadJavaTXClass(name)) {
|
||||
var file = findFileForClass(name);
|
||||
var sf = sourceFiles.get(file);
|
||||
if (sf != null) allClasses.addAll(sf.KlassenVektor);
|
||||
} else {
|
||||
ClassOrInterface importedClass = ASTFactory.createClass(classLoader.loadClass(name.toString()));
|
||||
allClasses.add(importedClass);
|
||||
}
|
||||
return new ArrayList<>(allClasses);
|
||||
}
|
||||
|
||||
public List<ClassOrInterface> getAvailableClasses(SourceFile forSourceFile) throws ClassNotFoundException {
|
||||
// PL 2018-09-18: List durch Set ersetzt, damit die Klassen nur einmal
|
||||
// hinzugefuegt werden
|
||||
@@ -181,22 +219,8 @@ public class JavaTXCompiler {
|
||||
// ArrayList<>();//environment.getAllAvailableClasses();
|
||||
Set<ClassOrInterface> 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<ClassOrInterface> getAvailableClasses(SourceFile forSourceFile) throws ClassNotFoundException { // PL 2018-09-18: List durch Set ersetzt, damit die Klassen nur einmal // hinzugefuegt werden // List<ClassOrInterface> allClasses = new // ArrayList<>();//environment.getAllAvailableClasses(); Set<ClassOrInterface> allClasses = new HashSet<>();
|
||||
*
|
||||
* /* PL 2018-09-19 geloescht werden bereits in typeInference hinzugefuegt for (SourceFile sf : sourceFiles.values()) { allClasses.addAll(sf.getClasses()); }
|
||||
*/
|
||||
|
||||
List<ClassOrInterface> 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);
|
||||
allClasses.addAll(getAvailableClasses(name));
|
||||
}
|
||||
return new ArrayList<>(allClasses);
|
||||
}
|
||||
@@ -251,7 +275,7 @@ public class JavaTXCompiler {
|
||||
SourceFile sf = source.getValue();
|
||||
allClasses.addAll(getAvailableClasses(sf));
|
||||
allClasses.addAll(sf.getClasses());
|
||||
allClasses.addAll(CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), source.getKey(), classLoader).stream().map(ASTFactory::createClass).collect(Collectors.toList()));
|
||||
allClasses.addAll(CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), source.getKey(), this).stream().map(ASTFactory::createClass).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
final ConstraintSet<Pair> cons = getConstraints();
|
||||
@@ -260,7 +284,7 @@ public class JavaTXCompiler {
|
||||
// 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);
|
||||
IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses, logFile, getClassLoader());
|
||||
System.out.println(finiteClosure);
|
||||
urm = new UnifyResultModel(cons, finiteClosure);
|
||||
urm.addUnifyResultListener(resultListener);
|
||||
@@ -382,16 +406,12 @@ public class JavaTXCompiler {
|
||||
SourceFile sf = source.getValue();
|
||||
allClasses.addAll(getAvailableClasses(sf));
|
||||
allClasses.addAll(sf.getClasses());
|
||||
var newClasses = CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), source.getKey(), classLoader).stream().map(ASTFactory::createClass).collect(Collectors.toList());
|
||||
var newClasses = CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), source.getKey(), this).stream().map(ASTFactory::createClass).collect(Collectors.toList());
|
||||
for (var clazz : newClasses) {
|
||||
var found = false;
|
||||
for (var old : allClasses) {
|
||||
if (clazz.getClassName().equals(old.getClassName())) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
// Don't load classes that get recompiled
|
||||
if (sf.getClasses().stream().anyMatch(nf -> nf.getClassName().equals(clazz.getClassName())))
|
||||
continue;
|
||||
if (allClasses.stream().noneMatch(old -> old.getClassName().equals(clazz.getClassName())))
|
||||
allClasses.add(clazz);
|
||||
}
|
||||
}
|
||||
@@ -399,7 +419,9 @@ public class JavaTXCompiler {
|
||||
final ConstraintSet<Pair> cons = getConstraints();
|
||||
Set<Set<UnifyPair>> results = new HashSet<>();
|
||||
try {
|
||||
Writer logFile = log ? new FileWriter(new File(System.getProperty("user.dir") + "/logFiles/" + "log_" + sourceFiles.keySet().iterator().next().getName())) : new OutputStreamWriter(new NullOutputStream());
|
||||
var logFolder = new File(System.getProperty("user.dir") + "/logFiles/");
|
||||
if (log) logFolder.mkdirs();
|
||||
Writer logFile = log ? new FileWriter(new File(logFolder, "log_" + sourceFiles.keySet().iterator().next().getName())) : new OutputStreamWriter(new NullOutputStream());
|
||||
IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses, logFile, classLoader);
|
||||
System.out.println(finiteClosure);
|
||||
ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(cons);
|
||||
@@ -624,11 +646,53 @@ public class JavaTXCompiler {
|
||||
return usedTPH;
|
||||
}
|
||||
|
||||
public final JavaClassRegistry classRegistry = new JavaClassRegistry();
|
||||
|
||||
private SourceFile parse(File sourceFile) throws IOException, java.lang.ClassNotFoundException {
|
||||
SourceFileContext tree = JavaTXParser.parse(sourceFile);
|
||||
SyntaxTreeGenerator generator = new SyntaxTreeGenerator(environment.getRegistry(tree, sourceFile, classLoader), new GenericsRegistry(null));
|
||||
SourceFile ret = generator.convert(tree, environment.packageCrawler, classLoader);
|
||||
return ret;
|
||||
environment.addClassesToRegistry(classRegistry, tree, sourceFile, this);
|
||||
SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null));
|
||||
var classes = new ArrayList<ClassOrInterface>();
|
||||
var sf = new SourceFile(generator.pkgName, classes, generator.imports);
|
||||
addSourceFile(sourceFile, sf);
|
||||
generator.convert(classes, tree, environment.packageCrawler);
|
||||
sf.imports.addAll(generator.imports);
|
||||
return sf;
|
||||
}
|
||||
|
||||
/**
|
||||
* When an import tries to import a JavaTX class it first looks it up in the cache and
|
||||
* if it doesn't exist it's going to compile it and add it to the source files list
|
||||
* @param name
|
||||
*/
|
||||
public boolean loadJavaTXClass(JavaClassName name) {
|
||||
var file = findFileForClass(name);
|
||||
if (file != null) {
|
||||
try {
|
||||
var tree = JavaTXParser.parse(file);
|
||||
classRegistry.addName(name.toString(), 0); // TODO This gets overwritten later, is it bad if we don't know this right away?
|
||||
environment.addClassesToRegistry(classRegistry, tree, file, this);
|
||||
SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null));
|
||||
var classes = new ArrayList<ClassOrInterface>();
|
||||
var sf = new SourceFile(generator.pkgName, classes, generator.imports);
|
||||
addSourceFile(file, sf);
|
||||
generator.convert(classes, tree, environment.packageCrawler);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public File findFileForClass(JavaClassName name) {
|
||||
var packageName = name.getPackageName();
|
||||
var className = name.getClassName().split("\\.")[0];
|
||||
for (var cp : classPath) {
|
||||
var file = new File(cp, packageName.replaceAll("\\.", "/") + "/" + className + ".jav");
|
||||
if (file.exists()) return file;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void generateBytecode() throws ClassNotFoundException, IOException {
|
||||
@@ -681,10 +745,10 @@ public class JavaTXCompiler {
|
||||
}
|
||||
|
||||
public synchronized Map<JavaClassName, byte[]> generateBytecode(SourceFile sf, List<ResultSet> typeInferenceResult) {
|
||||
var converter = new ASTToTargetAST(typeInferenceResult, sf, classLoader);
|
||||
var converter = new ASTToTargetAST(this, typeInferenceResult, sf, classLoader);
|
||||
var generatedClasses = new HashMap<JavaClassName, byte[]>();
|
||||
for (var clazz : sf.getClasses()) {
|
||||
var codegen = new Codegen(converter.convert(clazz));
|
||||
var codegen = new Codegen(converter.convert(clazz), this);
|
||||
var code = codegen.generate();
|
||||
generatedClasses.put(clazz.getClassName(), code);
|
||||
converter.auxiliaries.forEach((name, source) -> {
|
||||
|
||||
@@ -7,6 +7,7 @@ import java.net.URL;
|
||||
import java.util.*;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
|
||||
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
|
||||
|
||||
@@ -56,21 +57,22 @@ public class CompilationEnvironment {
|
||||
this.packageCrawler = new PackageCrawler(librarys);
|
||||
}
|
||||
|
||||
public JavaClassRegistry getRegistry(SourceFileContext tree, File sourceFile, ClassLoader classLoader) throws ClassNotFoundException, IOException {
|
||||
public void addClassesToRegistry(JavaClassRegistry registry, SourceFileContext tree, File sourceFile, JavaTXCompiler compiler) throws ClassNotFoundException, IOException {
|
||||
Map<String, Integer> allNames;
|
||||
if (tree instanceof SrcfileContext srcfile) {
|
||||
allNames = GatherNames.getNames((SrcfileContext) tree, packageCrawler, classLoader);
|
||||
for (Class c : loadDefaultPackageClasses(getPackageName(srcfile), sourceFile, classLoader)) {
|
||||
allNames = GatherNames.getNames((SrcfileContext) tree, packageCrawler, compiler);
|
||||
for (Class c : loadDefaultPackageClasses(getPackageName(srcfile), sourceFile, compiler)) {
|
||||
allNames.put(c.getName(), c.getTypeParameters().length);
|
||||
}
|
||||
return new JavaClassRegistry(allNames);
|
||||
registry.addNames(allNames);
|
||||
} else {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static List<Class> loadDefaultPackageClasses(String packageName, File sourceFile, ClassLoader classLoader) throws IOException, ClassNotFoundException {
|
||||
public static List<Class> loadDefaultPackageClasses(String packageName, File sourceFile, JavaTXCompiler compiler) throws IOException, ClassNotFoundException {
|
||||
ClassLoader classLoader = compiler.getClassLoader();
|
||||
List<Class> ret = new ArrayList<>();
|
||||
// Set classLoader to include default package for this specific source file
|
||||
File dir = sourceFile.getParentFile();
|
||||
|
||||
@@ -2,8 +2,11 @@ package de.dhbwstuttgart.parser.SyntaxTreeGenerator;
|
||||
|
||||
import de.dhbwstuttgart.exceptions.DebugException;
|
||||
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.Method;
|
||||
import de.dhbwstuttgart.syntaxtree.Pattern;
|
||||
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
|
||||
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
|
||||
import de.dhbwstuttgart.syntaxtree.type.*;
|
||||
@@ -31,13 +34,36 @@ public class FCGenerator {
|
||||
//PL 2018-09-18: gtvs vor die for-Schleife gezogen, damit immer die gleichen Typeplaceholder eingesetzt werden.
|
||||
HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs = new HashMap<>();
|
||||
for(ClassOrInterface cly : availableClasses){
|
||||
pairs.addAll(getSuperTypes(cly, availableClasses, gtvs, classLoader));
|
||||
List<Pair> newPairs = getSuperTypes(cly, availableClasses, gtvs, classLoader);
|
||||
pairs.addAll(newPairs);
|
||||
|
||||
//For all Functional Interfaces FI: FunN$$<... args auf dem Functional Interface ...> <. FI is added to FC
|
||||
if (isFunctionalInterface(cly)) {
|
||||
pairs.add(genImplFunType(cly, newPairs.get(0).TA1, gtvs));
|
||||
}
|
||||
}
|
||||
return pairs;
|
||||
}
|
||||
|
||||
|
||||
private static Boolean isFunctionalInterface(ClassOrInterface cly) {
|
||||
return (cly.isInterface() && (cly.isFunctionalInterface() || cly.getMethods().size() == 1));
|
||||
}
|
||||
|
||||
private static Pair genImplFunType(ClassOrInterface cly, RefTypeOrTPHOrWildcardOrGeneric fIType, HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs) {
|
||||
for(Method m : cly.getMethods()) {
|
||||
if (!java.lang.reflect.Modifier.isAbstract(m.modifier))
|
||||
continue;
|
||||
List<RefTypeOrTPHOrWildcardOrGeneric> tl =
|
||||
(m.getParameterList().getFormalparalist()
|
||||
.stream().map(p -> p.getType().acceptTV(new TypeExchanger(gtvs)))
|
||||
.collect(Collectors.toList()));
|
||||
tl.add(m.getReturnType().acceptTV(new TypeExchanger(gtvs)));
|
||||
return new Pair(new RefType(new JavaClassName("Fun" + (tl.size()-1) + "$$"), tl, new NullToken()),
|
||||
fIType);
|
||||
}
|
||||
return null; //kann nicht passieren, da die Methode nur aufgerufen wird wenn cl Functional Interface ist
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package de.dhbwstuttgart.parser.SyntaxTreeGenerator;
|
||||
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||
|
||||
public record FieldEntry(String name, RefTypeOrTPHOrWildcardOrGeneric type, int modifiers) {
|
||||
}
|
||||
+270
-72
@@ -1,5 +1,6 @@
|
||||
package de.dhbwstuttgart.parser.SyntaxTreeGenerator;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
@@ -8,6 +9,10 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
import de.dhbwstuttgart.syntaxtree.*;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.*;
|
||||
import de.dhbwstuttgart.syntaxtree.type.Void;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
|
||||
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||
@@ -34,11 +39,17 @@ import de.dhbwstuttgart.parser.antlr.Java17Parser.EqualityexpressionContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.ExpressionContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.FltLiteralContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.ForloopContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.GPatternContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.GuardedPatternContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.IdentifierContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.InstanceofexpressionContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.IntLiteralContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.LabeledRuleDefaultContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.LabeledRuleExprListContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.LabeledRulePatternContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.LabeledstmtContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.LambdaLVTIParameterContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.LambdaexpressionContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.LambdaExpression2Context;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.MathaddsubexpressionContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.MathmuldivmodexpressionContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.MethodCallContext;
|
||||
@@ -46,81 +57,74 @@ import de.dhbwstuttgart.parser.antlr.Java17Parser.MethodcallexpressionContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.NewinstanceexpressionContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.NullLiteralContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.OrexpressionContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.PPatternContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.PatternContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.PostfixexpressionContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.PrefixexpressionContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.PrimaryClassrefContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.PrimaryExpressionContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.PrimaryIdentifierContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.PrimaryLiteralContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.PrimaryPatternContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.PrimarySuperContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.PrimaryThisContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.PrimaryexpressionContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.PrimaryExpression2Context;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.RPatternContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.RecordPatternContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.RelationalexpressionContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.ReturnstmtContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.SemistmtContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.ShiftexpressionContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.StmtexpressionContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.StringLiteralContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.SwitchexpressionstmtContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.SwitchBlockStatementGroupContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.SwitchLabelConstContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.SwitchLabelContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.SwitchLabelDefaultContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.SwitchLabelPatternContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.SwitchLabeledRuleContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.SwitchRuleOutcomeContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.SwitchExpression2Context;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.SwitchstmtContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.SynchronizedstmtContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.TPatternContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.ThrowstmtContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.TrycatchblockContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.TrycatchresourceContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.TypePatternContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.WhileloopContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.YieldstmtContext;
|
||||
import de.dhbwstuttgart.parser.scope.GenericsRegistry;
|
||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||
import de.dhbwstuttgart.parser.scope.JavaClassRegistry;
|
||||
import de.dhbwstuttgart.syntaxtree.FormalParameter;
|
||||
import de.dhbwstuttgart.syntaxtree.ParameterList;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.ArgumentList;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.Assign;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.AssignLeftSide;
|
||||
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.Expression;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.ExpressionReceiver;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.FieldVar;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.IfStmt;
|
||||
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.NewClass;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.Receiver;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.Return;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.ReturnVoid;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.Statement;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.StaticClassName;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.Super;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.This;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.UnaryExpr;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.WhileStmt;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||
|
||||
public class StatementGenerator {
|
||||
|
||||
private JavaClassRegistry reg;
|
||||
private Map<String, RefTypeOrTPHOrWildcardOrGeneric> fields; // PL 2018-11-01 fields eingefuegt, damit die fields
|
||||
// immer die gleiche TPH bekommen
|
||||
private Map<String, RefTypeOrTPHOrWildcardOrGeneric> localVars;
|
||||
private GenericsRegistry generics;
|
||||
private final JavaClassRegistry reg;
|
||||
|
||||
public StatementGenerator(JavaClassRegistry reg, GenericsRegistry generics, Map<String, RefTypeOrTPHOrWildcardOrGeneric> fields, Map<String, RefTypeOrTPHOrWildcardOrGeneric> localVars) {
|
||||
private final Map<String, FieldEntry> fields; // PL 2018-11-01 fields eingefuegt, damit die fields
|
||||
// immer die gleiche TPH bekommen
|
||||
private final Map<String, RefTypeOrTPHOrWildcardOrGeneric> localVars;
|
||||
private final GenericsRegistry generics;
|
||||
private final JavaTXCompiler compiler;
|
||||
|
||||
private final RefType superClass;
|
||||
|
||||
// TODO How about instead of passing all of these types we just pass an instance of the SyntaxTreeGenerator?
|
||||
public StatementGenerator(RefType superType, JavaTXCompiler compiler, JavaClassRegistry reg, GenericsRegistry generics, Map<String, FieldEntry> fields, Map<String, RefTypeOrTPHOrWildcardOrGeneric> localVars) {
|
||||
this.reg = reg;
|
||||
this.generics = generics;
|
||||
this.fields = fields;
|
||||
this.localVars = localVars;
|
||||
this.compiler = compiler;
|
||||
this.superClass = superType;
|
||||
}
|
||||
|
||||
public ParameterList convert(Java17Parser.FormalParameterListContext formalParameterListContext) {
|
||||
List<FormalParameter> ret = new ArrayList<>();
|
||||
List<Pattern> ret = new ArrayList<>();
|
||||
List<Java17Parser.FormalParameterContext> fps = new ArrayList<>();
|
||||
if (Objects.isNull(formalParameterListContext))
|
||||
return new ParameterList(ret, new NullToken()); // Dann ist die Parameterliste leer
|
||||
@@ -133,6 +137,9 @@ public class StatementGenerator {
|
||||
|
||||
fps = formalParameterListContext.formalParameter();
|
||||
for (Java17Parser.FormalParameterContext fp : fps) {
|
||||
if (fp.pattern() != null) {
|
||||
ret.add(convert(fp.pattern()));
|
||||
} else {
|
||||
String paramName = SyntaxTreeGenerator.convert(fp.variableDeclaratorId());
|
||||
RefTypeOrTPHOrWildcardOrGeneric type;
|
||||
if (fp.typeType() != null) {
|
||||
@@ -143,6 +150,7 @@ public class StatementGenerator {
|
||||
ret.add(new FormalParameter(paramName, type, fp.getStart()));
|
||||
localVars.put(paramName, type);
|
||||
}
|
||||
}
|
||||
return new ParameterList(ret, ret.get(0).getOffset());
|
||||
}
|
||||
|
||||
@@ -162,8 +170,6 @@ public class StatementGenerator {
|
||||
return convert(dowhileloop);
|
||||
case SwitchstmtContext switchstmt:
|
||||
return convert(switchstmt);
|
||||
case SwitchexpressionstmtContext switchexpression:
|
||||
return convert(switchexpression);
|
||||
case ReturnstmtContext returnstmt:
|
||||
return convert(returnstmt);
|
||||
case YieldstmtContext yieldstmt:
|
||||
@@ -243,7 +249,12 @@ public class StatementGenerator {
|
||||
ret = convert(prefix);
|
||||
ret.setStatement();
|
||||
return ret;
|
||||
case SwitchExpression2Context switchexpr:
|
||||
ret = convert(switchexpr);
|
||||
ret.setStatement();
|
||||
return ret;
|
||||
default:
|
||||
System.out.println(stmt.getClass());
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -317,23 +328,152 @@ public class StatementGenerator {
|
||||
}
|
||||
|
||||
private Statement convert(Java17Parser.SwitchstmtContext stmt) {
|
||||
// TODO
|
||||
throw new NotImplementedException();
|
||||
Expression switched = convert(stmt.parExpression().expression());
|
||||
List<SwitchBlock> switchBlocks = new ArrayList<>();
|
||||
for (SwitchBlockStatementGroupContext blockstmt : stmt.switchBlockStatementGroup()) {
|
||||
switchBlocks.add(convert(blockstmt));
|
||||
}
|
||||
return new Switch(switched, switchBlocks, TypePlaceholder.fresh(switched.getOffset()), true, stmt.getStart());
|
||||
}
|
||||
|
||||
private Statement convert(Java17Parser.SwitchexpressionstmtContext switchexpression) {
|
||||
// TODO
|
||||
throw new NotImplementedException();
|
||||
// Um switchExpressions als Statement zu behandeln
|
||||
private Statement convert(Java17Parser.SwitchExpression2Context switchexpression) {
|
||||
Expression switchExpr = convert(switchexpression.switchExpression());
|
||||
if (switchExpr instanceof Switch s) {
|
||||
s.setStatement();
|
||||
return s;
|
||||
} else {
|
||||
// sollte nie vorkommen, da convert(Java17Parser.SwitchExpressionContext switchExpression) eine Instanz von Switch zurückgibt
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
private Expression convert(Java17Parser.SwitchExpressionContext switchExpression) {
|
||||
Expression switched = convert(switchExpression.parExpression().expression());
|
||||
List<SwitchBlock> switchBlocks = new ArrayList<>();
|
||||
Token offset = switchExpression.getStart();
|
||||
for (SwitchLabeledRuleContext labeledRule : switchExpression.switchLabeledRule()) {
|
||||
switchBlocks.add(convert(labeledRule));
|
||||
}
|
||||
return new Switch(switched, switchBlocks, TypePlaceholder.fresh(offset), false, offset);
|
||||
}
|
||||
|
||||
private SwitchBlock convert(SwitchLabeledRuleContext labeledRule) {
|
||||
Boolean isDefault = false;
|
||||
List<SwitchLabel> labels = switch (labeledRule.switchLabelCase()) {
|
||||
case LabeledRuleExprListContext exprList -> {
|
||||
List<SwitchLabel> labelList = exprList.expressionList().expression().stream().map((exprctx) -> {
|
||||
Pattern expr = new ExpressionPattern(convert(exprctx), exprList.getStart());
|
||||
return new SwitchLabel(expr, expr.getType(), exprList.getStart());
|
||||
}).toList();
|
||||
yield labelList;
|
||||
}
|
||||
case LabeledRulePatternContext pattern -> {
|
||||
Pattern p = convert(pattern.pattern());
|
||||
yield Arrays.asList(new SwitchLabel(p, p.getType(), pattern.getStart()));
|
||||
}
|
||||
case LabeledRuleDefaultContext def -> {
|
||||
isDefault = true;
|
||||
yield Arrays.asList(new SwitchLabel(new Void(def.getStart()), def.getStart()));
|
||||
}
|
||||
default -> throw new NotImplementedException();
|
||||
};
|
||||
|
||||
var isSingleExpression = false;
|
||||
Token offset = labeledRule.getStart();
|
||||
SwitchRuleOutcomeContext outcome = labeledRule.switchRuleOutcome();
|
||||
Block block;
|
||||
if (Objects.isNull(outcome.block())) {
|
||||
List<Statement> stmts = new ArrayList<>();
|
||||
stmts.add(new Yield(convert(outcome.expression()), outcome.expression().start));
|
||||
isSingleExpression = true;
|
||||
block = new Block(stmts, outcome.expression().getStart());
|
||||
} else {
|
||||
block = convert(outcome.block(), false);
|
||||
}
|
||||
return new SwitchBlock(labels, block, isDefault, isSingleExpression, offset);
|
||||
}
|
||||
|
||||
private Statement convert(Java17Parser.YieldstmtContext yieldstmt) {
|
||||
// TODO
|
||||
throw new NotImplementedException();
|
||||
return new Yield(convert(yieldstmt.expression()), yieldstmt.getStart());
|
||||
}
|
||||
|
||||
private Statement convert(Java17Parser.SwitchBlockStatementGroupContext stmt) {
|
||||
// TODO
|
||||
private SwitchBlock convert(Java17Parser.SwitchBlockStatementGroupContext stmt) {
|
||||
List<SwitchLabel> labels = new ArrayList<>();
|
||||
stmt.switchLabel().forEach((label) -> {
|
||||
labels.add(convert(label));
|
||||
});
|
||||
List<Statement> block = new ArrayList<>();
|
||||
stmt.blockStatement().stream().forEach((blockStmt) -> {
|
||||
block.addAll(convert(blockStmt));
|
||||
});
|
||||
return new SwitchBlock(labels, new Block(block, stmt.blockStatement(0).getStart()), false, stmt.getStart());
|
||||
}
|
||||
|
||||
private SwitchLabel convert(SwitchLabelContext switchLabel) {
|
||||
RefTypeOrTPHOrWildcardOrGeneric type = null;
|
||||
Pattern caseExpression = switch (switchLabel) {
|
||||
case SwitchLabelConstContext cons -> {
|
||||
yield new ExpressionPattern(convert(cons.constantExpression), cons.getStart());
|
||||
}
|
||||
case SwitchLabelPatternContext pattern -> {
|
||||
yield convert(pattern.pattern());
|
||||
}
|
||||
case SwitchLabelDefaultContext def -> {
|
||||
type = new Void(switchLabel.getStart());
|
||||
yield null;
|
||||
}
|
||||
default -> throw new NotImplementedException();
|
||||
};
|
||||
Token offset = switchLabel.getStart();
|
||||
if (Objects.isNull(caseExpression)) {
|
||||
if (type == null)
|
||||
type = TypePlaceholder.fresh(offset);
|
||||
return new SwitchLabel(type, offset);
|
||||
} else {
|
||||
return new SwitchLabel(caseExpression, caseExpression.getType(), offset);
|
||||
}
|
||||
}
|
||||
|
||||
private Pattern convert(PatternContext pattern) {
|
||||
return switch (pattern) {
|
||||
case PPatternContext pPattern -> {
|
||||
yield convert(pPattern.primaryPattern());
|
||||
}
|
||||
case GPatternContext gPattern -> {
|
||||
GuardedPatternContext guarded = gPattern.guardedPattern();
|
||||
Expression condition = convert(guarded.expression());
|
||||
yield new GuardedPattern(condition, convert(guarded.primaryPattern()), guarded.getStart());
|
||||
}
|
||||
default -> throw new NotImplementedException();
|
||||
};
|
||||
}
|
||||
|
||||
private FormalParameter convert(PrimaryPatternContext pPattern) {
|
||||
switch (pPattern) {
|
||||
case TPatternContext tPattern:
|
||||
TypePatternContext typePattern = tPattern.typePattern();
|
||||
var text = typePattern.identifier().getText();
|
||||
var type = TypeGenerator.convert(typePattern.typeType(), reg, generics);
|
||||
localVars.put(text, type);
|
||||
return new FormalParameter(text, type, typePattern.getStart());
|
||||
case RPatternContext rPattern:
|
||||
RecordPatternContext recordPattern = rPattern.recordPattern();
|
||||
return convert(recordPattern);
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private RecordPattern convert(RecordPatternContext recordPatternCtx) {
|
||||
List<PatternContext> subPatternCtx = recordPatternCtx.recordStructurePattern().recordComponentPatternList().pattern();
|
||||
List<Pattern> subPattern = subPatternCtx.stream().map(this::convert).collect(Collectors.toList());
|
||||
IdentifierContext identifierCtx = recordPatternCtx.identifier();
|
||||
var text = (identifierCtx != null) ? identifierCtx.getText() : null;
|
||||
var type = TypeGenerator.convert(recordPatternCtx.typeType(), reg, generics);
|
||||
if (text != null) localVars.put(text, type);
|
||||
return new RecordPattern(subPattern, text, type, recordPatternCtx.getStart());
|
||||
}
|
||||
|
||||
private Statement convert(Java17Parser.WhileloopContext stmt) {
|
||||
@@ -349,7 +489,18 @@ public class StatementGenerator {
|
||||
}
|
||||
|
||||
private Statement convert(Java17Parser.ForloopContext stmt) {
|
||||
var control = stmt.forControl();
|
||||
var block = convert(stmt.statement());
|
||||
if (control.enhancedForControl() != null)
|
||||
throw new NotImplementedException();
|
||||
else {
|
||||
return new ForStmt(
|
||||
stmt.getStart(),
|
||||
convert(control.forInit().localVariableDeclaration()),
|
||||
convert(control.expression()), control.forUpdate.expression().stream().map(this::convert).toList(),
|
||||
block
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private ArgumentList convertArguments(Java17Parser.ExpressionListContext arglist) {
|
||||
@@ -410,12 +561,18 @@ public class StatementGenerator {
|
||||
} else {
|
||||
initValue = convert(varDecl.variableInitializer().expression());
|
||||
}
|
||||
return (new Assign(new AssignToField(new FieldVar(new This(varDecl.getStart()), name.getText(), type, varDecl.getStart())), initValue, name.getStart()));
|
||||
var fieldEntry = fields.get(name.getText());
|
||||
return (new Assign(new AssignToField(new FieldVar(new This(varDecl.getStart()), (fieldEntry.modifiers() & Modifier.STATIC) != 0, name.getText(), type, varDecl.getStart())), initValue, name.getStart()));
|
||||
}
|
||||
|
||||
private Statement convert(Java17Parser.BreakstmtContext stmt) {
|
||||
// TODO
|
||||
throw new NotImplementedException();
|
||||
Token offset = stmt.getStart();
|
||||
if (!Objects.isNull(stmt.identifier())) {
|
||||
return new Break(localVars.get(stmt.identifier().getText()), offset);
|
||||
} else {
|
||||
return new Break(TypePlaceholder.fresh(offset), offset);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Statement convert(Java17Parser.ContinuestmtContext stmt) {
|
||||
@@ -462,7 +619,7 @@ public class StatementGenerator {
|
||||
|
||||
private Expression convert(Java17Parser.ExpressionContext expression) {
|
||||
switch (expression) {
|
||||
case PrimaryexpressionContext primary:
|
||||
case PrimaryExpression2Context primary:
|
||||
return convert(primary.primary());
|
||||
case DottedexpressionContext dotted:
|
||||
return convert(dotted, expression.getStart());
|
||||
@@ -482,14 +639,15 @@ public class StatementGenerator {
|
||||
return convert(mathexpr);
|
||||
case RelationalexpressionContext comparison:
|
||||
return convert(comparison);
|
||||
/*
|
||||
* TODO: syntaxtree for instanceof vorbereiten case InstanceofexpressionContext instanceof: case SwitchexpressionContext switchexpression:
|
||||
*/
|
||||
case InstanceofexpressionContext instanceOf:
|
||||
return convert(instanceOf);
|
||||
case SwitchExpression2Context switchexpression:
|
||||
return convert(switchexpression.switchExpression());
|
||||
case EqualityexpressionContext equal:
|
||||
return convert(equal);
|
||||
case AssignexpressionContext assignment:
|
||||
return convert(assignment);
|
||||
case LambdaexpressionContext lambdaexpr:
|
||||
case LambdaExpression2Context lambdaexpr:
|
||||
return convert(lambdaexpr.lambdaExpression());
|
||||
case ArrayaccessexpressionContext arrayaccess:
|
||||
return convert(arrayaccess);
|
||||
@@ -562,7 +720,7 @@ public class StatementGenerator {
|
||||
public Receiver getReceiver(ExpressionContext expr) {
|
||||
Expression expression = convert(expr);
|
||||
/*
|
||||
* if (expr instanceof PrimaryexpressionContext pc) { expression = convert(pc.primary()); } else { expression = generateLocalOrFieldVarOrClassName(expr.getText(), expr.getStart()); }
|
||||
* if (expr instanceof PrimaryExpression2Context pc) { expression = convert(pc.primary()); } else { expression = generateLocalOrFieldVarOrClassName(expr.getText(), expr.getStart()); }
|
||||
*/
|
||||
return getReceiver(expression);
|
||||
}
|
||||
@@ -588,16 +746,15 @@ public class StatementGenerator {
|
||||
// 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
|
||||
} 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);
|
||||
var field = fields.get(expression);
|
||||
return new FieldVar(new This(offset), Modifier.isStatic(field.modifiers()), expression, fields.get(expression).type(), offset);
|
||||
|
||||
} else {
|
||||
// kann eigentlich nicht vorkommen
|
||||
// Dann Muss es ein Feld sein!
|
||||
return new FieldVar(new This(offset), expression, TypePlaceholder.fresh(offset), offset);
|
||||
}
|
||||
// lokale Variable wurde ohne "var"-Keyword deklariert und direkt mit Wert versehen
|
||||
localVars.put(expression, TypePlaceholder.fresh(offset));
|
||||
return new LocalVar(expression, localVars.get(expression), offset);
|
||||
}
|
||||
}
|
||||
return generateFieldVarOrClassname(expression, offset);
|
||||
@@ -615,16 +772,24 @@ public class StatementGenerator {
|
||||
}
|
||||
whole += ".";
|
||||
}
|
||||
var fieldName = parts[parts.length - 1];
|
||||
|
||||
var isStatic = false;
|
||||
if (parts.length < 2 || parts[0].contentEquals("this")) {
|
||||
receiver = new This(offset);
|
||||
isStatic = Modifier.isStatic(fields.get(fieldName).modifiers());
|
||||
} else if (parts[0].contentEquals("super")) {
|
||||
receiver = new Super(offset);
|
||||
isStatic = Modifier.isStatic(compiler.getClass(new JavaClassName(superClass.getName().toString())).getField(fieldName).orElseThrow().modifier);
|
||||
} 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);
|
||||
} else {
|
||||
StaticClassName cname = (StaticClassName) receiver;
|
||||
var javaClassName = reg.getName(cname.getType().toString());
|
||||
isStatic = Modifier.isStatic(compiler.getClass(javaClassName).getField(fieldName).orElseThrow().modifier);
|
||||
}
|
||||
return new FieldVar(receiver, parts[parts.length - 1], TypePlaceholder.fresh(offset), offset);
|
||||
return new FieldVar(receiver, isStatic, fieldName, TypePlaceholder.fresh(offset), offset);
|
||||
}
|
||||
|
||||
private Expression convert(Java17Parser.ArrayaccessexpressionContext arrayaccess) {
|
||||
@@ -636,11 +801,19 @@ public class StatementGenerator {
|
||||
}
|
||||
|
||||
private Expression convert(Java17Parser.OrexpressionContext expression) {
|
||||
if (expression.expression().size() != 2) {
|
||||
throw new NotImplementedException();
|
||||
} else {
|
||||
return new BoolExpression(BoolExpression.Operator.OR, new RefType(new JavaClassName("java.lang.Boolean"), expression.getStart()), convert(expression.expression(0)), convert(expression.expression(1)), expression.getStart());
|
||||
}
|
||||
}
|
||||
|
||||
private Expression convert(Java17Parser.AndexpressionContext expression) {
|
||||
if (expression.expression().size() != 2) {
|
||||
throw new NotImplementedException();
|
||||
} else {
|
||||
return new BoolExpression(BoolExpression.Operator.AND, new RefType(new JavaClassName("java.lang.Boolean"), expression.getStart()), convert(expression.expression(0)), convert(expression.expression(1)), expression.getStart());
|
||||
}
|
||||
}
|
||||
|
||||
private Statement convert(AssignexpressionContext expr) {
|
||||
@@ -700,6 +873,30 @@ public class StatementGenerator {
|
||||
return new BinaryExpr(convertBinaryOperator(operator), TypePlaceholder.fresh(expression.getStart()), convert(expression.expression(0)), convert(expression.expression(1)), expression.getStart());
|
||||
}
|
||||
|
||||
private Expression convert(Java17Parser.InstanceofexpressionContext expression) {
|
||||
Expression left = convert(expression.expression());
|
||||
Token offset = expression.getStart();
|
||||
if (Objects.isNull(expression.pattern())) {;
|
||||
return new InstanceOf(left, new RefType(reg.getName("java.lang.Boolean"), expression.getStart()), TypeGenerator.convert(expression.typeType(), reg, generics), offset);
|
||||
} else {
|
||||
switch (expression.pattern()) {
|
||||
case PPatternContext primaryPattern:
|
||||
switch (primaryPattern.primaryPattern()) {
|
||||
case TPatternContext typePattern:
|
||||
TypePatternContext typePatternCtx = typePattern.typePattern();
|
||||
String localVarName = typePatternCtx.identifier().getText();
|
||||
RefTypeOrTPHOrWildcardOrGeneric localVarType = TypeGenerator.convert(typePatternCtx.typeType(), reg, generics);
|
||||
localVars.put(localVarName, localVarType);
|
||||
return new InstanceOf(left, new RefType(reg.getName("java.lang.Boolean"), expression.getStart()), new FormalParameter(localVarName, localVarType, typePatternCtx.getStart()), offset);
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private BinaryExpr.Operator convertBinaryOperator(String operator) {
|
||||
// return BinaryExpr.Operator.ADD;
|
||||
if (operator.equals("+")) {
|
||||
@@ -837,7 +1034,7 @@ public class StatementGenerator {
|
||||
Java17Parser.LambdaParametersContext lambdaParams = expression.lambdaParameters();
|
||||
ParameterList params;
|
||||
if (lambdaParams.identifier().size() > 0) {
|
||||
List<FormalParameter> parameterList = new ArrayList<>();
|
||||
List<Pattern> parameterList = new ArrayList<>();
|
||||
for (IdentifierContext identifier : lambdaParams.identifier()) {
|
||||
Token offset = identifier.getStart();
|
||||
parameterList.add(new FormalParameter(identifier.getText(), TypePlaceholder.fresh(offset), offset));
|
||||
@@ -847,7 +1044,7 @@ public class StatementGenerator {
|
||||
params = convert(lambdaParams.formalParameterList());
|
||||
// }else if( lambdaParams.inferredFormalParameterList != null){
|
||||
} else if (!Objects.isNull(lambdaParams.lambdaLVTIList())) {
|
||||
List<FormalParameter> parameterList = new ArrayList<>();
|
||||
List<Pattern> parameterList = new ArrayList<>();
|
||||
for (LambdaLVTIParameterContext param : lambdaParams.lambdaLVTIList().lambdaLVTIParameter()) {
|
||||
Token offset = param.getStart();
|
||||
parameterList.add(new FormalParameter(param.identifier().getText(), TypePlaceholder.fresh(offset), offset));
|
||||
@@ -859,10 +1056,11 @@ public class StatementGenerator {
|
||||
|
||||
HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> lambdaLocals = new HashMap<>();
|
||||
lambdaLocals.putAll(localVars);
|
||||
for (FormalParameter param : params.getFormalparalist()) {
|
||||
lambdaLocals.put(param.getName(), param.getType());
|
||||
for (Pattern param : params.getFormalparalist()) {
|
||||
if (!(param instanceof FormalParameter fp)) throw new IllegalArgumentException();
|
||||
lambdaLocals.put(fp.getName(), fp.getType());
|
||||
}
|
||||
StatementGenerator lambdaGenerator = new StatementGenerator(reg, generics, fields, lambdaLocals);
|
||||
StatementGenerator lambdaGenerator = new StatementGenerator(superClass, compiler, reg, generics, fields, lambdaLocals);
|
||||
|
||||
Block block;
|
||||
if (expression.lambdaBody().expression() != null) {
|
||||
|
||||
+87
-55
@@ -12,6 +12,10 @@ import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
import de.dhbwstuttgart.parser.NullToken;
|
||||
import de.dhbwstuttgart.syntaxtree.*;
|
||||
import de.dhbwstuttgart.syntaxtree.Record;
|
||||
import org.antlr.v4.runtime.CommonToken;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
|
||||
@@ -54,22 +58,13 @@ import de.dhbwstuttgart.parser.antlr.Java17Parser.ModifierContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.NoclassorinterfaceContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.RecordComponentContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.RecordDeclarationContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.ReftypeContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.RefType2Context;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.SrcfileContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.TypeArgumentsContext;
|
||||
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.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.Method;
|
||||
import de.dhbwstuttgart.syntaxtree.ParameterList;
|
||||
import de.dhbwstuttgart.syntaxtree.Record;
|
||||
import de.dhbwstuttgart.syntaxtree.SourceFile;
|
||||
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.Assign;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.AssignLeftSide;
|
||||
@@ -85,20 +80,27 @@ import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||
import de.dhbwstuttgart.syntaxtree.type.Void;
|
||||
import de.dhbwstuttgart.typeinference.constraints.GenericsResolver;
|
||||
import javassist.compiler.SyntaxError;
|
||||
|
||||
import javax.swing.text.html.Option;
|
||||
|
||||
public class SyntaxTreeGenerator {
|
||||
private JavaClassRegistry reg;
|
||||
private final GenericsRegistry globalGenerics;
|
||||
private String pkgName = "";
|
||||
Set<JavaClassName> imports = new HashSet<>();
|
||||
public String pkgName = "";
|
||||
public Set<JavaClassName> imports = new HashSet<>();
|
||||
HashMap<String, Integer> allmodifiers = new HashMap<>();
|
||||
// PL 2018-11-01 fields eingefuegt, damit die fields immer die gleiche TPH
|
||||
// bekommen
|
||||
private Map<String, RefTypeOrTPHOrWildcardOrGeneric> fields = new HashMap<>();
|
||||
private final Map<String, FieldEntry> fields = new HashMap<>();
|
||||
// PL 2019-10-23: Muss für jede Klasse neu initilisiert werden
|
||||
List<Statement> fieldInitializations = new ArrayList<>();
|
||||
List<Statement> staticFieldInitializations = new ArrayList<>();
|
||||
|
||||
public SyntaxTreeGenerator(JavaClassRegistry reg, GenericsRegistry globalGenerics) {
|
||||
private final JavaTXCompiler compiler;
|
||||
private RefType superClass;
|
||||
|
||||
public SyntaxTreeGenerator(JavaTXCompiler compiler, 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
|
||||
@@ -121,6 +123,8 @@ public class SyntaxTreeGenerator {
|
||||
this.allmodifiers.put("non-sealed", 8192);
|
||||
this.allmodifiers.put("default", 16384);
|
||||
this.allmodifiers.put("strictfp", 32768);
|
||||
|
||||
this.compiler = compiler;
|
||||
}
|
||||
|
||||
public JavaClassRegistry getReg() {
|
||||
@@ -134,17 +138,16 @@ public class SyntaxTreeGenerator {
|
||||
return ctx.getText();
|
||||
}
|
||||
|
||||
public SourceFile convert(Java17Parser.SourceFileContext ctx, PackageCrawler packageCrawler, ClassLoader classLoader) throws ClassNotFoundException, NotImplementedException {
|
||||
public void convert(List<ClassOrInterface> classes, Java17Parser.SourceFileContext ctx, PackageCrawler packageCrawler) throws ClassNotFoundException, NotImplementedException {
|
||||
SrcfileContext srcfile;
|
||||
List<ClassOrInterface> classes = new ArrayList<>();
|
||||
if (ctx instanceof Java17Parser.SrcfileContext) {
|
||||
srcfile = (SrcfileContext) ctx;
|
||||
} else {
|
||||
return new SourceFile(this.pkgName, classes, this.imports);
|
||||
return;
|
||||
}
|
||||
if (srcfile.packageDeclaration() != null)
|
||||
this.pkgName = convert(srcfile.packageDeclaration());
|
||||
Map<String, Integer> imports = GatherNames.getImports(srcfile, packageCrawler, classLoader);
|
||||
Map<String, Integer> imports = GatherNames.getImports(srcfile, packageCrawler, compiler);
|
||||
this.imports = imports.keySet().stream().map(name -> reg.getName(name)).collect(Collectors.toSet());
|
||||
for (Java17Parser.ClassOrInterfaceContext type : srcfile.classOrInterface()) {
|
||||
ClassorinterfacedeclContext clsoif;
|
||||
@@ -161,6 +164,7 @@ public class SyntaxTreeGenerator {
|
||||
}
|
||||
}
|
||||
fieldInitializations = new ArrayList<>(); // PL 2019-10-22: muss für jede Klasse neu initilisiert werden
|
||||
staticFieldInitializations = new ArrayList<>();
|
||||
if (!Objects.isNull(clsoif.classDeclaration())) {
|
||||
newClass = convertClass(clsoif.classDeclaration(), modifiers);
|
||||
} else if (!Objects.isNull(clsoif.interfaceDeclaration())) {
|
||||
@@ -172,9 +176,7 @@ public class SyntaxTreeGenerator {
|
||||
}
|
||||
classes.add(newClass);
|
||||
}
|
||||
if (classes.size() > 0) {
|
||||
return new SourceFile(this.pkgName, classes, this.imports);
|
||||
} else {
|
||||
if (classes.isEmpty()) {
|
||||
throw new NotImplementedException("SourceFile enthält keine Klassen");
|
||||
}
|
||||
}
|
||||
@@ -193,7 +195,7 @@ public class SyntaxTreeGenerator {
|
||||
Token offset = ctx.getStart();
|
||||
GenericDeclarationList genericClassParameters;
|
||||
if (ctx.genericDeclarationList() == null) {
|
||||
genericClassParameters = new GenericDeclarationList(new ArrayList<>(), ctx.identifier().getStop());
|
||||
genericClassParameters = new GenericDeclarationList(new ArrayList<>(), ctx.classBody().getStart());
|
||||
} else {
|
||||
genericClassParameters = TypeGenerator.convert(ctx.genericDeclarationList(), name, "", reg, generics);
|
||||
}
|
||||
@@ -203,10 +205,12 @@ public class SyntaxTreeGenerator {
|
||||
} else {
|
||||
superClass = new RefType(ASTFactory.createObjectClass().getClassName(), ctx.getStart());
|
||||
}
|
||||
this.superClass = superClass;
|
||||
List<Field> fielddecl = new ArrayList<>();
|
||||
List<Method> methods = new ArrayList<>();
|
||||
List<Constructor> constructors = new ArrayList<>();
|
||||
Boolean isInterface = false;
|
||||
Boolean isFunctionalInterface = false;
|
||||
List<RefType> implementedInterfaces = new ArrayList<>();
|
||||
List<RefType> permittedSubtypes = new ArrayList<>();
|
||||
for (ClassBodyDeclarationContext clsbodydecl : ctx.classBody().classBodyDeclaration()) {
|
||||
@@ -220,24 +224,22 @@ public class SyntaxTreeGenerator {
|
||||
}
|
||||
// Ist Bit für 'sealed'-Modifier gesetzt
|
||||
if ((modifiers & 4096) != 0) {
|
||||
switch (ctx.typeList().size()) {
|
||||
case 1: {
|
||||
permittedSubtypes.addAll(convert(ctx.typeList(0), generics));
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
permittedSubtypes.addAll(convert(ctx.typeList(1), generics));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
if (!Objects.isNull(ctx.PERMITS())) {
|
||||
// permitted subtypes sind letzte typeList (siehe Grammatikregel 'classDeclaration')
|
||||
permittedSubtypes.addAll(convert(ctx.typeList(ctx.typeList().size() - 1), generics));
|
||||
} else {
|
||||
// falls sealed modifier ohne 'permits'-List oder umgekehrt
|
||||
throw new NotImplementedException("Invalid sealed class declaration");
|
||||
}
|
||||
}
|
||||
}
|
||||
return new ClassOrInterface(modifiers, name, fielddecl, Optional.of(this.generatePseudoConstructor(ctx.identifier().getText(), name, superClass, genericClassParameters, offset)), methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, offset);
|
||||
var ctor = Optional.of(this.generatePseudoConstructor(ctx.identifier().getText(), fieldInitializations, genericClassParameters, offset));
|
||||
var staticCtor = Optional.of(this.generateStaticConstructor(ctx.identifier().getText(), staticFieldInitializations, genericClassParameters, offset));
|
||||
return new ClassOrInterface(modifiers, name, fielddecl, ctor, staticCtor, methods, constructors, genericClassParameters, superClass, isInterface, isFunctionalInterface, implementedInterfaces, permittedSubtypes, offset);
|
||||
|
||||
}
|
||||
|
||||
private de.dhbwstuttgart.syntaxtree.Record convertRecord(RecordDeclarationContext recordDeclaration, int modifiers) {
|
||||
this.superClass = new RefType(new JavaClassName("java.lang.Record"), new NullToken());
|
||||
String identifier = recordDeclaration.identifier().getText();
|
||||
String className = this.pkgName + (this.pkgName.length() > 0 ? "." : "") + identifier;
|
||||
JavaClassName name = reg.getName(className); // Holt den Package Namen mit dazu
|
||||
@@ -248,17 +250,17 @@ public class SyntaxTreeGenerator {
|
||||
}
|
||||
GenericDeclarationList genericClassParameters;
|
||||
if (recordDeclaration.genericDeclarationList() == null) {
|
||||
genericClassParameters = new GenericDeclarationList(new ArrayList<>(), recordDeclaration.identifier().getStop());
|
||||
genericClassParameters = new GenericDeclarationList(new ArrayList<>(), recordDeclaration.recordBody().getStart());
|
||||
} else {
|
||||
genericClassParameters = TypeGenerator.convert(recordDeclaration.genericDeclarationList(), name, "", reg, generics);
|
||||
}
|
||||
RefType superClass = new RefType(ASTFactory.createObjectClass().getClassName(), offset);
|
||||
RefType superClass = new RefType(ASTFactory.createClass(java.lang.Record.class).getClassName(), offset);
|
||||
List<Field> fielddecl = new ArrayList<>();
|
||||
List<Method> methods = new ArrayList<>();
|
||||
List<Constructor> constructors = new ArrayList<>();
|
||||
Boolean isInterface = false;
|
||||
List<RefType> implementedInterfaces = new ArrayList<>();
|
||||
List<FormalParameter> constructorParameters = new ArrayList<>();
|
||||
List<Pattern> constructorParameters = new ArrayList<>();
|
||||
List<Statement> constructorStatements = new ArrayList<>();
|
||||
for (RecordComponentContext component : recordDeclaration.recordHeader().recordComponentList().recordComponent()) {
|
||||
int fieldmodifiers = allmodifiers.get("private") + allmodifiers.get("final");
|
||||
@@ -272,7 +274,7 @@ public class SyntaxTreeGenerator {
|
||||
}
|
||||
fielddecl.add(new Field(fieldname, fieldtype, fieldmodifiers, fieldoffset));
|
||||
constructorParameters.add(new FormalParameter(fieldname, fieldtype, fieldoffset));
|
||||
FieldVar fieldvar = new FieldVar(new This(offset), fieldname, fieldtype, fieldoffset);
|
||||
FieldVar fieldvar = new FieldVar(new This(offset), false, fieldname, fieldtype, fieldoffset);
|
||||
constructorStatements.add(new Assign(new AssignToField(fieldvar), new LocalVar(fieldname, fieldtype, fieldoffset), offset));
|
||||
Statement returnStatement = new Return(fieldvar, offset);
|
||||
methods.add(new Method(allmodifiers.get("public"), fieldname, fieldtype, new ParameterList(new ArrayList<>(), offset), new Block(Arrays.asList(returnStatement), offset), new GenericDeclarationList(new ArrayList<>(), offset), offset));
|
||||
@@ -287,12 +289,12 @@ public class SyntaxTreeGenerator {
|
||||
if (!Objects.isNull(recordDeclaration.IMPLEMENTS())) {
|
||||
implementedInterfaces.addAll(convert(recordDeclaration.typeList(), generics));
|
||||
}
|
||||
return new Record(modifiers, name, fielddecl, initializations, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, offset);
|
||||
var staticCtor = Optional.of(this.generateStaticConstructor(recordDeclaration.identifier().getText(), staticFieldInitializations, genericClassParameters, offset));
|
||||
return new Record(modifiers, name, fielddecl, initializations, staticCtor, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, offset);
|
||||
}
|
||||
|
||||
private void convert(ClassBodyDeclarationContext classBody, List<Field> fields, List<Constructor> constructors, List<Method> methods, JavaClassName name, RefType superClass, GenericsRegistry generics) {
|
||||
MemberdeclContext member;
|
||||
// Statement-Blöcke und "leere Zeilen" (;) werden noch nicht berücksichtigt
|
||||
if (classBody instanceof MemberdeclContext) {
|
||||
member = (MemberdeclContext) classBody;
|
||||
Integer membermodifiers = 0;
|
||||
@@ -323,10 +325,16 @@ public class SyntaxTreeGenerator {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (classBody instanceof Java17Parser.ClassblockContext ctx && ctx.STATIC() != null) {
|
||||
// Static blocks
|
||||
var stmtgen = new StatementGenerator(superClass, compiler, reg, generics, this.fields, new HashMap<>());
|
||||
var block = stmtgen.convert(((Java17Parser.ClassblockContext) classBody).block(), false);
|
||||
staticFieldInitializations.addAll(block.statements);
|
||||
}
|
||||
}
|
||||
|
||||
private ClassOrInterface convertInterface(Java17Parser.InterfaceDeclarationContext ctx, int modifiers) {
|
||||
this.superClass = new RefType(new JavaClassName("java.lang.Object"), new NullToken());
|
||||
String className = this.pkgName.length() > 0 ? this.pkgName + "." : "" + 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?
|
||||
@@ -388,7 +396,20 @@ public class SyntaxTreeGenerator {
|
||||
if (!Objects.isNull(ctx.EXTENDS())) {
|
||||
extendedInterfaces.addAll(convert(ctx.typeList(0), generics));
|
||||
}
|
||||
return new ClassOrInterface(modifiers, name, fields, Optional.empty(), methods, new ArrayList<>(), genericParams, superClass, true, extendedInterfaces, ctx.getStart());
|
||||
List<RefType> permittedSubtypes = new ArrayList<>();
|
||||
// Ist Bit für 'sealed'-Modifier gesetzt
|
||||
if ((modifiers & 4096) != 0) {
|
||||
if (!Objects.isNull(ctx.PERMITS())) {
|
||||
// permitted subtypes sind letzte typeList (siehe Grammatikregel 'classDeclaration')
|
||||
permittedSubtypes.addAll(convert(ctx.typeList(ctx.typeList().size() - 1), generics));
|
||||
} else {
|
||||
// falls sealed modifier ohne 'permits'-List oder umgekehrt
|
||||
throw new NotImplementedException("Invalid sealed class declaration");
|
||||
}
|
||||
}
|
||||
|
||||
var staticCtor = Optional.of(this.generateStaticConstructor(ctx.identifier().getText(), staticFieldInitializations, genericParams, ctx.getStart()));
|
||||
return new ClassOrInterface(modifiers, name, fields, Optional.empty(), staticCtor, methods, new ArrayList<>(), genericParams, superClass, true, methods.size() == 1 ? true : false, extendedInterfaces, permittedSubtypes, ctx.getStart());
|
||||
}
|
||||
|
||||
private GenericDeclarationList createEmptyGenericDeclarationList(Token classNameIdentifier) {
|
||||
@@ -410,13 +431,13 @@ public class SyntaxTreeGenerator {
|
||||
if (Objects.isNull(bodydeclaration.refType())) {
|
||||
retType = TypePlaceholder.fresh(bodydeclaration.getStart());
|
||||
} else {
|
||||
if (bodydeclaration.refType() instanceof ReftypeContext reftype) {
|
||||
if (bodydeclaration.refType() instanceof RefType2Context reftype) {
|
||||
retType = TypeGenerator.convert(reftype.typeType(), reg, generics);
|
||||
} else {
|
||||
retType = new Void(bodydeclaration.refType().getStart());
|
||||
}
|
||||
}
|
||||
StatementGenerator stmtgen = new StatementGenerator(reg, generics, fields, new HashMap<>());
|
||||
StatementGenerator stmtgen = new StatementGenerator(superClass, compiler, reg, generics, fields, new HashMap<>());
|
||||
ParameterList paramlist = stmtgen.convert(bodydeclaration.formalParameters().formalParameterList());
|
||||
MethodBodyContext body = bodydeclaration.methodBody();
|
||||
Block block = null;
|
||||
@@ -444,15 +465,22 @@ public class SyntaxTreeGenerator {
|
||||
/*
|
||||
* fieldInitializations werden in einem Psedokonstruktor in der abstrakten Syntax gespeichert
|
||||
*/
|
||||
private Constructor generatePseudoConstructor(String className, JavaClassName parentClass, RefType superClass, GenericDeclarationList classGenerics, Token offset) {
|
||||
private Constructor generatePseudoConstructor(String className, List<Statement> initializations, 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);
|
||||
Block block = new Block(new ArrayList<>(initializations), offset);
|
||||
return new Constructor(Modifier.PUBLIC, className, classType, params, block, classGenerics, offset /*
|
||||
* fieldInitializations geloescht PL 2018-11-24
|
||||
*/);
|
||||
}
|
||||
|
||||
private Method generateStaticConstructor(String className, List<Statement> initializations, 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<>(initializations), offset);
|
||||
return new Method(Modifier.PUBLIC, className, classType, params, block, classGenerics, offset);
|
||||
}
|
||||
|
||||
private RefType convertSuperType(Java17Parser.TypeTypeContext typeType) {
|
||||
ClassOrInterfaceTypeContext supertypecontext = typeType.classOrInterfaceType();
|
||||
if (supertypecontext != null && supertypecontext.DOT().size() > 0) {
|
||||
@@ -503,13 +531,13 @@ public class SyntaxTreeGenerator {
|
||||
if (Objects.isNull(header.refType())) {
|
||||
retType = TypePlaceholder.fresh(header.getStart());
|
||||
} else {
|
||||
if (header.refType() instanceof ReftypeContext reftype) {
|
||||
if (header.refType() instanceof RefType2Context reftype) {
|
||||
retType = TypeGenerator.convert(reftype.typeType(), reg, generics);
|
||||
} else {
|
||||
retType = new Void(header.refType().getStart());
|
||||
}
|
||||
}
|
||||
StatementGenerator stmtgen = new StatementGenerator(reg, localgenerics, fields, new HashMap<>());
|
||||
StatementGenerator stmtgen = new StatementGenerator(superClass, compiler, reg, localgenerics, fields, new HashMap<>());
|
||||
ParameterList paramlist = stmtgen.convert(header.formalParameters().formalParameterList());
|
||||
MethodBodyContext body = methoddeclaration.methodBody();
|
||||
Block block = null;
|
||||
@@ -549,13 +577,13 @@ public class SyntaxTreeGenerator {
|
||||
gtvDeclarations = new GenericDeclarationList(new ArrayList<>(), constructordeclaration.getStart());
|
||||
}
|
||||
RefTypeOrTPHOrWildcardOrGeneric retType = TypeGenerator.convertTypeName(name, constructordeclaration.getStart(), reg, localgenerics);
|
||||
StatementGenerator stmtgen = new StatementGenerator(reg, localgenerics, fields, new HashMap<>());
|
||||
StatementGenerator stmtgen = new StatementGenerator(superClass, compiler, reg, localgenerics, fields, new HashMap<>());
|
||||
ParameterList paramlist = stmtgen.convert(constructordeclaration.formalParameters().formalParameterList());
|
||||
Block block = stmtgen.convert(constructordeclaration.constructorBody, true);
|
||||
return new Constructor(modifiers, name, retType, paramlist, block, gtvDeclarations, constructordeclaration.getStart());
|
||||
}
|
||||
|
||||
private List<? extends Field> convert(Java17Parser.FieldDeclarationContext fieldDeclContext, int modifiers, GenericsRegistry generics) {
|
||||
List<? extends Field> convert(Java17Parser.FieldDeclarationContext fieldDeclContext, int modifiers, GenericsRegistry generics) {
|
||||
List<Field> ret = new ArrayList<>();
|
||||
RefTypeOrTPHOrWildcardOrGeneric fieldType;
|
||||
if (fieldDeclContext.typeType() != null) {
|
||||
@@ -567,9 +595,9 @@ public class SyntaxTreeGenerator {
|
||||
}
|
||||
for (Java17Parser.VariableDeclaratorContext varDecl : fieldDeclContext.variableDeclarators().variableDeclarator()) {
|
||||
String fieldName = varDecl.variableDeclaratorId().getText();
|
||||
this.fields.put(fieldName, fieldType);
|
||||
this.fields.put(fieldName, new FieldEntry(fieldName, fieldType, modifiers));
|
||||
if (varDecl.variableInitializer() != null) {
|
||||
initializeField(varDecl, fieldType, generics);
|
||||
initializeField(varDecl, Modifier.isStatic(modifiers), fieldType, generics);
|
||||
}
|
||||
ret.add(new Field(fieldName, fieldType, modifiers, varDecl.getStart()));
|
||||
}
|
||||
@@ -581,9 +609,13 @@ public class SyntaxTreeGenerator {
|
||||
}
|
||||
|
||||
// Initialize a field by creating implicit constructor.
|
||||
private void initializeField(Java17Parser.VariableDeclaratorContext ctx, RefTypeOrTPHOrWildcardOrGeneric typeOfField, GenericsRegistry generics) {
|
||||
StatementGenerator statementGenerator = new StatementGenerator(reg, generics, fields, new HashMap<>());
|
||||
fieldInitializations.add(statementGenerator.generateFieldAssignment(ctx, typeOfField));
|
||||
private void initializeField(Java17Parser.VariableDeclaratorContext ctx, boolean isStatic, RefTypeOrTPHOrWildcardOrGeneric typeOfField, GenericsRegistry generics) {
|
||||
StatementGenerator statementGenerator = new StatementGenerator(superClass, compiler, reg, generics, fields, new HashMap<>());
|
||||
var assignment = statementGenerator.generateFieldAssignment(ctx, typeOfField);
|
||||
if (isStatic) {
|
||||
staticFieldInitializations.add(assignment);
|
||||
}
|
||||
else fieldInitializations.add(assignment);
|
||||
}
|
||||
|
||||
public int convertModifier(String modifier) {
|
||||
|
||||
@@ -65,6 +65,8 @@ public class TypeGenerator {
|
||||
return new RefType(ASTFactory.createClass(Boolean.class).getClassName(), typeContext.getStart());
|
||||
case "int":
|
||||
return new RefType(ASTFactory.createClass(Integer.class).getClassName(), typeContext.getStart());
|
||||
case "double":
|
||||
return new RefType(ASTFactory.createClass(Double.class).getClassName(), typeContext.getStart());
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -1,28 +1,48 @@
|
||||
package de.dhbwstuttgart.parser.scope;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.antlr.v4.runtime.ParserRuleContext;
|
||||
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.ClassDeclarationContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.ClassorinterfacedeclContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.NoclassorinterfaceContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.SrcfileContext;
|
||||
import com.google.common.collect.Iterables;
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
import de.dhbwstuttgart.environment.PackageCrawler;
|
||||
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.AnnotationTypeElementDeclarationContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.ClassBodyContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.ClassBodyDeclarationContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.ClassOrInterfaceContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.ClassorinterfacedeclContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.EnumConstantContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.EnumConstantsContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.InterfaceBodyDeclarationContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.InterfacememberContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.MemberclassorinterfaceContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.MemberdeclContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.NoclassorinterfaceContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.SrcfileContext;
|
||||
import de.dhbwstuttgart.parser.antlr.Java17Parser.SubclassorinterfaceContext;
|
||||
|
||||
public class GatherNames {
|
||||
|
||||
public static Map<String, Integer> getNames(SrcfileContext ctx, PackageCrawler packages, ClassLoader classLoader) throws ClassNotFoundException {
|
||||
public static Map<String, Integer> getNames(SrcfileContext ctx, PackageCrawler packages, JavaTXCompiler compiler) throws ClassNotFoundException {
|
||||
Map<String, Integer> ret = new HashMap<>();
|
||||
String pkgName = getPackageName(ctx);
|
||||
String nameString = "";
|
||||
for (Java17Parser.ClassOrInterfaceContext member : ctx.classOrInterface()) {
|
||||
if (member instanceof NoclassorinterfaceContext) {
|
||||
for (Java17Parser.ClassOrInterfaceContext clsoifctx : ctx.classOrInterface()) {
|
||||
if (clsoifctx instanceof NoclassorinterfaceContext) {
|
||||
continue;
|
||||
}
|
||||
ClassorinterfacedeclContext clsoif = (ClassorinterfacedeclContext) member;
|
||||
ret.putAll(getNames(clsoifctx, getPackageName(ctx), packages, compiler));
|
||||
}
|
||||
ret.putAll(getImports(ctx, packages, compiler));
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static Map<String, Integer> getNames(ClassOrInterfaceContext clsoifctx, String pkgName, PackageCrawler packages, JavaTXCompiler compiler) throws ClassNotFoundException {
|
||||
Map<String, Integer> ret = new HashMap<>();
|
||||
ClassorinterfacedeclContext clsoif = (ClassorinterfacedeclContext) clsoifctx;
|
||||
String nameString = "";
|
||||
String fullname = clsoif.getChild(clsoif.getChildCount() - 1).getClass().getName();
|
||||
String classname = fullname.substring(fullname.indexOf("$") + 1);
|
||||
int numGenerics = 0;
|
||||
@@ -38,6 +58,7 @@ public class GatherNames {
|
||||
}
|
||||
numGenerics = clsoif.classDeclaration().genericDeclarationList() != null ? clsoif.classDeclaration().genericDeclarationList().genericTypeVar().size() : 0;
|
||||
ret.put(nameString, numGenerics);
|
||||
ret.putAll(getNames(clsoif.classDeclaration().classBody().classBodyDeclaration(), pkgName, packages, compiler));
|
||||
break;
|
||||
case "EnumDeclarationContext":
|
||||
if (!pkgName.isEmpty()) {
|
||||
@@ -47,6 +68,15 @@ public class GatherNames {
|
||||
}
|
||||
numGenerics = 0;
|
||||
ret.put(nameString, numGenerics);
|
||||
EnumConstantsContext enumConstants = clsoif.enumDeclaration().enumConstants();
|
||||
if (!Objects.isNull(enumConstants)) {
|
||||
for (EnumConstantContext enumConstant : enumConstants.enumConstant()) {
|
||||
ClassBodyContext enumConstClassBody = enumConstant.classBody();
|
||||
if (!Objects.isNull(enumConstClassBody)) {
|
||||
ret.putAll(getNames(enumConstClassBody.classBodyDeclaration(), pkgName, packages, compiler));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "InterfaceDeclarationContext":
|
||||
if (pkgName != "") {
|
||||
@@ -56,6 +86,11 @@ public class GatherNames {
|
||||
}
|
||||
numGenerics = clsoif.interfaceDeclaration().genericDeclarationList() != null ? clsoif.interfaceDeclaration().genericDeclarationList().genericTypeVar().size() : 0;
|
||||
ret.put(nameString, numGenerics);
|
||||
for (InterfaceBodyDeclarationContext ifbody : clsoif.interfaceDeclaration().interfaceBody().interfaceBodyDeclaration()) {
|
||||
if (ifbody instanceof InterfacememberContext member && member.interfaceMemberDeclaration() instanceof SubclassorinterfaceContext sub) {
|
||||
ret.putAll(getNames(sub.classOrInterface(), pkgName, packages, compiler));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "AnnotationTypeDeclarationContext":
|
||||
if (pkgName != "") {
|
||||
@@ -65,6 +100,12 @@ public class GatherNames {
|
||||
}
|
||||
numGenerics = 0;
|
||||
ret.put(nameString, numGenerics);
|
||||
for (AnnotationTypeElementDeclarationContext anTypeElem : clsoif.annotationTypeDeclaration().annotationTypeBody().annotationTypeElementDeclaration()) {
|
||||
ClassOrInterfaceContext anClsoifctx = anTypeElem.annotationTypeElementRest().classOrInterface();
|
||||
if (!Objects.isNull(anClsoifctx)) {
|
||||
ret.putAll(getNames(anClsoifctx, pkgName, packages, compiler));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "RecordDeclarationContext":
|
||||
if (pkgName != "") {
|
||||
@@ -74,23 +115,39 @@ public class GatherNames {
|
||||
}
|
||||
numGenerics = clsoif.recordDeclaration().genericDeclarationList() != null ? clsoif.recordDeclaration().genericDeclarationList().genericTypeVar().size() : 0;
|
||||
ret.put(nameString, numGenerics);
|
||||
ret.putAll(getNames(clsoif.recordDeclaration().recordBody().classBodyDeclaration(), pkgName, packages, compiler));
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
ret.putAll(getImports(ctx, packages, classLoader));
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static Map<String, Integer> getImports(Java17Parser.SrcfileContext ctx, PackageCrawler packages, ClassLoader classLoader) throws ClassNotFoundException {
|
||||
public static Map<String, Integer> getNames(List<ClassBodyDeclarationContext> clsBodyDecl, String pkgName, PackageCrawler packages, JavaTXCompiler compiler) throws ClassNotFoundException {
|
||||
Map<String, Integer> ret = new HashMap<>();
|
||||
for (ClassBodyDeclarationContext clsbody : clsBodyDecl) {
|
||||
if (clsbody instanceof MemberdeclContext member && member.memberDeclaration() instanceof MemberclassorinterfaceContext memberclsoifctx) {
|
||||
ret.putAll(getNames(memberclsoifctx.classOrInterface(), pkgName, packages, compiler));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static Map<String, Integer> getImports(Java17Parser.SrcfileContext ctx, PackageCrawler packages, JavaTXCompiler compiler) throws ClassNotFoundException {
|
||||
Map<String, Integer> ret = new HashMap<>();
|
||||
// ret.putAll(packages.getClassNames("java.lang"));
|
||||
for (Java17Parser.ImportDeclarationContext importDeclCtx : ctx.importDeclaration()) {
|
||||
if (importDeclCtx.MUL() == null) {
|
||||
Class<?> cl = classLoader.loadClass(importDeclCtx.qualifiedName().getText());
|
||||
var name = importDeclCtx.qualifiedName().getText();
|
||||
var className = new JavaClassName(name);
|
||||
if (compiler.loadJavaTXClass(className)) {
|
||||
ret.put(name, compiler.classRegistry.getNumberOfGenerics(name));
|
||||
} else {
|
||||
Class<?> cl = compiler.getClassLoader().loadClass(name);
|
||||
ret.put(cl.getName(), cl.getTypeParameters().length);
|
||||
}
|
||||
} else if (importDeclCtx.MUL() != null) {
|
||||
// TODO Find stuff in user defined packages
|
||||
ret.putAll(packages.getClassNames(importDeclCtx.qualifiedName().getText()));
|
||||
}
|
||||
// Die Unterscheidungen für 'static imports' wurden herausgenommen, da sie den
|
||||
|
||||
@@ -12,6 +12,10 @@ import java.util.List;
|
||||
*/
|
||||
public class JavaClassName {
|
||||
|
||||
// FIXME It's very much possible to have imports to inner classes
|
||||
// In that case a.package.Foo.Bar, a.package is the Package and Foo.Bar the class name
|
||||
// Its impossible to decide what's the package based solely on the name of the class
|
||||
|
||||
public static final JavaClassName Void = new JavaClassName("void");
|
||||
private String name;
|
||||
private PackageName packageName;
|
||||
|
||||
@@ -11,9 +11,19 @@ public class JavaClassRegistry {
|
||||
final Map<JavaClassName, Integer> existingClasses = new HashMap<>();
|
||||
|
||||
public JavaClassRegistry(Map<String, Integer> initialNames) {
|
||||
for (String name : initialNames.keySet()) {
|
||||
existingClasses.put(new JavaClassName(name), initialNames.get(name));
|
||||
addNames(initialNames);
|
||||
}
|
||||
|
||||
public JavaClassRegistry() {}
|
||||
|
||||
public void addNames(Map<String, Integer> names) {
|
||||
for (String name : names.keySet()) {
|
||||
existingClasses.put(new JavaClassName(name), names.get(name));
|
||||
}
|
||||
}
|
||||
|
||||
public void addName(String className, int numberOfGenerics) {
|
||||
existingClasses.put(new JavaClassName(className), numberOfGenerics);
|
||||
}
|
||||
|
||||
public JavaClassName getName(String className) {
|
||||
|
||||
@@ -31,4 +31,11 @@ public interface ASTVisitor extends StatementVisitor{
|
||||
void visit(ExtendsWildcardType extendsWildcardType);
|
||||
|
||||
void visit(GenericRefType genericRefType);
|
||||
|
||||
void visit(ExpressionPattern aPattern);
|
||||
|
||||
void visit(RecordPattern aRecordPattern);
|
||||
|
||||
void visit(GuardedPattern aGuardedPattern);
|
||||
|
||||
}
|
||||
|
||||
@@ -2,10 +2,10 @@ 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;
|
||||
import java.util.Objects;
|
||||
|
||||
public abstract class AbstractASTWalker implements ASTVisitor {
|
||||
@Override
|
||||
@@ -66,7 +66,7 @@ public abstract class AbstractASTWalker implements ASTVisitor {
|
||||
|
||||
@Override
|
||||
public void visit(ParameterList formalParameters) {
|
||||
Iterator<FormalParameter> it = formalParameters.getFormalparalist().iterator();
|
||||
Iterator<Pattern> it = formalParameters.getFormalparalist().iterator();
|
||||
if (it.hasNext()) {
|
||||
while (it.hasNext()) {
|
||||
it.next().accept(this);
|
||||
@@ -134,6 +134,11 @@ public abstract class AbstractASTWalker implements ASTVisitor {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BoolExpression logical) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Block block) {
|
||||
for (Statement stmt : block.getStatements()) {
|
||||
@@ -158,12 +163,13 @@ public abstract class AbstractASTWalker implements ASTVisitor {
|
||||
|
||||
@Override
|
||||
public void visit(ForStmt forStmt) {
|
||||
forStmt.body_Loop_block.accept(this);
|
||||
forStmt.block.accept(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(IfStmt ifStmt) {
|
||||
ifStmt.then_block.accept(this);
|
||||
if (!Objects.isNull(ifStmt.else_block))
|
||||
ifStmt.else_block.accept(this);
|
||||
}
|
||||
|
||||
@@ -269,4 +275,46 @@ public abstract class AbstractASTWalker implements ASTVisitor {
|
||||
public void visit(SuperCall superCall) {
|
||||
this.visit((MethodCall) superCall);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Switch switchStmt) {
|
||||
switchStmt.getSwitch().accept(this);
|
||||
switchStmt.getBlocks().stream().forEach((switchBlock) -> {
|
||||
switchBlock.accept(this);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(SwitchBlock switchBlock) {
|
||||
switchBlock.getLabels().stream().forEach((label) -> {
|
||||
label.accept(this);
|
||||
});
|
||||
switchBlock.getStatements().stream().forEach((stmt) -> {
|
||||
stmt.accept(this);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(SwitchLabel switchLabel) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Yield aYield) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ExpressionPattern aPattern) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RecordPattern aRecordPattern) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(GuardedPattern aGuardedPattern) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,11 @@
|
||||
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;
|
||||
@@ -30,32 +23,38 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope{
|
||||
protected JavaClassName name;
|
||||
private List<Field> fields = new ArrayList<>();
|
||||
private Optional<Constructor> fieldInitializations; // PL 2018-11-24: Noetig, um Bytecode fuer initializators nur einmal zu erzeugen
|
||||
private Optional<Method> staticInitializer;
|
||||
private List<Method> methods = new ArrayList<>();
|
||||
private GenericDeclarationList genericClassParameters;
|
||||
private RefType superClass;
|
||||
protected boolean isInterface;
|
||||
protected boolean isFunctionalInterface;
|
||||
private List<RefType> implementedInterfaces;
|
||||
private List<RefType> permittedSubtypes;
|
||||
private List<Constructor> constructors;
|
||||
|
||||
|
||||
public ClassOrInterface(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters,
|
||||
RefType superClass, Boolean isInterface, List<RefType> implementedInterfaces, Token offset){
|
||||
public ClassOrInterface(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, Optional<Method> staticInitializer, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, Boolean isFunctionalInterface, List<RefType> implementedInterfaces, List<RefType> permittedSubtypes, Token offset) {
|
||||
super(offset);
|
||||
if(isInterface && !Modifier.isInterface(modifiers))modifiers += Modifier.INTERFACE;
|
||||
if (isInterface) {
|
||||
modifiers |= Modifier.INTERFACE | Modifier.ABSTRACT;
|
||||
}
|
||||
this.modifiers = modifiers;
|
||||
this.name = name;
|
||||
this.fields = fielddecl;
|
||||
this.fieldInitializations = fieldInitializations;
|
||||
this.staticInitializer = staticInitializer;
|
||||
this.genericClassParameters = genericClassParameters;
|
||||
this.superClass = superClass;
|
||||
this.isInterface = isInterface;
|
||||
this.isFunctionalInterface= isFunctionalInterface;
|
||||
this.implementedInterfaces = implementedInterfaces;
|
||||
this.permittedSubtypes = permittedSubtypes;
|
||||
this.methods = methods;
|
||||
this.constructors = constructors;
|
||||
}
|
||||
|
||||
/* erzeugt fuer Fields, Konstruktoren und Methoden neue ArrayList-Objekte
|
||||
* alle anderen Datenobjekte werden nur kopiert.
|
||||
/*
|
||||
* erzeugt fuer Fields, Konstruktoren und Methoden neue ArrayList-Objekte alle anderen Datenobjekte werden nur kopiert.
|
||||
*/
|
||||
public ClassOrInterface(ClassOrInterface cl) {
|
||||
super(cl.getOffset());
|
||||
@@ -63,14 +62,33 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope{
|
||||
this.name = cl.name;
|
||||
this.fields = new ArrayList<>(cl.fields);
|
||||
this.fieldInitializations = cl.fieldInitializations;
|
||||
this.staticInitializer = cl.staticInitializer;
|
||||
this.genericClassParameters = cl.genericClassParameters;
|
||||
this.superClass = cl.superClass;
|
||||
this.isInterface = cl.isInterface;
|
||||
this.isFunctionalInterface= cl.isFunctionalInterface;
|
||||
this.implementedInterfaces = cl.implementedInterfaces;
|
||||
this.methods = new ArrayList<>(cl.methods);
|
||||
this.constructors = new ArrayList<>(cl.constructors);
|
||||
}
|
||||
|
||||
public Optional<Field> getField(String name) {
|
||||
// TODO This should be a map
|
||||
return fields.stream().filter(field -> field.getName().equals(name)).findFirst();
|
||||
}
|
||||
|
||||
public Optional<Method> getStaticInitializer() {
|
||||
return staticInitializer;
|
||||
}
|
||||
|
||||
public boolean isInterface() {
|
||||
return (Modifier.INTERFACE & this.getModifiers()) != 0;
|
||||
}
|
||||
|
||||
public boolean isFunctionalInterface() {
|
||||
return this.isFunctionalInterface;
|
||||
}
|
||||
|
||||
// Gets if it is added
|
||||
public Boolean areMethodsAdded() {
|
||||
return methodAdded;
|
||||
@@ -104,9 +122,7 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope{
|
||||
}
|
||||
|
||||
/*
|
||||
public RefType getType() {
|
||||
return generateTypeOfClass(this.getClassName(), this.getGenerics(), this.getOffset());
|
||||
}
|
||||
* 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) {
|
||||
@@ -131,9 +147,9 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope{
|
||||
}
|
||||
return new RefType(name, params, new NullToken());
|
||||
}
|
||||
|
||||
/**
|
||||
* Die Superklasse im Kontext dieser ClassOrInterface
|
||||
* Das bedeutet, dass generische Variablen als GenericRefTypes dargestellt sind
|
||||
* Die Superklasse im Kontext dieser ClassOrInterface Das bedeutet, dass generische Variablen als GenericRefTypes dargestellt sind
|
||||
*/
|
||||
public RefType getSuperClass() {
|
||||
return superClass;
|
||||
@@ -164,4 +180,5 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope{
|
||||
public String toString() {
|
||||
return this.name.toString() + this.genericClassParameters.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package de.dhbwstuttgart.syntaxtree;
|
||||
|
||||
import de.dhbwstuttgart.syntaxtree.statement.Expression;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
|
||||
public class ExpressionPattern extends Pattern {
|
||||
private final Expression expression;
|
||||
|
||||
public ExpressionPattern(Expression expression, Token offset) {
|
||||
super(expression.getType(), offset);
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
public Expression getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionPattern withType(RefTypeOrTPHOrWildcardOrGeneric type) {
|
||||
return new ExpressionPattern(expression, getOffset());
|
||||
}
|
||||
}
|
||||
@@ -3,18 +3,12 @@ package de.dhbwstuttgart.syntaxtree;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
|
||||
public class FormalParameter extends SyntaxTreeNode {
|
||||
private RefTypeOrTPHOrWildcardOrGeneric type;
|
||||
public class FormalParameter extends Pattern {
|
||||
private String name;
|
||||
|
||||
public FormalParameter(String name, RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
|
||||
super(offset);
|
||||
super(type, offset);
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public RefTypeOrTPHOrWildcardOrGeneric getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
@@ -25,4 +19,9 @@ public class FormalParameter extends SyntaxTreeNode {
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FormalParameter withType(RefTypeOrTPHOrWildcardOrGeneric type) {
|
||||
return new FormalParameter(name, type, getOffset());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package de.dhbwstuttgart.syntaxtree;
|
||||
|
||||
import de.dhbwstuttgart.syntaxtree.statement.Expression;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
|
||||
public class GuardedPattern extends Pattern {
|
||||
|
||||
private final Expression condition;
|
||||
private final Pattern nested;
|
||||
|
||||
public GuardedPattern(Expression condition, Pattern nested, Token offset) {
|
||||
super(nested.getType(), offset);
|
||||
this.condition = condition;
|
||||
this.nested = nested;
|
||||
}
|
||||
|
||||
public Expression getCondition() {
|
||||
return condition;
|
||||
}
|
||||
|
||||
public Pattern getNestedPattern() {
|
||||
return nested;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuardedPattern withType(RefTypeOrTPHOrWildcardOrGeneric type) {
|
||||
return new GuardedPattern(condition, nested, getOffset());
|
||||
}
|
||||
}
|
||||
@@ -67,7 +67,7 @@ public class Method extends SyntaxTreeNode implements IItemWithOffset, TypeScope
|
||||
return parameterlist;
|
||||
}
|
||||
|
||||
public Iterable<? extends GenericTypeVar> getGenerics() {
|
||||
public GenericDeclarationList getGenerics() {
|
||||
return generics;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,27 +5,27 @@ import org.antlr.v4.runtime.Token;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class ParameterList extends SyntaxTreeNode implements Iterable<FormalParameter> {
|
||||
private List<FormalParameter> formalparameter;
|
||||
public class ParameterList extends SyntaxTreeNode implements Iterable<Pattern> {
|
||||
private List<Pattern> formalparameter;
|
||||
|
||||
public ParameterList(List<FormalParameter> params, Token offset) {
|
||||
public ParameterList(List<Pattern> params, Token offset) {
|
||||
super(offset);
|
||||
this.formalparameter = params;
|
||||
}
|
||||
|
||||
public FormalParameter getParameterAt(int i) {
|
||||
public Pattern getParameterAt(int i) {
|
||||
if (i >= formalparameter.size())
|
||||
return null;
|
||||
|
||||
return formalparameter.get(i);
|
||||
}
|
||||
|
||||
public List<FormalParameter> getFormalparalist() {
|
||||
public List<Pattern> getFormalparalist() {
|
||||
return formalparameter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<FormalParameter> iterator() {
|
||||
public Iterator<Pattern> iterator() {
|
||||
return formalparameter.iterator();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package de.dhbwstuttgart.syntaxtree;
|
||||
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
|
||||
public abstract class Pattern extends SyntaxTreeNode {
|
||||
private final RefTypeOrTPHOrWildcardOrGeneric type;
|
||||
|
||||
public Pattern(RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
|
||||
super(offset);
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public RefTypeOrTPHOrWildcardOrGeneric getType(){
|
||||
return type;
|
||||
}
|
||||
|
||||
public abstract Pattern withType(RefTypeOrTPHOrWildcardOrGeneric type);
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package de.dhbwstuttgart.syntaxtree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -8,9 +9,11 @@ import org.antlr.v4.runtime.Token;
|
||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||
|
||||
import javax.swing.text.html.Option;
|
||||
|
||||
public class Record extends ClassOrInterface {
|
||||
|
||||
public Record(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, List<RefType> implementedInterfaces, Token offset) {
|
||||
super(modifiers, name, fielddecl, fieldInitializations, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, offset);
|
||||
public Record(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, Optional<Method> staticInitializer, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, List<RefType> implementedInterfaces, Token offset) {
|
||||
super(modifiers, name, fielddecl, fieldInitializations, staticInitializer, methods, constructors, genericClassParameters, superClass, isInterface, methods.size() == 1 ? true : false, implementedInterfaces, new ArrayList<>(), offset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package de.dhbwstuttgart.syntaxtree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.antlr.v4.runtime.Token;
|
||||
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||
|
||||
public class RecordPattern extends FormalParameter {
|
||||
|
||||
private final List<Pattern> subPattern;
|
||||
|
||||
public RecordPattern(String name, RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
|
||||
super(name, type, offset);
|
||||
subPattern = new ArrayList<>();
|
||||
}
|
||||
|
||||
public RecordPattern(List<Pattern> subPattern, String name, RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
|
||||
super(name, type, offset);
|
||||
this.subPattern = subPattern;
|
||||
}
|
||||
|
||||
public List<Pattern> getSubPattern() {
|
||||
return this.subPattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,11 +21,11 @@ public class SourceFile extends SyntaxTreeNode {
|
||||
*/
|
||||
public SourceFile(String pkgName, List<ClassOrInterface> classDefinitions, Set<JavaClassName> imports) {
|
||||
super(new NullToken());
|
||||
if (classDefinitions.size() > 0) { // Enthält die Liste Klassen?
|
||||
//if (classDefinitions.size() > 0) { // Enthält die Liste Klassen?
|
||||
this.KlassenVektor = classDefinitions; // Klassen werden übernommen
|
||||
} else {
|
||||
this.KlassenVektor = null; // es handelt sich um ein "Java Module"
|
||||
}
|
||||
//} else {
|
||||
// this.KlassenVektor = null; // es handelt sich um ein "Java Module"
|
||||
//}
|
||||
this.pkgName = pkgName;
|
||||
this.imports = imports;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ public interface StatementVisitor {
|
||||
|
||||
void visit(BinaryExpr binary);
|
||||
|
||||
void visit(BoolExpression logical);
|
||||
|
||||
void visit(Block block);
|
||||
|
||||
void visit(CastExpr castExpr);
|
||||
@@ -41,8 +43,16 @@ public interface StatementVisitor {
|
||||
|
||||
void visit(ReturnVoid aReturn);
|
||||
|
||||
void visit(Switch switchStmt);
|
||||
|
||||
void visit(SwitchBlock switchBlock);
|
||||
|
||||
void visit(SwitchLabel switchLabel);
|
||||
|
||||
void visit(Break aBreak);
|
||||
|
||||
void visit(Yield aYield);
|
||||
|
||||
void visit(StaticClassName staticClassName);
|
||||
|
||||
void visit(Super aSuper);
|
||||
|
||||
@@ -1,27 +1,25 @@
|
||||
package de.dhbwstuttgart.syntaxtree.factory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.*;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
import de.dhbwstuttgart.bytecode.JavaTXSignatureAttribute;
|
||||
import de.dhbwstuttgart.parser.NullToken;
|
||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||
import de.dhbwstuttgart.syntaxtree.*;
|
||||
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 de.dhbwstuttgart.target.tree.type.TargetRefType;
|
||||
import de.dhbwstuttgart.util.Pair;
|
||||
import javassist.bytecode.SignatureAttribute;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.objectweb.asm.*;
|
||||
@@ -29,13 +27,15 @@ import org.objectweb.asm.signature.SignatureReader;
|
||||
import org.objectweb.asm.signature.SignatureVisitor;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* 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 {
|
||||
|
||||
private static final HashMap<java.lang.Class, ClassOrInterface> cache = new HashMap<>();
|
||||
|
||||
public static ClassOrInterface createClass(java.lang.Class jreClass) {
|
||||
if (cache.containsKey(jreClass))
|
||||
return cache.get(jreClass);
|
||||
|
||||
// TODO Inner classes
|
||||
|
||||
@@ -46,7 +46,7 @@ public class ASTFactory {
|
||||
try {
|
||||
var path = jreClass.getName().replace('.', '/') + ".class";
|
||||
var classLoader = jreClass.getClassLoader();
|
||||
if (classLoader != null) {
|
||||
if (classLoader != null && new File(path).exists()) {
|
||||
var bytes = IOUtils.toByteArray(Objects.requireNonNull(classLoader.getResourceAsStream(path)));
|
||||
var classReader = new ClassReader(bytes);
|
||||
var classVisitor = new ClassVisitor(Opcodes.ASM7) {
|
||||
@@ -88,7 +88,6 @@ public class ASTFactory {
|
||||
} catch (IOException e) {
|
||||
// Skip
|
||||
}
|
||||
|
||||
JavaClassName name = new JavaClassName(jreClass.getName());
|
||||
List<Method> methoden = new ArrayList<>();
|
||||
List<de.dhbwstuttgart.syntaxtree.Constructor> konstruktoren = new ArrayList<>();
|
||||
@@ -114,6 +113,12 @@ public class ASTFactory {
|
||||
}
|
||||
int modifier = jreClass.getModifiers();
|
||||
boolean isInterface = jreClass.isInterface();
|
||||
List<Annotation> aLA;
|
||||
boolean isFunctionalInterface =
|
||||
(aLA = Arrays.asList(jreClass.getAnnotations())).size() > 0 &&
|
||||
aLA.get(0) instanceof FunctionalInterface ?
|
||||
true :
|
||||
false;
|
||||
// see: https://stackoverflow.com/questions/9934774/getting-generic-parameter-from-supertype-class
|
||||
ParameterizedType parameterSuperClass = null;
|
||||
Type tempSuperClass = jreClass.getGenericSuperclass();
|
||||
@@ -132,12 +137,20 @@ public class ASTFactory {
|
||||
for (Type jreInterface : jreClass.getGenericInterfaces()) {
|
||||
implementedInterfaces.add((RefType) createType(jreInterface));
|
||||
}
|
||||
List<RefType> permittedSubtypes = new ArrayList<>();
|
||||
if (jreClass.isSealed()) {
|
||||
for (Class subclass : jreClass.getPermittedSubclasses()) {
|
||||
permittedSubtypes.add((RefType) createType(subclass));
|
||||
}
|
||||
}
|
||||
|
||||
GenericDeclarationList genericDeclarationList = createGenerics(jreClass.getTypeParameters(), jreClass, null, classSignature);
|
||||
|
||||
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);
|
||||
var cinf = new ClassOrInterface(modifier, name, felder, Optional.empty() /* eingefuegt PL 2018-11-24 */, Optional.empty(), methoden, konstruktoren, genericDeclarationList, superClass, isInterface, isFunctionalInterface, implementedInterfaces, permittedSubtypes, offset);
|
||||
cache.put(jreClass, cinf);
|
||||
return cinf;
|
||||
}
|
||||
|
||||
private static Field createField(java.lang.reflect.Field field, JavaClassName jreClass) {
|
||||
@@ -153,10 +166,11 @@ public class ASTFactory {
|
||||
RefTypeOrTPHOrWildcardOrGeneric returnType = createType(inClass);
|
||||
Parameter[] jreParams = constructor.getParameters();
|
||||
Type[] jreGenericParams = constructor.getGenericParameterTypes();
|
||||
List<FormalParameter> params = new ArrayList<>();
|
||||
List<Pattern> params = new ArrayList<>();
|
||||
int i = 0;
|
||||
for (Type jreParam : jreGenericParams) {
|
||||
if (jreParam == null) continue;
|
||||
if (jreParam == null)
|
||||
continue;
|
||||
RefTypeOrTPHOrWildcardOrGeneric paramType = createType(jreParam);
|
||||
params.add(new FormalParameter(jreParams[i].getName(), paramType, new NullToken()));
|
||||
i++;
|
||||
@@ -186,10 +200,11 @@ public class ASTFactory {
|
||||
returnType = createType(jreRetType);
|
||||
Parameter[] jreParams = jreMethod.getParameters();
|
||||
Type[] jreGenericParams = jreMethod.getGenericParameterTypes();
|
||||
List<FormalParameter> params = new ArrayList<>();
|
||||
List<Pattern> params = new ArrayList<>();
|
||||
int i = 0;
|
||||
for (Type jreParam : jreGenericParams) {
|
||||
if (jreParam == null) continue;
|
||||
if (jreParam == null)
|
||||
continue;
|
||||
RefTypeOrTPHOrWildcardOrGeneric paramType = createType(jreParam);
|
||||
params.add(new FormalParameter(jreParams[i].getName(), paramType, new NullToken()));
|
||||
i++;
|
||||
@@ -217,7 +232,8 @@ public class ASTFactory {
|
||||
}
|
||||
|
||||
public static GenericDeclarationList createGenerics(String signature) {
|
||||
if (signature == null) return new GenericDeclarationList(new ArrayList<>(), new NullToken());
|
||||
if (signature == null)
|
||||
return new GenericDeclarationList(new ArrayList<>(), new NullToken());
|
||||
|
||||
var gtvs = new ArrayList<GenericTypeVar>();
|
||||
var signatureVisitor = new SignatureVisitor(Opcodes.ASM7) {
|
||||
@@ -226,7 +242,8 @@ public class ASTFactory {
|
||||
final Stack<RefType> classTypes = new Stack<>();
|
||||
|
||||
// All hail the mighty visitor pattern
|
||||
final SignatureVisitor doNothing = new SignatureVisitor(Opcodes.ASM7) {};
|
||||
final SignatureVisitor doNothing = new SignatureVisitor(Opcodes.ASM7) {
|
||||
};
|
||||
|
||||
char wildcard = '=';
|
||||
|
||||
@@ -338,19 +355,19 @@ public class ASTFactory {
|
||||
if (type == null || 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());
|
||||
return new RefType(new JavaClassName("java.lang.Integer"), new ArrayList<>(), new NullToken(), true);
|
||||
} else if (type.getTypeName().equals("byte")) {
|
||||
return new RefType(new JavaClassName("java.lang.Byte"), new ArrayList<>(), new NullToken());
|
||||
return new RefType(new JavaClassName("java.lang.Byte"), new ArrayList<>(), new NullToken(), true);
|
||||
} else if (type.getTypeName().equals("boolean")) {
|
||||
return new RefType(new JavaClassName("java.lang.Boolean"), new ArrayList<>(), new NullToken());
|
||||
return new RefType(new JavaClassName("java.lang.Boolean"), new ArrayList<>(), new NullToken(), true);
|
||||
} else if (type.getTypeName().equals("char")) {
|
||||
return new RefType(new JavaClassName("java.lang.Char"), new ArrayList<>(), new NullToken());
|
||||
return new RefType(new JavaClassName("java.lang.Char"), new ArrayList<>(), new NullToken(), true);
|
||||
} else if (type.getTypeName().equals("short")) {
|
||||
return new RefType(new JavaClassName("java.lang.Short"), new ArrayList<>(), new NullToken());
|
||||
return new RefType(new JavaClassName("java.lang.Short"), new ArrayList<>(), new NullToken(), true);
|
||||
} else if (type.getTypeName().equals("double")) {
|
||||
return new RefType(new JavaClassName("java.lang.Double"), new ArrayList<>(), new NullToken());
|
||||
return new RefType(new JavaClassName("java.lang.Double"), new ArrayList<>(), new NullToken(), true);
|
||||
} else if (type.getTypeName().equals("long")) {
|
||||
return new RefType(new JavaClassName("java.lang.Long"), new ArrayList<>(), new NullToken());
|
||||
return new RefType(new JavaClassName("java.lang.Long"), new ArrayList<>(), new NullToken(), true);
|
||||
} else {
|
||||
if (type instanceof TypeVariable) {
|
||||
// GTVDeclarationContext via "(TypeVariable) type).getGenericDeclaration()"
|
||||
@@ -404,48 +421,26 @@ public class ASTFactory {
|
||||
}
|
||||
|
||||
/*
|
||||
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("<init>", 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<String> 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<Method>(), new ArrayList<Field>(), modifiers,
|
||||
true, superClass, new ArrayList<RefType>(), new GenericDeclarationList(), -1);
|
||||
generatedClass.parserPostProcessing(parent);
|
||||
return generatedClass;
|
||||
}
|
||||
|
||||
public static RefType createObjectType(){
|
||||
return createObjectClass().getType();
|
||||
}
|
||||
* 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("<init>", 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<String> 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<Method>(), new ArrayList<Field>(), modifiers, true, superClass, new ArrayList<RefType>(), new GenericDeclarationList(), -1); generatedClass.parserPostProcessing(parent); return generatedClass; }
|
||||
*
|
||||
* public static RefType createObjectType(){ return createObjectClass().getType(); }
|
||||
*/
|
||||
}
|
||||
@@ -15,8 +15,8 @@ public class BinaryExpr extends Expression {
|
||||
SUB, // -
|
||||
MUL, // *
|
||||
MOD, // Modulo Operator %
|
||||
AND, // &&
|
||||
OR, // ||
|
||||
AND, // &
|
||||
OR, // |
|
||||
DIV, // /
|
||||
LESSTHAN, // <
|
||||
BIGGERTHAN, // >
|
||||
|
||||
@@ -1,26 +1,22 @@
|
||||
package de.dhbwstuttgart.syntaxtree.statement;
|
||||
import java.util.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.antlr.v4.runtime.Token;
|
||||
|
||||
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 class Block extends Statement {
|
||||
public Block(List<Statement> statements, Token offset) {
|
||||
super(TypePlaceholder.fresh(offset), offset);
|
||||
this.statements = statements;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public List<Statement> statements = new ArrayList<>();
|
||||
|
||||
public List<Statement> getStatements()
|
||||
{
|
||||
public List<Statement> getStatements() {
|
||||
return statements;
|
||||
}
|
||||
|
||||
@@ -29,5 +25,3 @@ public class Block extends Statement
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package de.dhbwstuttgart.syntaxtree.statement;
|
||||
|
||||
import org.antlr.v4.runtime.Token;
|
||||
|
||||
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||
|
||||
public class BoolExpression extends Expression {
|
||||
|
||||
public enum Operator {
|
||||
AND, // &&
|
||||
OR, // ||
|
||||
}
|
||||
|
||||
public final Operator operation;
|
||||
public final Expression lexpr;
|
||||
public final Expression rexpr;
|
||||
|
||||
public BoolExpression(Operator operation, RefTypeOrTPHOrWildcardOrGeneric type, Expression lexpr, Expression rexpr, Token offset) {
|
||||
super(type, offset);
|
||||
this.operation = operation;
|
||||
this.lexpr = lexpr;
|
||||
this.rexpr = rexpr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(StatementVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,7 +13,7 @@ public class Break extends Statement {
|
||||
|
||||
@Override
|
||||
public void accept(StatementVisitor visitor) {
|
||||
this.accept((StatementVisitor) visitor);
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,8 +9,7 @@ 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 abstract class Expression extends TypableStatement {
|
||||
public Expression(RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
|
||||
super(type, offset);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user