Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32ddb1132f | ||
|
|
174c999543 | ||
|
|
4b576da19d | ||
|
|
942b8ca488 | ||
|
|
de96cda327 | ||
|
|
2710685db3 | ||
|
|
e951a60ae6 | ||
|
|
825df05fac | ||
|
|
fab3e73596 | ||
|
|
392c5fa619 | ||
|
|
e21d2d7ced | ||
|
|
5a12545e8f | ||
|
|
d6c59f07f6 | ||
|
|
eb1c5c6629 | ||
|
|
a5c8d93e4c | ||
|
|
e70f071c63 | ||
|
|
4c203d9ded | ||
|
|
f66499b4fe | ||
|
|
eb05d22735 | ||
|
|
dfe90bfa2d | ||
|
|
719e1ab4a2 | ||
|
|
1e32f69952 | ||
|
|
65d5d79078 | ||
|
|
ca81cfd587 | ||
|
|
0998d231fe | ||
|
|
78a8f82325 | ||
|
|
20b974fd2a | ||
|
|
a504743a40 | ||
|
|
70764640d6 | ||
|
|
090263b6ca | ||
|
|
2e5447c06b | ||
|
|
1fb9dcd691 | ||
|
|
2e238efbc5 | ||
|
|
c375235680 | ||
|
|
d5c0d653d2 | ||
|
|
f7e5a1f8a2 | ||
|
|
8f6e6e1980 | ||
|
|
912f3d381e | ||
|
|
7e24bbd552 | ||
|
|
50f2572644 | ||
|
|
e1518c8b37 | ||
|
|
f7a85db191 | ||
|
|
41d5f661e1 | ||
|
|
b7f46c428f | ||
|
|
8ab87b3e8d | ||
|
|
8aa5e65d15 | ||
|
|
ee295d876a | ||
|
|
075be2939f | ||
|
|
8c0d0c6b47 | ||
|
|
9035633568 | ||
|
|
ea3ce98530 | ||
|
|
bcd0c28038 | ||
|
|
9657ef5691 | ||
|
|
88db5f9eb7 | ||
|
|
8c5228f8c5 | ||
|
|
3a9a2576a2 | ||
|
|
0f7ffe5381 | ||
|
|
2e7b536d9d | ||
|
|
654c8d6df8 | ||
|
|
30dd045a7c | ||
|
|
5dccbffebd | ||
|
|
9b762470b5 | ||
|
|
85ee805a3f | ||
|
|
523452f437 | ||
|
|
7051b4335a | ||
|
|
7daec0a291 | ||
|
|
76f2048797 | ||
|
|
653f704265 | ||
|
|
b36ba5e128 | ||
|
|
a43f49cadb | ||
|
|
69292c37fc | ||
|
|
218e704272 | ||
|
|
e83e9a041c | ||
|
|
a1195b689d | ||
|
|
3cd61778d6 | ||
|
|
021d3e1b27 | ||
|
|
c90f01d5db | ||
|
|
8b3b018ea9 | ||
|
|
210adaa493 | ||
|
|
2f7e4fc1e4 | ||
|
|
433dcf83c2 |
No files matched your search
Binary file not shown.
@@ -0,0 +1,19 @@
|
|||||||
|
import java.util.stream.Stream;
|
||||||
|
import Pair;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class Kombinatoren_After {
|
||||||
|
|
||||||
|
|
||||||
|
after (fst, snd) { //System.out.println("after2");
|
||||||
|
|
||||||
|
return () -> Stream.of(
|
||||||
|
toks -> {
|
||||||
|
return fst.apply().flatMap(x ->
|
||||||
|
x.apply(toks).flatMap(p1 ->
|
||||||
|
snd.apply().flatMap(y -> y.apply(p1.snd()).map(p2 ->
|
||||||
|
new Pair<>(new Pair<>(p1.fst(), p2.fst()), p2.snd()))))); } );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import java.util.stream.Stream;
|
||||||
|
import Pair;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class Kombinatoren_After_Lazy {
|
||||||
|
|
||||||
|
|
||||||
|
afterP (fst, snd) {
|
||||||
|
return toks -> {
|
||||||
|
return fst.apply(toks).flatMap(p1 ->
|
||||||
|
snd.apply(p1.snd()).map(p2 ->
|
||||||
|
new Pair<>(new Pair<>(p1.fst(), p2.fst()), p2.snd())));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import java.util.stream.Stream;
|
||||||
|
import Pair;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class Kombinatoren_Or {
|
||||||
|
|
||||||
|
|
||||||
|
orP (p1, p2) {
|
||||||
|
return ()-> Stream.concat(p1.apply(), p2.apply());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
after (fst, snd) { //System.out.println("after2");
|
||||||
|
|
||||||
|
return () -> Stream.of(
|
||||||
|
toks -> {
|
||||||
|
return fst.apply().flatMap(x ->
|
||||||
|
x.apply(toks).flatMap(p1 ->
|
||||||
|
snd.apply().flatMap(y -> y.apply(p1.snd()).map(p2 ->
|
||||||
|
new Pair<>(new Pair<>(p1.fst(), p2.fst()), p2.snd()))))); } );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
trans (p, f) {
|
||||||
|
return () -> p.apply().map(x -> (toks -> x.apply(toks).map(pr -> new Pair<>(f.apply(pr.fst()), pr.snd() ) ) ) );
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
import java.util.stream.Stream;
|
||||||
|
//import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.lang.System;
|
||||||
|
|
||||||
|
//import java.lang.String;
|
||||||
|
import java.lang.Boolean;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import Pair;
|
||||||
|
import Kombinatoren_failure;
|
||||||
|
|
||||||
|
public class Kombinatoren_Satisfy {
|
||||||
|
|
||||||
|
kb = new Kombinatoren_failure();
|
||||||
|
|
||||||
|
satisfy(cond) {
|
||||||
|
// return () -> Stream.of (newToks -> new Kombinatoren_failure().failure().apply().map(x -> x.apply(newToks)));
|
||||||
|
//}
|
||||||
|
return () -> Stream.of (toks -> {
|
||||||
|
if(toks.isEmpty()) {
|
||||||
|
return new ArrayList<>().stream();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var fst = toks.getFirst();
|
||||||
|
if (cond.apply(fst))
|
||||||
|
{
|
||||||
|
//var newToks = List.copyOf(toks.subList(1, toks.size()));
|
||||||
|
var newToks = new ArrayList<>(toks);
|
||||||
|
return newToks.removeFirst();
|
||||||
|
kb.getContent(
|
||||||
|
kb.succeed(fst).apply().map(x -> x.apply(newToks))
|
||||||
|
);
|
||||||
|
// ;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/* () -> Stream.of (toks -> {
|
||||||
|
//System.out.println(toks);
|
||||||
|
if(toks.isEmpty())
|
||||||
|
{
|
||||||
|
return new ArrayList<>().stream();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var fst = toks.getFirst();
|
||||||
|
if (cond.apply(fst))
|
||||||
|
{
|
||||||
|
var newToks = List.copyOf(toks.subList(1, toks.size()));
|
||||||
|
//System.out.println("satisfy ok " + fst.toString());
|
||||||
|
//return get(succeed(fst).apply().map(x -> x.apply(newToks)));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//System.out.println("satisfy failure " + fst.toString());
|
||||||
|
//return get(failure().apply()).apply(toks);
|
||||||
|
}
|
||||||
|
return new ArrayList<>().stream();
|
||||||
|
} } ) ;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import java.util.stream.Stream;
|
||||||
|
import Pair;
|
||||||
|
//import java.util.function.Function;
|
||||||
|
|
||||||
|
public class Kombinatoren_Trans {
|
||||||
|
|
||||||
|
|
||||||
|
trans (p, f) {
|
||||||
|
return () -> p.apply().map(x -> (toks -> x.apply(toks).map(pr -> new Pair<>(f.apply(pr.fst()), pr.snd() ) ) ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import java.util.stream.Stream;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.lang.System;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import java.lang.String;
|
||||||
|
import java.lang.Boolean;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import Pair;
|
||||||
|
|
||||||
|
|
||||||
|
public class Kombinatoren_failure {
|
||||||
|
public getContent(s) {
|
||||||
|
return s.toList().getFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
public failure() {
|
||||||
|
return () -> Stream.of(
|
||||||
|
toks -> new ArrayList<>().stream());
|
||||||
|
}
|
||||||
|
public succeed( value) {
|
||||||
|
return () -> Stream.of(toks -> {
|
||||||
|
//System.out.println("succeed");
|
||||||
|
var al = new ArrayList<>();
|
||||||
|
al.add(new Pair<>(value, toks));
|
||||||
|
//al.forEach(x -> { System.out.println(x.toString());});
|
||||||
|
return al.stream();});
|
||||||
|
}
|
||||||
|
|
||||||
|
parser(p, inp) {
|
||||||
|
return p.map(y -> y.apply(
|
||||||
|
inp.chars().mapToObj(c -> (char) c)
|
||||||
|
.collect(Collectors.toList())))
|
||||||
|
.flatMap(x -> x)
|
||||||
|
.filter(x -> x.snd().isEmpty())
|
||||||
|
.findFirst()
|
||||||
|
.get()
|
||||||
|
.fst();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
|
||||||
|
satisfy(cond) {
|
||||||
|
return newToks -> failure().apply().map(x -> x.apply(newToks));
|
||||||
|
/*
|
||||||
|
return () -> Stream.of (toks -> {
|
||||||
|
if(toks.isEmpty()) {
|
||||||
|
return new ArrayList<>().stream();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var fst = toks.getFirst();
|
||||||
|
if (cond.apply(fst)) {
|
||||||
|
var newToks = List.copyOf(toks.subList(1, toks.size()));
|
||||||
|
this.getContent(
|
||||||
|
succeed(fst)
|
||||||
|
.apply().map(x -> x.apply(newToks))
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
@@ -1,36 +1,24 @@
|
|||||||
import java.util.Vector;
|
|
||||||
import java.lang.Boolean;
|
import java.lang.Boolean;
|
||||||
import java.lang.Object;
|
import java.lang.Object;
|
||||||
|
|
||||||
class Pair<U, T> {
|
import java.util.List;
|
||||||
U a;
|
|
||||||
T b;
|
|
||||||
|
|
||||||
make(x) {
|
class Pair<T, U> {
|
||||||
var ret = new Pair<>();
|
T a;
|
||||||
ret.a = x.elementAt(0);
|
U b;
|
||||||
ret.b = x.elementAt(1);
|
|
||||||
return ret;
|
public Pair() { }
|
||||||
|
public Pair(T a, U b) {
|
||||||
|
this.a = a;
|
||||||
|
this.b = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public T fst () {
|
||||||
eq(a, b) {
|
return a;
|
||||||
b = a;
|
|
||||||
return a == b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public U snd () {
|
||||||
compare( p) {
|
return b;
|
||||||
return eq(p.a, p.b);
|
|
||||||
//return p.a == p.b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
void m(Pair<?, ?> p, Vector<?> b)
|
|
||||||
{
|
|
||||||
//this.compare(p); //1, type incorrect
|
|
||||||
this.compare(this.make(b)); //2, OK
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
Executable
+27
@@ -0,0 +1,27 @@
|
|||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class Pair<T, U> {
|
||||||
|
T a;
|
||||||
|
U b;
|
||||||
|
|
||||||
|
public Pair() { }
|
||||||
|
public Pair(T a, U b) {
|
||||||
|
System.out.println("Pair a; " + a + " b: " + b);
|
||||||
|
this.a = a;
|
||||||
|
this.b = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T fst () {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public U snd () {
|
||||||
|
System.out.println("snd b: " + b);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "Pair<"+a.toString()+","+b.toString()+">";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
import java.util.stream.Stream;
|
||||||
|
//import java.util.stream.IntStream;
|
||||||
|
//import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.lang.System;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.lang.Character;
|
||||||
|
import java.lang.String;
|
||||||
|
import java.lang.Boolean;
|
||||||
|
import java.lang.Integer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
//import java.util.function.IntFunction;
|
||||||
|
|
||||||
|
import Pair;
|
||||||
|
|
||||||
|
|
||||||
|
public class Parser {
|
||||||
|
|
||||||
|
|
||||||
|
strToList(s) {
|
||||||
|
var al;
|
||||||
|
al = new ArrayList<>();
|
||||||
|
var i = 0;
|
||||||
|
while (i < s.length()) {
|
||||||
|
al.add(s.charAt(i));
|
||||||
|
i=i+1;
|
||||||
|
}
|
||||||
|
return al;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
|
||||||
|
parser(p, inp) {
|
||||||
|
return p.map(y -> y.apply(
|
||||||
|
strToList(inp)//chars().mapToObj(c -> (Character) c)
|
||||||
|
//.toList()
|
||||||
|
))
|
||||||
|
|
||||||
|
//.flatMap(x -> x)
|
||||||
|
|
||||||
|
//.filter(x -> x.snd().isEmpty())
|
||||||
|
;
|
||||||
|
/*
|
||||||
|
.findFirst()
|
||||||
|
.get()
|
||||||
|
.fst()
|
||||||
|
|
||||||
|
;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
satisfy(cond) {
|
||||||
|
return newToks -> failure().apply().map(x -> x.apply(newToks));
|
||||||
|
/*
|
||||||
|
return () -> Stream.of (toks -> {
|
||||||
|
if(toks.isEmpty()) {
|
||||||
|
return new ArrayList<>().stream();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var fst = toks.getFirst();
|
||||||
|
if (cond.apply(fst)) {
|
||||||
|
var newToks = List.copyOf(toks.subList(1, toks.size()));
|
||||||
|
this.getContent(
|
||||||
|
succeed(fst)
|
||||||
|
.apply().map(x -> x.apply(newToks))
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
@@ -2,7 +2,7 @@ import java.lang.String;
|
|||||||
import java.lang.Object;
|
import java.lang.Object;
|
||||||
|
|
||||||
public class Bug365{
|
public class Bug365{
|
||||||
swap(f){
|
swap(Fun1$$<String, Fun1$$<String, Object>> f){
|
||||||
return x -> y -> f.apply(y).apply(x);
|
return x -> y -> f.apply(y).apply(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18,4 +18,8 @@ public class Bug365{
|
|||||||
var func = x -> y -> z -> x + y + z;
|
var func = x -> y -> z -> x + y + z;
|
||||||
return swap(func).apply("A").apply("B").apply("C");
|
return swap(func).apply("A").apply("B").apply("C");
|
||||||
}
|
}
|
||||||
|
public ex3() {
|
||||||
|
var func = x -> y -> x + y;
|
||||||
|
return swap(func).apply("A").apply("B");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
sealed interface List<T> permits Cons, Empty {}
|
sealed interface List<T> permits Cons, Empty {}
|
||||||
record Cons<T>(T a , List<T> l ) implements List <T> {}
|
record Cons<T>(T a, List<T> l ) implements List <T> {}
|
||||||
record Empty<T>() implements List <T> {}
|
record Empty<T>() implements List <T> {}
|
||||||
|
|
||||||
public class Bug380 {
|
public class Bug380 {
|
||||||
public <T> List<T> append(l1, List<T> l2) {
|
public <T> List<T> append(List<T> l1, List<T> l2) {
|
||||||
return switch ( l1 ) {
|
return switch ( l1 ) {
|
||||||
case Cons(e, rest) -> new Cons<>(e, append(rest, l2)); //::Typ TPH A
|
case Cons(e, rest) -> new Cons<>(e, append(rest, l2)); //::Typ TPH A
|
||||||
case Empty() -> l2;//::TPH B
|
case Empty() -> l2;//::TPH B
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
public class Bug389 {
|
||||||
|
//public swap(f) {
|
||||||
|
// return x -> y -> f.apply(y).apply(x);
|
||||||
|
//}
|
||||||
|
public swap(f) {
|
||||||
|
return x -> y -> z -> f.apply(z).apply(x).apply(y);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import Bug389;
|
||||||
|
import java.util.List;
|
||||||
|
import java.lang.Integer;
|
||||||
|
|
||||||
|
public class Bug389Main {
|
||||||
|
public static main(args) {
|
||||||
|
var func = (Integer x) -> y -> z -> x + y + z;
|
||||||
|
var swap = new Bug389();
|
||||||
|
swap.swap(func).apply(1).apply(2).apply(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import java.lang.Integer;
|
||||||
|
|
||||||
|
public class Bug395 {
|
||||||
|
dup(x) {
|
||||||
|
//Hier beliebiger Seiteneffekt
|
||||||
|
return x + x;
|
||||||
|
}
|
||||||
|
|
||||||
|
dup(s) {
|
||||||
|
return s + s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
//package de.dhbwstuttgart;
|
||||||
|
|
||||||
|
import java.lang.Integer;
|
||||||
|
import java.lang.IO;
|
||||||
|
|
||||||
|
public sealed interface IntList permits Empty, Cons{}
|
||||||
|
public record Empty() implements IntList {}
|
||||||
|
public record Cons(Integer a, IntList rest) implements IntList {}
|
||||||
|
|
||||||
|
public class Bug406 {
|
||||||
|
|
||||||
|
public head(Empty()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
public head(Cons(e,r)) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public append(Empty(), ys) {
|
||||||
|
return ys;
|
||||||
|
}
|
||||||
|
public append(Cons(x, xs), IntList ys) {
|
||||||
|
return new Cons(x, append(xs, ys));
|
||||||
|
}
|
||||||
|
|
||||||
|
public add(x, y) {
|
||||||
|
return x + y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static main(args) {
|
||||||
|
|
||||||
|
var list1 = new Cons(1, new Cons(2, new Cons(3, new Empty())));
|
||||||
|
var list2 = new Cons(4, new Cons(5, new Cons(6, new Empty())));
|
||||||
|
|
||||||
|
IO.println(new Bug406().add(1, 2));
|
||||||
|
IO.println(new Bug406().append(list1, list2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import java.lang.Integer;
|
||||||
|
|
||||||
|
public class Bug409 {
|
||||||
|
public static m() {
|
||||||
|
var n = 0;
|
||||||
|
for (var i = 0; i < 5; i++) {
|
||||||
|
n = n + 1;
|
||||||
|
if (n > 100) { return -1; }
|
||||||
|
if (i == 2) { continue; }
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import java.lang.Integer;
|
||||||
|
|
||||||
|
public class Bug412 {
|
||||||
|
public m(Integer i) {
|
||||||
|
var r = 0;
|
||||||
|
switch (i) {
|
||||||
|
case 1: r = 10; break;
|
||||||
|
default: r = 20;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import java.lang.Integer;
|
||||||
|
import java.lang.String;
|
||||||
|
|
||||||
|
public class Bug417 {
|
||||||
|
public name(Integer i) {
|
||||||
|
return switch (i) {
|
||||||
|
case 1 -> "one";
|
||||||
|
default -> "many";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
public class Bug421 {
|
||||||
|
public m() { return 1 } // Missing semicolon
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
public class Bug422 {}
|
||||||
|
public class Bug422 {}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import java.lang.Integer;
|
||||||
|
|
||||||
|
interface Bug423I { Integer f(); }
|
||||||
|
|
||||||
|
public class Bug423 implements Bug423I { }
|
||||||
@@ -4,7 +4,7 @@ import java.lang.String;
|
|||||||
|
|
||||||
public class Fac {
|
public class Fac {
|
||||||
getFac(n) {
|
getFac(n) {
|
||||||
var res = 1;
|
Double res = 1;
|
||||||
var i = 1;
|
var i = 1;
|
||||||
while (i <= n) {
|
while (i <= n) {
|
||||||
res = res * i;
|
res = res * i;
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
import java.lang.String;
|
import java.lang.String;
|
||||||
import java.lang.Integer;
|
import java.lang.Integer;
|
||||||
|
|
||||||
sealed interface List permits LinkedElem, Elem {}
|
sealed interface List<T> permits LinkedElem, Elem {}
|
||||||
|
public record LinkedElem<T>(T a, List<T> l) implements List<T>{}
|
||||||
|
public record Elem<T>(T c) implements List<T>{}
|
||||||
public record LinkedElem<T>(T a,List l) implements List{}
|
|
||||||
public record Elem<T>(T c) implements List{}
|
|
||||||
|
|
||||||
public class GenericRecordSwitchCase {
|
public class GenericRecordSwitchCase {
|
||||||
public main(o) {
|
public main(o) {
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
import java.lang.System;
|
import java.lang.System;
|
||||||
import java.lang.String;
|
import java.lang.String;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
|
import java.lang.Object;
|
||||||
|
|
||||||
public class HelloWorld {
|
public class HelloWorld {
|
||||||
public static hello() {
|
public static hello() {
|
||||||
System.out.println("Hello World!");
|
System.out.println("Hello World!");
|
||||||
|
System.out.println("Bye World!");
|
||||||
|
System.out.println("The end!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -15,6 +15,7 @@ interface C {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ClassX implements A {
|
class ClassX implements A {
|
||||||
|
void method1() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
record ClassY(Integer myInt) implements C {}
|
record ClassY(Integer myInt) implements C {}
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
//Grundsaetzlich wird Lazy-Evaluation so realisiert, dass immer beim
|
||||||
|
//Methoden/Konstruktor-Aufruf das Argument in einen Lambda-Ausdruck (Supplier)
|
||||||
|
//eingepackt wird (siehe Aufruf von Cons und Empty in Count und main) und
|
||||||
|
//ein Lazy-Argument mit get ausgerollt wird (siehe Methode rest)
|
||||||
|
|
||||||
|
import java.lang.Integer;
|
||||||
|
import java.lang.Boolean;
|
||||||
|
import java.lang.String;
|
||||||
|
import java.lang.System;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
public sealed interface LazyList permits Empty, Cons {
|
||||||
|
public Integer fst();
|
||||||
|
public LazyList rest();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Filter {
|
||||||
|
/*public LazyList filter(Fun1$$<Integer, Boolean> p, LazyList l) {
|
||||||
|
return switch(l) {
|
||||||
|
case Empty e -> e;
|
||||||
|
case Cons(Integer x, Supplier<LazyList> l1) ->
|
||||||
|
p.apply(x) ? new Cons(x, () -> filter(p, l1.get())) : filter(p, l1.get());
|
||||||
|
};
|
||||||
|
}*/
|
||||||
|
public LazyList filter(Fun1$$<Integer, Boolean> p, Empty()@l) {
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LazyList filter(Fun1$$<Integer, Boolean> p, Cons(Integer x, l1)) {
|
||||||
|
return p.apply(x) ? new Cons(x, () -> filter(p, l1.apply())) : filter(p, l1.apply());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Der Konstruktor Cons muss lazy sein, deshalb hier Supplier<...>
|
||||||
|
record Cons(Integer x, Fun0$$<LazyList> l) implements LazyList {
|
||||||
|
public Integer fst() { return this.x; }
|
||||||
|
public LazyList rest() { return this.l.apply(); }
|
||||||
|
public String toString() {
|
||||||
|
return "Cons(" + this.x.toString() + ", " + this.l.apply().toString() + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record Empty() implements LazyList {
|
||||||
|
public Integer fst() { return -1; }
|
||||||
|
public LazyList rest() { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Main {
|
||||||
|
static LazyList Count(int i) { return new Cons(i, () -> Count(i+1)); }
|
||||||
|
|
||||||
|
public static void main(args) {
|
||||||
|
System.out.println(new Cons(1, () -> new Cons(2, () -> new Empty())).fst());
|
||||||
|
System.out.println(Count(1).rest().fst());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,4 +5,8 @@ public class Literal {
|
|||||||
public m2() { return 'C'; }
|
public m2() { return 'C'; }
|
||||||
public m3() { return 10L; }
|
public m3() { return 10L; }
|
||||||
public m4() { return 10.5F; }
|
public m4() { return 10.5F; }
|
||||||
|
public m5() { return 10.5D; }
|
||||||
|
public m6() { return 0xFF; }
|
||||||
|
public m7() { return 0b101010; }
|
||||||
|
public m8() { return 010; }
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
sealed interface Interface permits A, B {}
|
||||||
|
public record A() implements Interface {}
|
||||||
|
public record B() implements Interface {}
|
||||||
|
|
||||||
|
public interface Matcher {
|
||||||
|
default match(A()@a) { return 0; }
|
||||||
|
default match(B()@b) { return 1; }
|
||||||
|
}
|
||||||
@@ -1,25 +1,13 @@
|
|||||||
sealed interface List<T> permits Cons, Empty {}
|
public sealed interface List<T> permits Cons, Empty {}
|
||||||
|
|
||||||
public record Cons<T>(T a, List<T> l) implements List<T> {}
|
public record Cons<T>(T a, List<T> l) implements List<T> {}
|
||||||
public record Empty<T>() implements List<T> {}
|
public record Empty<T>() implements List<T> {}
|
||||||
public record Tuple<T1, T2>(T1 a, T2 b) {}
|
public record Pair<T1, T2>(T1 a, T2 b) {}
|
||||||
|
|
||||||
public class PatternMatching {
|
public class PatternMatching {
|
||||||
public zip(Cons(x, xs), Cons(y, ys)) {
|
// Anmerkung: Typ muss angegeben werden
|
||||||
return new Cons(new Tuple(x, y), zip(xs, ys));
|
public <A, B> Cons<Pair<A, B>> zip(Cons(x, xs), Cons(y, ys)) {
|
||||||
|
return new Cons<>(new Pair<>(x, y), zip(xs, ys));
|
||||||
}
|
}
|
||||||
public zip(Empty x, Empty y) { return new Empty(); }
|
public zip(Empty(), Empty()) { return new Empty<>(); }
|
||||||
|
|
||||||
/*public zip(Empty x, Cons y) { return new Empty(); }
|
|
||||||
public zip(Cons x, Empty y) { return new Empty(); }
|
|
||||||
public zip(Empty x, Empty y) { return new Empty(); }
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
Generiert:
|
|
||||||
Cons zip<T>(Cons(T x, Cons xs), Cons(T y, Cons ys))
|
|
||||||
Cons zip<T>(Cons(T x, Cons xs), Cons(T y, Empty ys))
|
|
||||||
Cons zip<T>(Cons(T x, Empty xs), Cons(T y, Cons ys))
|
|
||||||
Cons zip<T>(Cons(T x, Empty xs), Cons(T y, Empty ys))
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import java.lang.Integer;
|
||||||
|
import java.lang.Object;
|
||||||
|
|
||||||
|
public interface Base {
|
||||||
|
Object value();
|
||||||
|
}
|
||||||
|
public record R(Integer a) implements Base {
|
||||||
|
public Object value() { return this.a; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PatternMatchingCaptures {
|
||||||
|
public test1(Base R(a)@r) {
|
||||||
|
return r.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
public test2(Base R(a)) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public test3(R(a)@r) {
|
||||||
|
return r.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public test4(R(a)) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public test5(R r) {
|
||||||
|
return r.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public test6(r) {
|
||||||
|
return r.a;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import java.lang.Integer;
|
||||||
|
|
||||||
|
import Matcher;
|
||||||
|
import Interface;
|
||||||
|
|
||||||
|
public class M implements Matcher {}
|
||||||
|
|
||||||
|
public class PatternMatchingInterface {
|
||||||
|
public static match(matcher, v) {
|
||||||
|
return matcher.match(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,18 +2,24 @@ import java.lang.Object;
|
|||||||
import List;
|
import List;
|
||||||
import Cons;
|
import Cons;
|
||||||
import Empty;
|
import Empty;
|
||||||
import Tuple;
|
import Pair;
|
||||||
|
|
||||||
public class PatternMatchingJava {
|
public class PatternMatchingJava {
|
||||||
public zip(a, b) {
|
public <A, B> Cons<Pair<A, B>> zip(Cons<A> a, Cons<B> b) {
|
||||||
switch (a) {
|
switch (a) {
|
||||||
case Cons(x, Cons xs) -> {
|
case Cons(x, Cons xs) -> {
|
||||||
switch (b) {
|
switch (b) {
|
||||||
case Cons(y, Cons ys) -> { return new Cons<>(new Tuple<>(x, y), zip(xs, ys)); }
|
case Cons(y, Cons ys) -> { return new Cons<>(new Pair<>(x, y), zip(xs, ys)); }
|
||||||
case Cons(y, Empty()) -> { return new Empty<>(); }
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case Cons(x, Empty()) -> { return new Empty<>(); }
|
case Cons(x, Empty xs) -> {
|
||||||
|
switch (b) {
|
||||||
|
case Cons(y, Empty ys) -> { return new Cons<>(new Pair<>(x, y), zip(xs, ys)); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public <A, B> Empty<Pair<A, B>> zip(Empty<A> a, Empty<B>) {
|
||||||
|
return new Empty<>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
sealed interface List<T> permits Cons, Empty {}
|
public sealed interface List<T> permits Cons, Empty {}
|
||||||
|
|
||||||
public record Cons<T>(T a, List<T> l) implements List<T> {}
|
public record Cons<T>(T a, List<T> l) implements List<T> {}
|
||||||
public record Empty<T>() implements List<T> {}
|
public record Empty<T>() implements List<T> {}
|
||||||
public record Tuple<T1, T2>(T1 a, T2 b) {}
|
public record Pair<T1, T2>(T1 a, T2 b) {}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import java.lang.Boolean;
|
import java.lang.Boolean;
|
||||||
import java.lang.Object;
|
import java.lang.Object;
|
||||||
|
|
||||||
sealed interface List<T> permits Cons, Empty {}
|
public sealed interface List<T> permits Cons, Empty {}
|
||||||
|
|
||||||
public record Cons<T>(T a, List<T> l) implements List<T> {}
|
public record Cons<T>(T a, List<T> l) implements List<T> {}
|
||||||
public record Empty<T>() implements List<T> {}
|
public record Empty<T>() implements List<T> {}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import java.lang.Integer;
|
||||||
|
import java.lang.Number;
|
||||||
|
|
||||||
|
public record R(Number n) {}
|
||||||
|
|
||||||
|
public class PatternMatchingSpecificity {
|
||||||
|
public m(R(Number n)) { return 0; }
|
||||||
|
public m(R(Integer i)) { return 1; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import java.lang.Integer;
|
||||||
|
import java.lang.String;
|
||||||
|
import java.lang.System;
|
||||||
|
import java.lang.Boolean;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
import LazyList;
|
||||||
|
import Cons;
|
||||||
|
import Empty;
|
||||||
|
import Filter;
|
||||||
|
|
||||||
|
public class Primzahlen {
|
||||||
|
static LazyList from(Integer i) { return new Cons(i, () -> from(i+1)); }
|
||||||
|
|
||||||
|
/*LazyList filter(Fun1$$<Integer, Boolean> p, LazyList l) {
|
||||||
|
return switch(l) {
|
||||||
|
case Empty e -> e;
|
||||||
|
case Cons(Integer x, Fun0$$<LazyList> l1) ->
|
||||||
|
p.apply(x) ? new Cons(x, () -> filter(p, l1.apply())) : filter(p, l1.apply());
|
||||||
|
};
|
||||||
|
}*/
|
||||||
|
|
||||||
|
LazyList dropMul(Integer x, LazyList xs) {
|
||||||
|
return new Filter().filter(y -> (y % x != 0), xs);
|
||||||
|
}
|
||||||
|
|
||||||
|
LazyList del(LazyList xs) {
|
||||||
|
return new Cons(xs.fst(), () -> del(dropMul(xs.fst(), xs.rest())));
|
||||||
|
}
|
||||||
|
|
||||||
|
LazyList primes() {
|
||||||
|
return del(from(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
LazyList take(Integer n, LazyList l) {
|
||||||
|
if (n == 0) return new Empty();
|
||||||
|
else return switch (l) {
|
||||||
|
case Empty() -> l;
|
||||||
|
case Cons(Integer x, l1) ->
|
||||||
|
new Cons(x, () -> take(n-1, l1.apply()));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
public static void main(args) {
|
||||||
|
System.out.println(new Cons(1, () -> new Cons(2, () -> new Empty())).fst());
|
||||||
|
var l = new Cons(1, () -> new Cons(2, () -> new Cons(2, () -> new Empty())));
|
||||||
|
System.out.println(l);
|
||||||
|
var filtered = new Filter().filter(x -> x == 2, l);
|
||||||
|
System.out.println(filtered);
|
||||||
|
//System.out.println(from(1).rest().fst());
|
||||||
|
//Primzahlen pz = new Primzahlen();
|
||||||
|
//System.out.println(pz.take(10, pz.from(2)));
|
||||||
|
//System.out.println(pz.take(14, pz.primes()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import java.lang.Integer;
|
||||||
|
|
||||||
|
public record RecordTestInstanceVariables(Integer a, Integer b) {
|
||||||
|
public Integer getA() { return a; }
|
||||||
|
public Integer getB() { return b; }
|
||||||
|
}
|
||||||
@@ -1,23 +1,25 @@
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.lang.String;
|
import java.lang.Integer;
|
||||||
|
|
||||||
public class Sorting{
|
public class Sorting {
|
||||||
merge(a, b){
|
List<Integer> merge(List<Integer> a, List<Integer> b) {
|
||||||
a.addAll(b);
|
var r = new ArrayList<>();
|
||||||
return a;
|
for (var i = 0, j = 0; i < a.size() || j < b.size();)
|
||||||
|
if (j == b.size() || (i < a.size() && a.get(i) <= b.get(j)))
|
||||||
|
r.add(a.get(i++));
|
||||||
|
else r.add(b.get(j++));
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
sort(in){
|
split(list) {
|
||||||
var firstHalf = in;
|
var mid = list.size() / 2;
|
||||||
var secondHalf = in;
|
return List.of(list.subList(0, mid), list.subList(mid, list.size()));
|
||||||
return merge(sort(firstHalf), sort(secondHalf));
|
}
|
||||||
}
|
|
||||||
|
public sort(in) {
|
||||||
|
if (in.size() <= 1) return in;
|
||||||
/*
|
var halves = split(in);
|
||||||
void sort(a){
|
return merge(sort(halves.get(0)), sort(halves.get(1)));
|
||||||
a = merge(a,a);
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
public class StaticFail {
|
||||||
|
void nonStaticM() {}
|
||||||
|
|
||||||
|
static void staticM() {
|
||||||
|
nonStaticM();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -658,7 +658,7 @@ primaryPattern
|
|||||||
;
|
;
|
||||||
|
|
||||||
recordPattern
|
recordPattern
|
||||||
: typeType recordStructurePattern identifier?
|
: type=typeType? ctor=typeType recordStructurePattern ('@' identifier)?
|
||||||
//| recordStructurePattern identifier?
|
//| recordStructurePattern identifier?
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import de.dhbwstuttgart.core.JavaTXCompiler;
|
|||||||
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||||
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
|
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.Pattern;
|
||||||
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
|
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
|
||||||
import de.dhbwstuttgart.target.tree.*;
|
import de.dhbwstuttgart.target.tree.*;
|
||||||
import de.dhbwstuttgart.target.tree.expression.*;
|
import de.dhbwstuttgart.target.tree.expression.*;
|
||||||
@@ -40,6 +41,15 @@ public class Codegen {
|
|||||||
protected ClassLoader getClassLoader() {
|
protected ClassLoader getClassLoader() {
|
||||||
return compiler.getClassLoader();
|
return compiler.getClassLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getCommonSuperClass(String type1, String type2) {
|
||||||
|
var t1 = new TargetRefType(type1.replaceAll("/", "."));
|
||||||
|
var t2 = new TargetRefType(type2.replaceAll("/", "."));
|
||||||
|
var common = ASTToTargetAST.getCommonSuperType(t1, t2, compiler);
|
||||||
|
return common.getClassName().toString().replaceAll("\\.", "/");
|
||||||
|
//return super.getCommonSuperClass(type1, type2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Codegen(TargetStructure clazz, JavaTXCompiler compiler, ASTToTargetAST converter) {
|
public Codegen(TargetStructure clazz, JavaTXCompiler compiler, ASTToTargetAST converter) {
|
||||||
@@ -243,11 +253,17 @@ public class Codegen {
|
|||||||
if (source.equals(dest))
|
if (source.equals(dest))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (isFunctionalInterface(source) && isFunctionalInterface(dest) &&
|
if (/*isFunctionalInterface(source) &&*/ isFunctionalInterface(dest) && !source.equals(dest)) {
|
||||||
!(source instanceof TargetFunNType && dest instanceof TargetFunNType)) {
|
if (source instanceof TargetFunNType funs && dest instanceof TargetFunNType fund) {
|
||||||
|
if (funs.funNParams().size() == fund.funNParams().size() && !fund.isInterface()) {
|
||||||
boxFunctionalInterface(state, source, dest);
|
boxFunctionalInterface(state, source, dest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
boxFunctionalInterface(state, source, dest);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var mv = state.mv;
|
var mv = state.mv;
|
||||||
if ((source instanceof TargetRefType || source instanceof TargetGenericType) &&
|
if ((source instanceof TargetRefType || source instanceof TargetGenericType) &&
|
||||||
@@ -335,7 +351,7 @@ public class Codegen {
|
|||||||
mv.visitTypeInsn(NEW, className);
|
mv.visitTypeInsn(NEW, className);
|
||||||
mv.visitInsn(DUP_X1);
|
mv.visitInsn(DUP_X1);
|
||||||
mv.visitInsn(SWAP);
|
mv.visitInsn(SWAP);
|
||||||
mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "(" + source.toDescriptor() + ")V", false);
|
mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "(Ljava/lang/Object;)V", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isFunctionalInterface(TargetType type) {
|
private boolean isFunctionalInterface(TargetType type) {
|
||||||
@@ -349,6 +365,8 @@ public class Codegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private TargetType largerType(TargetType left, TargetType right) {
|
private TargetType largerType(TargetType left, TargetType right) {
|
||||||
|
if (left instanceof TargetExtendsWildcard wc) left = wc.innerType();
|
||||||
|
if (right instanceof TargetExtendsWildcard wc) right = wc.innerType();
|
||||||
if (left.equals(TargetType.String) || right.equals(TargetType.String)) {
|
if (left.equals(TargetType.String) || right.equals(TargetType.String)) {
|
||||||
return TargetType.String;
|
return TargetType.String;
|
||||||
} else if (left.equals(TargetType.Double) || right.equals(TargetType.Double)) {
|
} else if (left.equals(TargetType.Double) || right.equals(TargetType.Double)) {
|
||||||
@@ -812,7 +830,9 @@ public class Codegen {
|
|||||||
private static TargetType removeGenerics(TargetType param) {
|
private static TargetType removeGenerics(TargetType param) {
|
||||||
return switch (param) {
|
return switch (param) {
|
||||||
case null -> null;
|
case null -> null;
|
||||||
case TargetFunNType funNType -> new TargetFunNType(funNType.name(), funNType.funNParams().stream().map(Codegen::removeGenerics).toList(), List.of(), funNType.returnArguments());
|
case TargetFunNType funNType -> new TargetFunNType(funNType.name(),
|
||||||
|
funNType.funNParams().stream().map(Codegen::removeGenerics).toList(), List.of(),
|
||||||
|
funNType.returnArguments(), funNType.isInterface());
|
||||||
case TargetRefType refType -> new TargetRefType(refType.name());
|
case TargetRefType refType -> new TargetRefType(refType.name());
|
||||||
case TargetGenericType targetGenericType -> TargetType.Object;
|
case TargetGenericType targetGenericType -> TargetType.Object;
|
||||||
default -> param;
|
default -> param;
|
||||||
@@ -860,6 +880,7 @@ public class Codegen {
|
|||||||
var pattern = (TargetTypePattern) capture.pattern();
|
var pattern = (TargetTypePattern) capture.pattern();
|
||||||
var variable = state.scope.get(pattern.name());
|
var variable = state.scope.get(pattern.name());
|
||||||
mv.visitVarInsn(ALOAD, variable.index);
|
mv.visitVarInsn(ALOAD, variable.index);
|
||||||
|
if (!(capture.pattern().type() instanceof TargetGenericType))
|
||||||
mv.visitTypeInsn(CHECKCAST, capture.pattern().type().getInternalName());
|
mv.visitTypeInsn(CHECKCAST, capture.pattern().type().getInternalName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1035,6 +1056,7 @@ public class Codegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Label start = new Label();
|
Label start = new Label();
|
||||||
|
Label skip = new Label();
|
||||||
Label end = new Label();
|
Label end = new Label();
|
||||||
mv.visitLabel(start);
|
mv.visitLabel(start);
|
||||||
if (_for.termination() != null) {
|
if (_for.termination() != null) {
|
||||||
@@ -1047,13 +1069,14 @@ public class Codegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var env = new BreakEnv();
|
var env = new BreakEnv();
|
||||||
env.startLabel = start;
|
env.startLabel = skip;
|
||||||
env.endLabel = end;
|
env.endLabel = end;
|
||||||
|
|
||||||
state.breakStack.push(env);
|
state.breakStack.push(env);
|
||||||
generate(state, _for.body());
|
generate(state, _for.body());
|
||||||
state.breakStack.pop();
|
state.breakStack.pop();
|
||||||
|
|
||||||
|
mv.visitLabel(skip);
|
||||||
if (_for.increment() != null) {
|
if (_for.increment() != null) {
|
||||||
_for.increment().forEach(e -> {
|
_for.increment().forEach(e -> {
|
||||||
generate(state, e);
|
generate(state, e);
|
||||||
@@ -1184,6 +1207,12 @@ public class Codegen {
|
|||||||
}
|
}
|
||||||
case TargetMethodCall call: {
|
case TargetMethodCall call: {
|
||||||
if (!call.isStatic()) {
|
if (!call.isStatic()) {
|
||||||
|
if (call.expr() instanceof TargetThis && state.isStatic) {
|
||||||
|
throw new CodeGenException(
|
||||||
|
"Attempted to call instance method " + call.name() +
|
||||||
|
" with descriptor " + call.getDescriptor() + " from a static context"
|
||||||
|
);
|
||||||
|
}
|
||||||
generate(state, call.expr());
|
generate(state, call.expr());
|
||||||
boxPrimitive(state, call.expr().type());
|
boxPrimitive(state, call.expr().type());
|
||||||
}
|
}
|
||||||
@@ -1194,13 +1223,14 @@ public class Codegen {
|
|||||||
convertTo(state, e.type(), arg);
|
convertTo(state, e.type(), arg);
|
||||||
}
|
}
|
||||||
var descriptor = call.getDescriptor();
|
var descriptor = call.getDescriptor();
|
||||||
|
TargetType casted = call.type();
|
||||||
if (call.owner() instanceof TargetFunNType owner) {
|
if (call.owner() instanceof TargetFunNType owner) {
|
||||||
// Decay FunN
|
|
||||||
descriptor = TargetMethod.getDescriptor(
|
descriptor = TargetMethod.getDescriptor(
|
||||||
(owner.returnArguments() == 0 ? null : TargetType.Object),
|
(owner.returnArguments() == 0 ? null : TargetType.Object),
|
||||||
call.parameterTypes().stream().map(x -> TargetType.Object).toArray(TargetType[]::new));
|
call.parameterTypes().stream().map(x -> TargetType.Object).toArray(TargetType[]::new));
|
||||||
|
if (owner.returnArguments() != 0)
|
||||||
|
casted = FunNGenerator.getReturnType(owner.funNParams());
|
||||||
}
|
}
|
||||||
|
|
||||||
int insn = INVOKEVIRTUAL;
|
int insn = INVOKEVIRTUAL;
|
||||||
if (call.isStatic()) insn = INVOKESTATIC;
|
if (call.isStatic()) insn = INVOKESTATIC;
|
||||||
else if (call.isInterface()) insn = INVOKEINTERFACE;
|
else if (call.isInterface()) insn = INVOKEINTERFACE;
|
||||||
@@ -1214,7 +1244,7 @@ public class Codegen {
|
|||||||
unboxPrimitive(state, call.type());
|
unboxPrimitive(state, call.type());
|
||||||
}*/
|
}*/
|
||||||
if (call.type() != null)
|
if (call.type() != null)
|
||||||
convertTo(state, call.returnType(), call.type());
|
convertTo(state, call.returnType(), casted);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TargetLambdaExpression lambda:
|
case TargetLambdaExpression lambda:
|
||||||
@@ -1407,13 +1437,16 @@ public class Codegen {
|
|||||||
if (label instanceof TargetTypePattern || label instanceof TargetComplexPattern) {
|
if (label instanceof TargetTypePattern || label instanceof TargetComplexPattern) {
|
||||||
if (label.type() instanceof TargetGenericType) types.add(Type.getType(Object.class));
|
if (label.type() instanceof TargetGenericType) types.add(Type.getType(Object.class));
|
||||||
else types.add(Type.getObjectType(label.type().getInternalName()));
|
else types.add(Type.getObjectType(label.type().getInternalName()));
|
||||||
} else if (label instanceof TargetLiteral lit) {
|
} else if (label instanceof TargetExpressionPattern expr) {
|
||||||
types.add(lit.value());
|
if (expr.expression() instanceof TargetLiteral literal) {
|
||||||
|
types.add(Type.getObjectType(TargetType.toWrapper(literal.type()).getInternalName()));
|
||||||
|
} else {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
} else if (label instanceof TargetGuard guard) {
|
} else if (label instanceof TargetGuard guard) {
|
||||||
types.add(Type.getObjectType(guard.inner().type().getInternalName()));
|
types.add(Type.getObjectType(guard.inner().type().getInternalName()));
|
||||||
// TODO Same here we need to evaluate constant;
|
// TODO Same here we need to evaluate constant;
|
||||||
} else {
|
} else {
|
||||||
logger.info(label);
|
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1439,6 +1472,7 @@ public class Codegen {
|
|||||||
for (var i = 0; i < aSwitch.cases().size(); i++) {
|
for (var i = 0; i < aSwitch.cases().size(); i++) {
|
||||||
mv.visitLabel(caseLabels[i]);
|
mv.visitLabel(caseLabels[i]);
|
||||||
var cse = aSwitch.cases().get(i);
|
var cse = aSwitch.cases().get(i);
|
||||||
|
state.enterScope();
|
||||||
|
|
||||||
if (cse.labels().size() == 1) {
|
if (cse.labels().size() == 1) {
|
||||||
var label = cse.labels().get(0);
|
var label = cse.labels().get(0);
|
||||||
@@ -1467,6 +1501,8 @@ public class Codegen {
|
|||||||
if (cse.isSingleExpression() && aSwitch.isExpression())
|
if (cse.isSingleExpression() && aSwitch.isExpression())
|
||||||
yieldValue(state, cse.body().statements().get(0).type());
|
yieldValue(state, cse.body().statements().get(0).type());
|
||||||
if (aSwitch.isExpression()) mv.visitJumpInsn(GOTO, end);
|
if (aSwitch.isExpression()) mv.visitJumpInsn(GOTO, end);
|
||||||
|
|
||||||
|
state.exitScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
mv.visitLabel(defaultLabel);
|
mv.visitLabel(defaultLabel);
|
||||||
@@ -1478,6 +1514,9 @@ public class Codegen {
|
|||||||
// throw illegal argument exception on missing default case
|
// throw illegal argument exception on missing default case
|
||||||
mv.visitTypeInsn(NEW, "java/lang/IllegalArgumentException");
|
mv.visitTypeInsn(NEW, "java/lang/IllegalArgumentException");
|
||||||
mv.visitInsn(DUP);
|
mv.visitInsn(DUP);
|
||||||
|
//mv.visitVarInsn(ALOAD, tmp);
|
||||||
|
//mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
|
||||||
|
//mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getName", "()Ljava/lang/String;", false);
|
||||||
mv.visitLdcInsn("Unhandled case value");
|
mv.visitLdcInsn("Unhandled case value");
|
||||||
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalArgumentException", "<init>", "(Ljava/lang/String;)V", false);
|
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalArgumentException", "<init>", "(Ljava/lang/String;)V", false);
|
||||||
mv.visitInsn(ATHROW);
|
mv.visitInsn(ATHROW);
|
||||||
@@ -1498,21 +1537,42 @@ public class Codegen {
|
|||||||
state.exitScope();
|
state.exitScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void extractField(State state, TargetType type, int i, ClassOrInterface clazz) {
|
private void extractField(State state, TargetType ret, TargetType type, int i, ClassOrInterface clazz) {
|
||||||
|
state.mv.visitTypeInsn(CHECKCAST, type.getInternalName());
|
||||||
if (i >= clazz.getFieldDecl().size())
|
if (i >= clazz.getFieldDecl().size())
|
||||||
throw new CodeGenException("Couldn't find suitable field accessor for '" + type.name() + "'");
|
throw new CodeGenException("Couldn't find suitable field accessor for '" + type.name() + "'");
|
||||||
var field = clazz.getFieldDecl().get(i);
|
var field = clazz.getFieldDecl().get(i);
|
||||||
var fieldType = converter.convert(field.getType());
|
var fieldType = converter.convert(field.getType());
|
||||||
state.mv.visitMethodInsn(INVOKEVIRTUAL, type.getInternalName(), field.getName(), "()" + fieldType.toDescriptor(), false);
|
state.mv.visitMethodInsn(INVOKEVIRTUAL, type.getInternalName(), field.getName(), "()" + fieldType.toDescriptor(), false);
|
||||||
|
if (ret != null) convertTo(state, fieldType, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bindPattern(State state, TargetType type, TargetPattern pat, Label start, int index, int depth) {
|
private void bindPattern(State state, TargetType type, TargetPattern pat, Label start, int index, int depth) {
|
||||||
//if (pat.type() instanceof TargetPrimitiveType)
|
//if (pat.type() instanceof TargetPrimitiveType)
|
||||||
// boxPrimitive(state, pat.type());
|
// boxPrimitive(state, pat.type());
|
||||||
|
|
||||||
if (pat.type() instanceof TargetRefType) {
|
if (pat.type() instanceof TargetSpecializedType) {
|
||||||
|
var name = pat.type().getInternalName();
|
||||||
|
//if (pat.type() instanceof TargetFunNType funNType) {
|
||||||
|
// name = FunNGenerator.getSuperClassName(funNType.funNParams().size() - 1, funNType.returnArguments());
|
||||||
|
//}
|
||||||
|
|
||||||
state.mv.visitInsn(DUP);
|
state.mv.visitInsn(DUP);
|
||||||
state.mv.visitTypeInsn(INSTANCEOF, pat.type().getInternalName());
|
|
||||||
|
/*state.mv.visitInsn(DUP);
|
||||||
|
state.mv.visitTypeInsn(INSTANCEOF, "Fun0$$LLazyList$_$");
|
||||||
|
state.mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
|
||||||
|
state.mv.visitInsn(SWAP);
|
||||||
|
state.mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Z)V", false);
|
||||||
|
|
||||||
|
state.mv.visitInsn(DUP);
|
||||||
|
state.mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
|
||||||
|
state.mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getName", "()Ljava/lang/String;", false);
|
||||||
|
state.mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
|
||||||
|
state.mv.visitInsn(SWAP);
|
||||||
|
state.mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
|
||||||
|
*/
|
||||||
|
state.mv.visitTypeInsn(INSTANCEOF, name);
|
||||||
|
|
||||||
var cont = new Label();
|
var cont = new Label();
|
||||||
state.mv.visitJumpInsn(IFNE, cont);
|
state.mv.visitJumpInsn(IFNE, cont);
|
||||||
@@ -1525,7 +1585,7 @@ public class Codegen {
|
|||||||
state.mv.visitJumpInsn(GOTO, start);
|
state.mv.visitJumpInsn(GOTO, start);
|
||||||
state.mv.visitLabel(cont);
|
state.mv.visitLabel(cont);
|
||||||
|
|
||||||
state.mv.visitTypeInsn(CHECKCAST, pat.type().getInternalName());
|
state.mv.visitTypeInsn(CHECKCAST, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pat instanceof TargetExpressionPattern ep) {
|
if (pat instanceof TargetExpressionPattern ep) {
|
||||||
@@ -1558,7 +1618,7 @@ public class Codegen {
|
|||||||
state.mv.visitVarInsn(ASTORE, local.index);
|
state.mv.visitVarInsn(ASTORE, local.index);
|
||||||
}
|
}
|
||||||
|
|
||||||
var clazz = findClass(new JavaClassName(cp.type().name()));
|
var clazz = findClass(new JavaClassName(cp.ctor().name()));
|
||||||
if (clazz == null) throw new CodeGenException("Class definition for '" + cp.type().name() + "' not found");
|
if (clazz == null) throw new CodeGenException("Class definition for '" + cp.type().name() + "' not found");
|
||||||
// TODO Check if class is a Record
|
// TODO Check if class is a Record
|
||||||
|
|
||||||
@@ -1566,7 +1626,7 @@ public class Codegen {
|
|||||||
var subPattern = cp.subPatterns().get(i);
|
var subPattern = cp.subPatterns().get(i);
|
||||||
|
|
||||||
state.mv.visitInsn(DUP);
|
state.mv.visitInsn(DUP);
|
||||||
extractField(state, cp.type(), i, clazz);
|
extractField(state, null, cp.ctor(), i, clazz);
|
||||||
|
|
||||||
if (subPattern.type() instanceof TargetRefType || subPattern.type() instanceof TargetExtendsWildcard) {
|
if (subPattern.type() instanceof TargetRefType || subPattern.type() instanceof TargetExtendsWildcard) {
|
||||||
state.mv.visitInsn(DUP);
|
state.mv.visitInsn(DUP);
|
||||||
@@ -1615,7 +1675,7 @@ public class Codegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateStaticConstructor(TargetMethod constructor) {
|
private void generateStaticConstructor(TargetMethod constructor) {
|
||||||
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "<clinit>", "()V", null, null);
|
MethodVisitor mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
|
|
||||||
var state = new State(null, mv, 0, true);
|
var state = new State(null, mv, 0, true);
|
||||||
@@ -1659,7 +1719,7 @@ public class Codegen {
|
|||||||
private void bindLocalVariables(State state, TargetComplexPattern cp, int offset) {
|
private void bindLocalVariables(State state, TargetComplexPattern cp, int offset) {
|
||||||
state.mv.visitVarInsn(ALOAD, offset);
|
state.mv.visitVarInsn(ALOAD, offset);
|
||||||
|
|
||||||
var clazz = findClass(new JavaClassName(cp.type().name()));
|
var clazz = findClass(new JavaClassName(cp.ctor().name()));
|
||||||
if (clazz == null) throw new CodeGenException("Class definition for '" + cp.type().name() + "' not found");
|
if (clazz == null) throw new CodeGenException("Class definition for '" + cp.type().name() + "' not found");
|
||||||
|
|
||||||
for (var i = 0; i < cp.subPatterns().size(); i++) {
|
for (var i = 0; i < cp.subPatterns().size(); i++) {
|
||||||
@@ -1668,7 +1728,7 @@ public class Codegen {
|
|||||||
if (i < cp.subPatterns().size() - 1)
|
if (i < cp.subPatterns().size() - 1)
|
||||||
state.mv.visitInsn(DUP);
|
state.mv.visitInsn(DUP);
|
||||||
|
|
||||||
extractField(state, cp.type(), i, clazz);
|
extractField(state, subPattern.type(), cp.ctor(), i, clazz);
|
||||||
if (subPattern.type() instanceof TargetRefType)
|
if (subPattern.type() instanceof TargetRefType)
|
||||||
state.mv.visitTypeInsn(CHECKCAST, subPattern.type().getInternalName());
|
state.mv.visitTypeInsn(CHECKCAST, subPattern.type().getInternalName());
|
||||||
offset = state.createVariable(subPattern.name(), subPattern.type()).index;
|
offset = state.createVariable(subPattern.name(), subPattern.type()).index;
|
||||||
@@ -1791,6 +1851,35 @@ public class Codegen {
|
|||||||
clazz.constructors().forEach(this::generateConstructor);
|
clazz.constructors().forEach(this::generateConstructor);
|
||||||
clazz.methods().forEach(this::generateMethod);
|
clazz.methods().forEach(this::generateMethod);
|
||||||
|
|
||||||
|
// Check if non abstract class implements all interface methods
|
||||||
|
if ((access & ACC_ABSTRACT) == 0) {
|
||||||
|
for (var intf : clazz.implementingInterfaces()) {
|
||||||
|
var intfClass = compiler.getClass(new JavaClassName(intf.name()));
|
||||||
|
for (var method : intfClass.getMethods()) {
|
||||||
|
if ((method.modifier & ACC_ABSTRACT) != 0) {
|
||||||
|
// Check if the method is implemented in the current class
|
||||||
|
// TODO This is duplicate code, we should probably refactor instances of this pattern
|
||||||
|
var foundMethods = clazz.methods().stream().filter(m -> {
|
||||||
|
if (!m.name().equals(method.name)) return false;
|
||||||
|
if (m.signature().parameters().size() != method.getParameterList().getFormalparalist().size())
|
||||||
|
return false;
|
||||||
|
for (var i = 0; i < m.signature().parameters().size(); i++) {
|
||||||
|
var param1 = m.signature().parameters().get(i).pattern().type();
|
||||||
|
var param2 = converter.convert(
|
||||||
|
method.getParameterList().getParameterAt(i).getType(),
|
||||||
|
ASTToTargetAST.Generics.nullGenerics(compiler).javaGenerics());
|
||||||
|
if (!param1.equals(param2)) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}).toList();
|
||||||
|
if (foundMethods.size() != 1) {
|
||||||
|
throw new CodeGenException("Class " + clazz.qualifiedName() + " does not implement method " + method.name + " from interface " + intfClass.getClassName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (clazz.staticConstructor() != null)
|
if (clazz.staticConstructor() != null)
|
||||||
generateStaticConstructor(clazz.staticConstructor());
|
generateStaticConstructor(clazz.staticConstructor());
|
||||||
|
|
||||||
@@ -1800,54 +1889,82 @@ public class Codegen {
|
|||||||
// Generate wrapper classes for function types
|
// Generate wrapper classes for function types
|
||||||
for (var pair : funWrapperClasses.keySet()) {
|
for (var pair : funWrapperClasses.keySet()) {
|
||||||
var className = funWrapperClasses.get(pair);
|
var className = funWrapperClasses.get(pair);
|
||||||
ClassWriter cw2 = new CustomClassWriter();
|
|
||||||
cw2.visit(V1_8, ACC_PUBLIC, className, null, "java/lang/Object", new String[] { pair.to.getInternalName() });
|
|
||||||
cw2.visitField(ACC_PRIVATE, "wrapped", pair.from.toDescriptor(), null, null).visitEnd();
|
|
||||||
|
|
||||||
// Generate constructor
|
var toName = "apply";
|
||||||
var ctor = cw2.visitMethod(ACC_PUBLIC, "<init>", "(" + pair.from.toDescriptor() + ")V", null, null);
|
TargetType toReturn;
|
||||||
ctor.visitVarInsn(ALOAD, 0);
|
TargetType[] toParams;
|
||||||
ctor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
|
||||||
ctor.visitVarInsn(ALOAD, 0);
|
if (!(pair.to instanceof TargetFunNType to)) {
|
||||||
ctor.visitVarInsn(ALOAD, 1);
|
var toClass = compiler.getClass(new JavaClassName(pair.to.name()));
|
||||||
ctor.visitFieldInsn(PUTFIELD, className, "wrapped", pair.from.toDescriptor());
|
var toMethod = toClass.getMethods().stream().filter(m -> (m.modifier & ACC_ABSTRACT) != 0).findFirst().orElseThrow();
|
||||||
ctor.visitInsn(RETURN);
|
toReturn = converter.convert(toMethod.getReturnType());
|
||||||
ctor.visitMaxs(0, 0);
|
toParams = converter.convert(toMethod.getParameterList()).stream().map(m -> m.pattern().type()).toArray(TargetType[]::new);
|
||||||
ctor.visitEnd();
|
toName = toMethod.name;
|
||||||
|
} else if (pair.from instanceof TargetFunNType from) {
|
||||||
|
toReturn = from.returnArguments() == 0 ? null : TargetType.Object;
|
||||||
|
toParams = from.funNParams().subList(0, from.funNParams().size() - 1).stream().map(x -> TargetType.Object).toArray(TargetType[]::new);
|
||||||
|
} else {
|
||||||
|
toReturn = to.returnArguments() == 0 ? null : TargetType.Object;
|
||||||
|
toParams = to.funNParams().subList(0, to.funNParams().size() - 1).stream().map(x -> TargetType.Object).toArray(TargetType[]::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
var toDescriptor = TargetMethod.getDescriptor(toReturn, toParams);
|
||||||
|
var fieldDescriptor = pair.from.toDescriptor();
|
||||||
|
|
||||||
String methodName = "apply";
|
String methodName = "apply";
|
||||||
String fromDescriptor = null;
|
String fromDescriptor = null;
|
||||||
TargetType fromReturn = null;
|
TargetType fromReturn = null;
|
||||||
if (!(pair.from instanceof TargetFunNType funNType)) {
|
String fromClass = pair.from.getInternalName();
|
||||||
var fromClass = compiler.getClass(new JavaClassName(pair.from.name()));
|
if (isFunctionalInterface(pair.from) && !(pair.from instanceof TargetFunNType)) {
|
||||||
var fromMethod = fromClass.getMethods().stream().filter(m -> (m.modifier & ACC_ABSTRACT) != 0).findFirst().orElseThrow();
|
var clazz = compiler.getClass(new JavaClassName(pair.from.name()));
|
||||||
|
var fromMethod = clazz.getMethods().stream().filter(m -> (m.modifier & ACC_ABSTRACT) != 0).findFirst().orElseThrow();
|
||||||
methodName = fromMethod.name;
|
methodName = fromMethod.name;
|
||||||
|
|
||||||
fromReturn = converter.convert(fromMethod.getReturnType());
|
fromReturn = converter.convert(fromMethod.getReturnType());
|
||||||
var fromParams = converter.convert(fromMethod.getParameterList()).stream().map(m -> m.pattern().type()).toArray(TargetType[]::new);
|
var fromParams = converter.convert(fromMethod.getParameterList()).stream().map(m -> m.pattern().type()).toArray(TargetType[]::new);
|
||||||
fromDescriptor = TargetMethod.getDescriptor(fromReturn, fromParams);
|
fromDescriptor = TargetMethod.getDescriptor(fromReturn, fromParams);
|
||||||
} else {
|
} else if (pair.from instanceof TargetFunNType funNType) {
|
||||||
fromReturn = funNType.returnArguments() > 0 ? TargetType.Object : null;
|
fromReturn = funNType.returnArguments() > 0 ? TargetType.Object : null;
|
||||||
fromDescriptor = funNType.toMethodDescriptor();
|
fromDescriptor = funNType.toMethodDescriptor();
|
||||||
|
} else {
|
||||||
|
fromDescriptor = toDescriptor;
|
||||||
|
fromReturn = toReturn;
|
||||||
|
var to = (TargetFunNType) pair.to;
|
||||||
|
fromClass = FunNGenerator.getSuperClassName(to.funNParams().size() - 1, to.returnArguments());
|
||||||
|
fieldDescriptor = "L" + fromClass + ";";
|
||||||
}
|
}
|
||||||
|
|
||||||
var toClass = compiler.getClass(new JavaClassName(pair.to.name()));
|
var superClasses = new ArrayList<>();
|
||||||
var toMethod = toClass.getMethods().stream().filter(m -> (m.modifier & ACC_ABSTRACT) != 0).findFirst().orElseThrow();
|
superClasses.add(pair.to.getInternalName());
|
||||||
var toReturn = converter.convert(toMethod.getReturnType());
|
if (isFunctionalInterface(pair.from))
|
||||||
var toParams = converter.convert(toMethod.getParameterList()).stream().map(m -> m.pattern().type()).toArray(TargetType[]::new);
|
superClasses.add(pair.from.getInternalName());
|
||||||
var toDescriptor = TargetMethod.getDescriptor(toReturn, toParams);
|
|
||||||
|
ClassWriter cw2 = new CustomClassWriter();
|
||||||
|
cw2.visit(V1_8, ACC_PUBLIC, className, null, "java/lang/Object", superClasses.toArray(String[]::new));
|
||||||
|
cw2.visitField(ACC_PRIVATE, "wrapped", fieldDescriptor, null, null).visitEnd();
|
||||||
|
|
||||||
|
// Generate constructor
|
||||||
|
var ctor = cw2.visitMethod(ACC_PUBLIC, "<init>", "(Ljava/lang/Object;)V", null, null);
|
||||||
|
ctor.visitVarInsn(ALOAD, 0);
|
||||||
|
ctor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
||||||
|
ctor.visitVarInsn(ALOAD, 0);
|
||||||
|
ctor.visitVarInsn(ALOAD, 1);
|
||||||
|
ctor.visitFieldInsn(PUTFIELD, className, "wrapped", fieldDescriptor);
|
||||||
|
ctor.visitInsn(RETURN);
|
||||||
|
ctor.visitMaxs(0, 0);
|
||||||
|
ctor.visitEnd();
|
||||||
|
|
||||||
// Generate wrapper method
|
// Generate wrapper method
|
||||||
var mv = cw2.visitMethod(ACC_PUBLIC, toMethod.name, toDescriptor, null, null);
|
var mv = cw2.visitMethod(ACC_PUBLIC, toName, toDescriptor, null, null);
|
||||||
var state = new State(null, mv, 0, false);
|
var state = new State(null, mv, 0, false);
|
||||||
|
|
||||||
mv.visitVarInsn(ALOAD, 0);
|
mv.visitVarInsn(ALOAD, 0);
|
||||||
mv.visitFieldInsn(GETFIELD, className, "wrapped", pair.from.toDescriptor());
|
mv.visitFieldInsn(GETFIELD, className, "wrapped", fieldDescriptor);
|
||||||
for (var i = 0; i < toParams.length; i++) {
|
for (var i = 0; i < toParams.length; i++) {
|
||||||
var arg = toParams[i];
|
var arg = toParams[i];
|
||||||
mv.visitVarInsn(findLoadCode(arg), i + 1);
|
mv.visitVarInsn(findLoadCode(arg), i + 1);
|
||||||
}
|
}
|
||||||
mv.visitMethodInsn(INVOKEINTERFACE, pair.from.getInternalName(), methodName, fromDescriptor, true);
|
mv.visitMethodInsn(INVOKEINTERFACE, fromClass, methodName, fromDescriptor, true);
|
||||||
if (fromReturn != null) {
|
if (fromReturn != null) {
|
||||||
if (toReturn instanceof TargetPrimitiveType) {
|
if (toReturn instanceof TargetPrimitiveType) {
|
||||||
convertTo(state, fromReturn, TargetType.toWrapper(toReturn));
|
convertTo(state, fromReturn, TargetType.toWrapper(toReturn));
|
||||||
@@ -1908,7 +2025,7 @@ public class Codegen {
|
|||||||
bootstrapArgs[i + 2] = fieldRef;
|
bootstrapArgs[i + 2] = fieldRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
{ // hashCode
|
if (clazz.methods().stream().filter(m -> m.getDescriptor().equals("()I") && m.name().equals("hashCode")).findFirst().isEmpty()) { // hashCode
|
||||||
var mv = cw.visitMethod(ACC_PUBLIC, "hashCode", "()I", null, null);
|
var mv = cw.visitMethod(ACC_PUBLIC, "hashCode", "()I", null, null);
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
mv.visitVarInsn(ALOAD, 0);
|
mv.visitVarInsn(ALOAD, 0);
|
||||||
@@ -1917,7 +2034,7 @@ public class Codegen {
|
|||||||
mv.visitMaxs(0, 0);
|
mv.visitMaxs(0, 0);
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
{ // equals
|
if (clazz.methods().stream().filter(m -> m.getDescriptor().equals("(Ljava/lang/Object;)Z") && m.name().equals("equals")).findFirst().isEmpty()) { // equals
|
||||||
var mv = cw.visitMethod(ACC_PUBLIC, "equals", "(Ljava/lang/Object;)Z", null, null);
|
var mv = cw.visitMethod(ACC_PUBLIC, "equals", "(Ljava/lang/Object;)Z", null, null);
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
mv.visitVarInsn(ALOAD, 0);
|
mv.visitVarInsn(ALOAD, 0);
|
||||||
@@ -1927,7 +2044,7 @@ public class Codegen {
|
|||||||
mv.visitMaxs(0, 0);
|
mv.visitMaxs(0, 0);
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
{ // toString
|
if (clazz.methods().stream().filter(m -> m.getDescriptor().equals("()Ljava/lang/String;") && m.name().equals("toString")).findFirst().isEmpty()) { // toString
|
||||||
var mv = cw.visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null);
|
var mv = cw.visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null);
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
mv.visitVarInsn(ALOAD, 0);
|
mv.visitVarInsn(ALOAD, 0);
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ class Args {
|
|||||||
|
|
||||||
public class ConsoleInterface {
|
public class ConsoleInterface {
|
||||||
public static Logger.LogLevel logLevel = Logger.LogLevel.ERROR;
|
public static Logger.LogLevel logLevel = Logger.LogLevel.ERROR;
|
||||||
|
public static boolean writeToConsole = true;
|
||||||
public static boolean writeLogFiles = false;
|
public static boolean writeLogFiles = false;
|
||||||
public static boolean inferTogether = false;
|
public static boolean inferTogether = false;
|
||||||
public static Optional<String> unifyServerUrl = Optional.empty();
|
public static Optional<String> unifyServerUrl = Optional.empty();
|
||||||
|
|||||||
@@ -5,8 +5,10 @@ import de.dhbwstuttgart.bytecode.Codegen;
|
|||||||
import de.dhbwstuttgart.bytecode.FunNGenerator;
|
import de.dhbwstuttgart.bytecode.FunNGenerator;
|
||||||
import de.dhbwstuttgart.environment.CompilationEnvironment;
|
import de.dhbwstuttgart.environment.CompilationEnvironment;
|
||||||
import de.dhbwstuttgart.environment.DirectoryClassLoader;
|
import de.dhbwstuttgart.environment.DirectoryClassLoader;
|
||||||
|
import de.dhbwstuttgart.exceptions.CompilerException;
|
||||||
|
import de.dhbwstuttgart.exceptions.CompilerWarning;
|
||||||
import de.dhbwstuttgart.exceptions.DebugException;
|
import de.dhbwstuttgart.exceptions.DebugException;
|
||||||
import de.dhbwstuttgart.languageServerInterface.model.LanguageServerTransferObject;
|
import de.dhbwstuttgart.exceptions.WarningsException;
|
||||||
import de.dhbwstuttgart.parser.JavaTXParser;
|
import de.dhbwstuttgart.parser.JavaTXParser;
|
||||||
import de.dhbwstuttgart.parser.NullToken;
|
import de.dhbwstuttgart.parser.NullToken;
|
||||||
import de.dhbwstuttgart.parser.antlr.Java17Parser;
|
import de.dhbwstuttgart.parser.antlr.Java17Parser;
|
||||||
@@ -20,14 +22,10 @@ import de.dhbwstuttgart.server.SocketFuture;
|
|||||||
import de.dhbwstuttgart.server.packet.SetAutoclosePacket;
|
import de.dhbwstuttgart.server.packet.SetAutoclosePacket;
|
||||||
import de.dhbwstuttgart.server.packet.UnifyRequestPacket;
|
import de.dhbwstuttgart.server.packet.UnifyRequestPacket;
|
||||||
import de.dhbwstuttgart.server.packet.UnifyResultPacket;
|
import de.dhbwstuttgart.server.packet.UnifyResultPacket;
|
||||||
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
|
import de.dhbwstuttgart.syntaxtree.*;
|
||||||
import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
|
|
||||||
import de.dhbwstuttgart.syntaxtree.Method;
|
|
||||||
import de.dhbwstuttgart.syntaxtree.ParameterList;
|
|
||||||
import de.dhbwstuttgart.syntaxtree.SourceFile;
|
|
||||||
import de.dhbwstuttgart.syntaxtree.GenericDeclarationList;
|
|
||||||
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
|
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
|
||||||
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
|
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.Block;
|
||||||
import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType;
|
import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType;
|
||||||
import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
|
import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
|
||||||
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||||
@@ -35,9 +33,12 @@ import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
|||||||
import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType;
|
import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType;
|
||||||
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||||
import de.dhbwstuttgart.syntaxtree.type.TypeVisitor;
|
import de.dhbwstuttgart.syntaxtree.type.TypeVisitor;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.Void;
|
||||||
import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter;
|
import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter;
|
||||||
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
|
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
|
||||||
import de.dhbwstuttgart.target.generate.GenericsResult;
|
import de.dhbwstuttgart.target.generate.GenericsResult;
|
||||||
|
import de.dhbwstuttgart.target.tree.*;
|
||||||
|
import de.dhbwstuttgart.target.tree.type.*;
|
||||||
import de.dhbwstuttgart.typeinference.constraints.Constraint;
|
import de.dhbwstuttgart.typeinference.constraints.Constraint;
|
||||||
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
||||||
import de.dhbwstuttgart.typeinference.constraints.Pair;
|
import de.dhbwstuttgart.typeinference.constraints.Pair;
|
||||||
@@ -62,7 +63,9 @@ import de.dhbwstuttgart.typeinference.unify.UnifyTaskModel;
|
|||||||
|
|
||||||
import de.dhbwstuttgart.util.Logger;
|
import de.dhbwstuttgart.util.Logger;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.lang.Record;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.sql.Array;
|
import java.sql.Array;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@@ -82,7 +85,9 @@ public class JavaTXCompiler {
|
|||||||
// public static JavaTXCompiler INSTANCE;
|
// public static JavaTXCompiler INSTANCE;
|
||||||
final CompilationEnvironment environment;
|
final CompilationEnvironment environment;
|
||||||
Boolean resultmodel = true;
|
Boolean resultmodel = true;
|
||||||
public final Map<File, SourceFile> sourceFiles = new HashMap<>();
|
|
||||||
|
private final List<File> sources;
|
||||||
|
public final Map<File, SourceFile> sourceFiles = new LinkedHashMap<>();
|
||||||
public final Set<JavaClassName> input = new HashSet<>();
|
public final Set<JavaClassName> input = new HashSet<>();
|
||||||
|
|
||||||
public volatile UnifyTaskModel usedTasks = new UnifyTaskModel();
|
public volatile UnifyTaskModel usedTasks = new UnifyTaskModel();
|
||||||
@@ -100,6 +105,7 @@ public class JavaTXCompiler {
|
|||||||
public DirectoryClassLoader getClassLoader() {
|
public DirectoryClassLoader getClassLoader() {
|
||||||
return classLoader;
|
return classLoader;
|
||||||
}
|
}
|
||||||
|
public final List<CompilerWarning> generatedWarnings = new ArrayList<>();
|
||||||
|
|
||||||
public JavaTXCompiler(File sourceFile) throws IOException, ClassNotFoundException {
|
public JavaTXCompiler(File sourceFile) throws IOException, ClassNotFoundException {
|
||||||
this(Collections.singletonList(sourceFile), List.of(), new File("."), ConsoleInterface.inferTogether);
|
this(Collections.singletonList(sourceFile), List.of(), new File("."), ConsoleInterface.inferTogether);
|
||||||
@@ -124,7 +130,23 @@ public class JavaTXCompiler {
|
|||||||
environment = new CompilationEnvironment(sources, classLoader);
|
environment = new CompilationEnvironment(sources, classLoader);
|
||||||
classPath = path;
|
classPath = path;
|
||||||
this.outputPath = outputPath;
|
this.outputPath = outputPath;
|
||||||
|
this.sources = sources;
|
||||||
|
// INSTANCE = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void warn(CompilerWarning warning) {
|
||||||
|
this.generatedWarnings.add(warning);
|
||||||
|
}
|
||||||
|
public void checkWarnings() {
|
||||||
|
for (var warning : this.generatedWarnings) {
|
||||||
|
defaultLogger.error("[Warning] " + warning.getMessage());
|
||||||
|
}
|
||||||
|
if (!generatedWarnings.isEmpty()) {
|
||||||
|
throw new WarningsException(generatedWarnings.size() + " warnings in code, aborting!", this.generatedWarnings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<SourceFileContext> generateSources(List<File> sources) throws IOException, ClassNotFoundException {
|
||||||
// TODO This should maybe be moved elsewhere
|
// TODO This should maybe be moved elsewhere
|
||||||
var treeList = new ArrayList<SourceFileContext>(sources.size());
|
var treeList = new ArrayList<SourceFileContext>(sources.size());
|
||||||
for (var s : sources) {
|
for (var s : sources) {
|
||||||
@@ -150,15 +172,13 @@ public class JavaTXCompiler {
|
|||||||
|
|
||||||
var numberOfGenerics = decl == null ? 0 : decl.genericTypeVar().size();
|
var numberOfGenerics = decl == null ? 0 : decl.genericTypeVar().size();
|
||||||
var className = pkgName + (!pkgName.isEmpty() ? "." : "") + name;
|
var className = pkgName + (!pkgName.isEmpty() ? "." : "") + name;
|
||||||
|
if (classRegistry.contains(className))
|
||||||
|
throw new CompilerException("Duplicate class definition: " + className);
|
||||||
classRegistry.addName(className, numberOfGenerics);
|
classRegistry.addName(className, numberOfGenerics);
|
||||||
input.add(classRegistry.getName(className));
|
input.add(classRegistry.getName(className));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return treeList;
|
||||||
for (var i = 0; i < sources.size(); i++) {
|
|
||||||
parse(treeList.get(i), sources.get(i));
|
|
||||||
}
|
|
||||||
// INSTANCE = this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addSourceFile(File file, SourceFile sf) {
|
private void addSourceFile(File file, SourceFile sf) {
|
||||||
@@ -422,6 +442,8 @@ public class JavaTXCompiler {
|
|||||||
return typeInference(List.of(file));
|
return typeInference(List.of(file));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ConstraintSet<?> lastConstraints;
|
||||||
|
|
||||||
public List<ResultSet> typeInference(List<File> files) throws ClassNotFoundException, IOException {
|
public List<ResultSet> typeInference(List<File> files) throws ClassNotFoundException, IOException {
|
||||||
Set<ClassOrInterface> allClasses = new HashSet<>();
|
Set<ClassOrInterface> allClasses = new HashSet<>();
|
||||||
|
|
||||||
@@ -437,14 +459,12 @@ public class JavaTXCompiler {
|
|||||||
|
|
||||||
TYPE ty = new TYPE(definedClasses, allClasses);
|
TYPE ty = new TYPE(definedClasses, allClasses);
|
||||||
var cons = ty.getConstraints();
|
var cons = ty.getConstraints();
|
||||||
|
lastConstraints = cons;
|
||||||
|
|
||||||
Set<Set<UnifyPair>> results = new HashSet<>();
|
Set<Set<UnifyPair>> results = new HashSet<>();
|
||||||
PlaceholderRegistry placeholderRegistry = new PlaceholderRegistry();
|
PlaceholderRegistry placeholderRegistry = new PlaceholderRegistry();
|
||||||
|
|
||||||
var logFolder = new File(System.getProperty("user.dir") + "/logFiles/");
|
Logger logger = new Logger("TypeInference");
|
||||||
if (ConsoleInterface.writeLogFiles && !logFolder.mkdirs()) throw new RuntimeException("Could not create directory for log files: " + logFolder);
|
|
||||||
Writer logFile = ConsoleInterface.writeLogFiles ? new FileWriter(new File(logFolder, "log_" + sourceFiles.keySet().iterator().next().getName())) : new OutputStreamWriter(new NullOutputStream());
|
|
||||||
Logger logger = new Logger(logFile, "TypeInference");
|
|
||||||
|
|
||||||
FiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses.stream().toList(), logger, classLoader, this, placeholderRegistry);
|
FiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses.stream().toList(), logger, classLoader, this, placeholderRegistry);
|
||||||
logger.info(finiteClosure.toString());
|
logger.info(finiteClosure.toString());
|
||||||
@@ -548,87 +568,6 @@ public class JavaTXCompiler {
|
|||||||
return results.stream().map((unifyPairs -> new ResultSet(UnifyTypeFactory.convert(unifyPairs, Pair.generateTPHMap(cons), placeholderRegistry)))).collect(Collectors.toList());
|
return results.stream().map((unifyPairs -> new ResultSet(UnifyTypeFactory.convert(unifyPairs, Pair.generateTPHMap(cons), placeholderRegistry)))).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* TEMPORARY - Only for Language Server Usage
|
|
||||||
*/
|
|
||||||
public LanguageServerTransferObject getResultSetAndAbstractSyntax(File file) throws IOException, ClassNotFoundException {
|
|
||||||
var sf = sourceFiles.get(file);
|
|
||||||
if(sf == null){
|
|
||||||
sf = sourceFiles.values().stream().findFirst().get();
|
|
||||||
}
|
|
||||||
Set<ClassOrInterface> allClasses = new HashSet<>();
|
|
||||||
allClasses.addAll(getAvailableClasses(sf));
|
|
||||||
allClasses.addAll(sf.getClasses());
|
|
||||||
var newClasses = CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), file, this).stream().map(ASTFactory::createClass).collect(Collectors.toSet());
|
|
||||||
for (var clazz : newClasses) {
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
final ConstraintSet<Pair> cons = getConstraints(file);
|
|
||||||
Set<Set<UnifyPair>> results = new HashSet<>();
|
|
||||||
|
|
||||||
Writer logFile = new OutputStreamWriter(new NullOutputStream());
|
|
||||||
Logger logger = new Logger(logFile, "TypeInferenceAsync");
|
|
||||||
UnifyContext context = new UnifyContext(logger, false, null, usedTasks, defaultClientPlaceholderRegistry);
|
|
||||||
try {
|
|
||||||
IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses.stream().toList(), logger, classLoader, this, context.placeholderRegistry());
|
|
||||||
ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(this, cons, context.placeholderRegistry());
|
|
||||||
Function<UnifyPair, UnifyPair> distributeInnerVars = x -> {
|
|
||||||
UnifyType lhs, rhs;
|
|
||||||
if (((lhs = x.getLhsType()) instanceof PlaceholderType) && ((rhs = x.getRhsType()) instanceof PlaceholderType) && (((PlaceholderType) lhs).isInnerType() || ((PlaceholderType) rhs).isInnerType())) {
|
|
||||||
((PlaceholderType) lhs).setInnerType(true);
|
|
||||||
((PlaceholderType) rhs).setInnerType(true);
|
|
||||||
}
|
|
||||||
return x;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
unifyCons = unifyCons.map(distributeInnerVars);
|
|
||||||
Set<PlaceholderType> varianceTPHold;
|
|
||||||
Set<PlaceholderType> varianceTPH = new HashSet<>();
|
|
||||||
varianceTPH = varianceInheritanceConstraintSet(unifyCons);
|
|
||||||
|
|
||||||
List<Set<Constraint<UnifyPair>>> oderConstraints = unifyCons.getOderConstraints();
|
|
||||||
|
|
||||||
if (resultmodel) {
|
|
||||||
/* UnifyResultModel Anfang */
|
|
||||||
UnifyResultModel urm = new UnifyResultModel(cons, finiteClosure);
|
|
||||||
UnifyResultListenerImpl li = new UnifyResultListenerImpl();
|
|
||||||
urm.addUnifyResultListener(li);
|
|
||||||
TypeUnify.unifyParallel(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, context);
|
|
||||||
generateBytecode(sf, li.getResults());
|
|
||||||
return new LanguageServerTransferObject(li.getResults(), sf, ASTTypePrinter.print(sf), generatedGenerics);
|
|
||||||
}
|
|
||||||
/* UnifyResultModel End */
|
|
||||||
else {
|
|
||||||
Set<Set<UnifyPair>> result = TypeUnify.unifyOderConstraints(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, context);
|
|
||||||
results.addAll(result);
|
|
||||||
|
|
||||||
results = results.stream().map(x -> {
|
|
||||||
Optional<Set<UnifyPair>> res = new RuleSet(context.placeholderRegistry()).subst(x.stream().map(y -> {
|
|
||||||
if (y.getPairOp() == PairOperator.SMALLERDOTWC)
|
|
||||||
y.setPairOp(PairOperator.EQUALSDOT);
|
|
||||||
return y; // alle Paare a <.? b erden durch a =. b ersetzt
|
|
||||||
}).collect(Collectors.toCollection(HashSet::new)));
|
|
||||||
if (res.isPresent()) {// wenn subst ein Erg liefert wurde was veraendert
|
|
||||||
return new TypeUnifyTask(context).applyTypeUnificationRules(res.get(), finiteClosure);
|
|
||||||
} else
|
|
||||||
return x; // wenn nichts veraendert wurde wird x zurueckgegeben
|
|
||||||
}).collect(Collectors.toCollection(HashSet::new));
|
|
||||||
}
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
}
|
|
||||||
generateBytecode(sf, results.stream().map((unifyPairs -> new ResultSet(UnifyTypeFactory.convert(unifyPairs, Pair.generateTPHMap(cons), context.placeholderRegistry())))).collect(Collectors.toList()));
|
|
||||||
return new LanguageServerTransferObject(results.stream().map((unifyPairs -> new ResultSet(UnifyTypeFactory.convert(unifyPairs, Pair.generateTPHMap(cons), context.placeholderRegistry())))).collect(Collectors.toList()), sf, ASTTypePrinter.print(sf), generatedGenerics);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Vererbt alle Variancen bei Paaren (a <. theta) oder (Theta <. a) wenn a eine Variance !=0 hat auf alle Typvariablen in Theta.
|
* Vererbt alle Variancen bei Paaren (a <. theta) oder (Theta <. a) wenn a eine Variance !=0 hat auf alle Typvariablen in Theta.
|
||||||
*
|
*
|
||||||
@@ -686,7 +625,7 @@ public class JavaTXCompiler {
|
|||||||
|
|
||||||
public final JavaClassRegistry classRegistry = new JavaClassRegistry();
|
public final JavaClassRegistry classRegistry = new JavaClassRegistry();
|
||||||
|
|
||||||
private void parse(SourceFileContext tree, File sourceFile) throws IOException, java.lang.ClassNotFoundException {
|
private void parse(SourceFileContext tree, File sourceFile) throws IOException, ClassNotFoundException {
|
||||||
SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null), sourceFile.getName());
|
SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null), sourceFile.getName());
|
||||||
environment.addClassesToRegistry(classRegistry, tree, sourceFile, this);
|
environment.addClassesToRegistry(classRegistry, tree, sourceFile, this);
|
||||||
var classes = new ArrayList<ClassOrInterface>();
|
var classes = new ArrayList<ClassOrInterface>();
|
||||||
@@ -697,29 +636,45 @@ public class JavaTXCompiler {
|
|||||||
sf.imports.addAll(generator.imports);
|
sf.imports.addAll(generator.imports);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void parseAll() throws IOException, ClassNotFoundException {
|
||||||
|
var treeList = generateSources(sources);
|
||||||
|
for (var i = 0; i < sources.size(); i++) {
|
||||||
|
parse(treeList.get(i), sources.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void generateBytecode() throws ClassNotFoundException, IOException {
|
public void generateBytecode() throws ClassNotFoundException, IOException {
|
||||||
|
// The compiler has two modes, one is to infer all files together and the other one is to do them in sequence
|
||||||
if (inferTogether) {
|
if (inferTogether) {
|
||||||
|
parseAll();
|
||||||
|
|
||||||
var files = sourceFiles.keySet().stream().toList();
|
var files = sourceFiles.keySet().stream().toList();
|
||||||
var typeinferenceResult = this.typeInference(files);
|
var typeinferenceResult = this.typeInference(files);
|
||||||
for (var file : files) {
|
for (var file : files) {
|
||||||
var sf = sourceFiles.get(file);
|
var sf = sourceFiles.get(file);
|
||||||
if (sf.isGenerated()) continue;
|
if (sf.isGenerated()) continue;
|
||||||
var classes = generateBytecode(sf, typeinferenceResult);
|
var classes = generateBytecode(sf, typeinferenceResult);
|
||||||
|
checkWarnings();
|
||||||
sf.setGenerated();
|
sf.setGenerated();
|
||||||
writeClassFile(classes, outputPath == null ? file.getParentFile() : outputPath, outputPath == null);
|
writeClassFile(classes, file);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (var file : sourceFiles.keySet()) {
|
var treeList = generateSources(sources);
|
||||||
|
for (var i = 0; i < sources.size(); i++) {
|
||||||
|
var file = sources.get(i);
|
||||||
|
parse(treeList.get(i), file);
|
||||||
|
|
||||||
var sf = sourceFiles.get(file);
|
var sf = sourceFiles.get(file);
|
||||||
if (sf.isGenerated()) continue;
|
if (sf.isGenerated()) continue;
|
||||||
var classes = generateBytecode(file);
|
var classes = generateBytecode(file);
|
||||||
|
checkWarnings();
|
||||||
sf.setGenerated();
|
sf.setGenerated();
|
||||||
writeClassFile(classes, outputPath == null ? file.getParentFile() : outputPath, outputPath == null);
|
writeClassFile(classes, file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<JavaClassName, byte[]> generateBytecode(File sourceFile) throws ClassNotFoundException, IOException {
|
private Map<JavaClassName, byte[]> generateBytecode(File sourceFile) throws ClassNotFoundException, IOException {
|
||||||
var sf = sourceFiles.get(sourceFile);
|
var sf = sourceFiles.get(sourceFile);
|
||||||
if (sf.isGenerated()) return null;
|
if (sf.isGenerated()) return null;
|
||||||
List<ResultSet> typeinferenceResult = this.typeInference(sourceFile);
|
List<ResultSet> typeinferenceResult = this.typeInference(sourceFile);
|
||||||
@@ -753,11 +708,95 @@ public class JavaTXCompiler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO Maybe move this elsewhere it doesn't really belong here
|
||||||
|
private static RefTypeOrTPHOrWildcardOrGeneric toRefType(TargetType type) {
|
||||||
|
return switch(type) {
|
||||||
|
case TargetExtendsWildcard targetExtendsWildcard ->
|
||||||
|
new ExtendsWildcardType(toRefType(targetExtendsWildcard.innerType()), new NullToken());
|
||||||
|
case TargetSuperWildcard targetSuperWildcard ->
|
||||||
|
new SuperWildcardType(toRefType(targetSuperWildcard.innerType()), new NullToken());
|
||||||
|
case TargetGenericType targetGenericType -> new GenericRefType(targetGenericType.name(), new NullToken());
|
||||||
|
case TargetPrimitiveType targetPrimitiveType -> toRefType(TargetType.toWrapper(targetPrimitiveType));
|
||||||
|
case TargetFunNType targetFunNType ->
|
||||||
|
new RefType(new JavaClassName(FunNGenerator.getSuperClassName(targetFunNType.funNParams().size() - 1, targetFunNType.returnArguments())),
|
||||||
|
targetFunNType.funNParams().stream().map(JavaTXCompiler::toRefType).toList(), new NullToken());
|
||||||
|
case TargetSpecializedType targetSpecializedType ->
|
||||||
|
new RefType(new JavaClassName(targetSpecializedType.name()),
|
||||||
|
targetSpecializedType.params().stream().map(JavaTXCompiler::toRefType).toList(), new NullToken()
|
||||||
|
);
|
||||||
|
case null -> new Void(new NullToken());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ParameterList toParameterList(List<MethodParameter> params) {
|
||||||
|
return new ParameterList(params.stream().map(mp
|
||||||
|
-> (Pattern) new FormalParameter(mp.pattern().name(), toRefType(mp.pattern().type()), new NullToken())).toList(),
|
||||||
|
new NullToken()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GenericDeclarationList toGenerics(Set<TargetGeneric> generics) {
|
||||||
|
return new GenericDeclarationList(
|
||||||
|
generics.stream().map(g
|
||||||
|
-> new GenericTypeVar(g.name(), List.of(toRefType(g.bound())), new NullToken(), new NullToken())
|
||||||
|
).toList(), new NullToken()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This writes back the compiled target structure into the loadedClasses map so that it can be used
|
||||||
|
* as an input in further processing
|
||||||
|
* @param target
|
||||||
|
*/
|
||||||
|
private void writeBackToClass(TargetStructure target) {
|
||||||
|
var fielddecl = new ArrayList<Field>();
|
||||||
|
for (var field : target.fields()) {
|
||||||
|
fielddecl.add(new Field(field.name(), toRefType(field.type()), field.access(), new NullToken()));
|
||||||
|
}
|
||||||
|
|
||||||
|
var methods = new ArrayList<Method>();
|
||||||
|
for (var method : target.methods()) {
|
||||||
|
methods.add(new Method(method.access(), method.name(), toRefType(method.signature().returnType()),
|
||||||
|
toParameterList(method.signature().parameters()), new Block(new ArrayList<>(), new NullToken()), toGenerics(method.signature().generics()), new NullToken())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
var constructors = new ArrayList<Constructor>();
|
||||||
|
for (var ctor : target.constructors()) {
|
||||||
|
constructors.add(new Constructor(ctor.access(), target.getName(), new RefType(target.qualifiedName(), new NullToken()),
|
||||||
|
toParameterList(ctor.parameters()), new Block(new ArrayList<>(), new NullToken()), toGenerics(ctor.generics()), new NullToken())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
var isInterface = target instanceof TargetInterface;
|
||||||
|
var generics = new GenericDeclarationList(toGenerics(target.generics()), new NullToken());
|
||||||
|
var superClass = isInterface ? ASTFactory.createObjectType() : (RefType) toRefType(target.superType());
|
||||||
|
var isFunctionalInterface = false; // TODO We might actually want to generate those
|
||||||
|
var implementedInterfaces = target.implementingInterfaces().stream()
|
||||||
|
.map(t -> (RefType) toRefType(t)).toList();
|
||||||
|
List<RefType> permittedSubtypes = null;
|
||||||
|
if (target instanceof TargetInterface tinf && tinf.permittedSubtypes() != null) {
|
||||||
|
permittedSubtypes = tinf.permittedSubtypes().stream().map(t -> (RefType) toRefType(t)).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
var clazz = new ClassOrInterface(
|
||||||
|
target.modifiers(), target.qualifiedName(),
|
||||||
|
fielddecl, Optional.empty(), Optional.empty(),
|
||||||
|
methods, constructors, generics, superClass,
|
||||||
|
isInterface, isFunctionalInterface, implementedInterfaces,
|
||||||
|
permittedSubtypes, new NullToken(), ""
|
||||||
|
);
|
||||||
|
loadedClasses.put(target.qualifiedName(), clazz);
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized Map<JavaClassName, byte[]> generateBytecode(SourceFile sf, List<ResultSet> typeInferenceResult) {
|
public synchronized Map<JavaClassName, byte[]> generateBytecode(SourceFile sf, List<ResultSet> typeInferenceResult) {
|
||||||
|
this.generatedWarnings.clear();
|
||||||
var converter = new ASTToTargetAST(this, typeInferenceResult, sf, classLoader);
|
var converter = new ASTToTargetAST(this, typeInferenceResult, sf, classLoader);
|
||||||
var generatedClasses = new HashMap<JavaClassName, byte[]>();
|
var generatedClasses = new HashMap<JavaClassName, byte[]>();
|
||||||
for (var clazz : sf.getClasses()) {
|
for (var clazz : sf.getClasses()) {
|
||||||
var codegen = new Codegen(converter.convert(clazz), this, converter);
|
var target = converter.convert(clazz);
|
||||||
|
writeBackToClass(target);
|
||||||
|
var codegen = new Codegen(target, this, converter);
|
||||||
var code = codegen.generate();
|
var code = codegen.generate();
|
||||||
generatedClasses.put(clazz.getClassName(), code);
|
generatedClasses.put(clazz.getClassName(), code);
|
||||||
}
|
}
|
||||||
@@ -769,6 +808,10 @@ public class JavaTXCompiler {
|
|||||||
return generatedClasses;
|
return generatedClasses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void writeClassFile(Map<JavaClassName, byte[]> classFiles, File file) throws IOException {
|
||||||
|
writeClassFile(classFiles, outputPath == null ? file.getParentFile() : outputPath, outputPath == null);
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized void writeClassFile(Map<JavaClassName, byte[]> classFiles, File path, boolean preserveHierarchy) throws IOException {
|
public synchronized void writeClassFile(Map<JavaClassName, byte[]> classFiles, File path, boolean preserveHierarchy) throws IOException {
|
||||||
FileOutputStream output;
|
FileOutputStream output;
|
||||||
for (JavaClassName name : classFiles.keySet()) {
|
for (JavaClassName name : classFiles.keySet()) {
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package de.dhbwstuttgart.exceptions;
|
||||||
|
|
||||||
|
public class CompilerException extends RuntimeException {
|
||||||
|
public CompilerException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package de.dhbwstuttgart.exceptions;
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
public class CompilerWarning extends RuntimeException {
|
||||||
|
private final Token offset;
|
||||||
|
|
||||||
|
public CompilerWarning(Token offset, String message) {
|
||||||
|
super(message);
|
||||||
|
this.offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Token getOffset() {
|
||||||
|
return this.offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,6 @@ package de.dhbwstuttgart.exceptions;
|
|||||||
public class DebugException extends RuntimeException {
|
public class DebugException extends RuntimeException {
|
||||||
|
|
||||||
public DebugException(String message) {
|
public DebugException(String message) {
|
||||||
System.err.print(message);
|
super(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,9 +2,8 @@ package de.dhbwstuttgart.exceptions;
|
|||||||
|
|
||||||
import org.antlr.v4.runtime.Token;
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
public class ParserError extends TypeinferenceException{
|
public class ParserError extends RuntimeException{
|
||||||
|
public ParserError(String message) {
|
||||||
public ParserError(Token offset){
|
super(message);
|
||||||
super("Fehler beim Parsen", offset);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package de.dhbwstuttgart.exceptions;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class WarningsException extends RuntimeException {
|
||||||
|
|
||||||
|
public final List<CompilerWarning> compilerWarnings;
|
||||||
|
|
||||||
|
public WarningsException(String message, List<CompilerWarning> warnings) {
|
||||||
|
super(message);
|
||||||
|
this.compilerWarnings = Collections.unmodifiableList(warnings);
|
||||||
|
}
|
||||||
|
}
|
||||||
+21
-6
@@ -2,8 +2,11 @@ package de.dhbwstuttgart.languageServerInterface;
|
|||||||
|
|
||||||
|
|
||||||
import de.dhbwstuttgart.bytecode.Codegen;
|
import de.dhbwstuttgart.bytecode.Codegen;
|
||||||
|
import de.dhbwstuttgart.core.ConsoleInterface;
|
||||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||||
import de.dhbwstuttgart.environment.IByteArrayClassLoader;
|
import de.dhbwstuttgart.environment.IByteArrayClassLoader;
|
||||||
|
import de.dhbwstuttgart.exceptions.CompilerWarning;
|
||||||
|
import de.dhbwstuttgart.exceptions.WarningsException;
|
||||||
import de.dhbwstuttgart.languageServerInterface.model.LanguageServerTransferObject;
|
import de.dhbwstuttgart.languageServerInterface.model.LanguageServerTransferObject;
|
||||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||||
import de.dhbwstuttgart.syntaxtree.SourceFile;
|
import de.dhbwstuttgart.syntaxtree.SourceFile;
|
||||||
@@ -11,6 +14,7 @@ import de.dhbwstuttgart.syntaxtree.factory.NameGenerator;
|
|||||||
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
|
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
|
||||||
import de.dhbwstuttgart.target.generate.GenericsResult;
|
import de.dhbwstuttgart.target.generate.GenericsResult;
|
||||||
import de.dhbwstuttgart.target.tree.TargetStructure;
|
import de.dhbwstuttgart.target.tree.TargetStructure;
|
||||||
|
import de.dhbwstuttgart.util.Logger;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
@@ -31,7 +35,7 @@ import java.util.stream.Stream;
|
|||||||
public class LanguageServerInterface {
|
public class LanguageServerInterface {
|
||||||
|
|
||||||
|
|
||||||
public LanguageServerTransferObject getResultSetAndAbastractSyntax(String path, String resetNamesTo) throws IOException, URISyntaxException, ClassNotFoundException {
|
public LanguageServerTransferObject getResultSetAndAbstractSyntax(String path, String resetNamesTo) throws IOException, URISyntaxException, ClassNotFoundException {
|
||||||
NameGenerator.resetTo(resetNamesTo);
|
NameGenerator.resetTo(resetNamesTo);
|
||||||
return getResultSetAndAbstractSyntax(path);
|
return getResultSetAndAbstractSyntax(path);
|
||||||
|
|
||||||
@@ -52,21 +56,32 @@ public class LanguageServerInterface {
|
|||||||
*/
|
*/
|
||||||
public LanguageServerTransferObject getResultSetAndAbstractSyntax(String pathAsString){
|
public LanguageServerTransferObject getResultSetAndAbstractSyntax(String pathAsString){
|
||||||
System.setOut(new PrintStream(OutputStream.nullOutputStream()));
|
System.setOut(new PrintStream(OutputStream.nullOutputStream()));
|
||||||
|
ConsoleInterface.logLevel = Logger.LogLevel.DEBUG;
|
||||||
|
ConsoleInterface.writeLogFiles = true;
|
||||||
|
ConsoleInterface.writeToConsole = false;
|
||||||
|
Logger.resetLogs();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var uri = new URI(pathAsString);
|
var uri = new URI(pathAsString);
|
||||||
var path = Path.of(uri);
|
var path = Path.of(uri);
|
||||||
var file = path.toFile();
|
var file = path.toFile();
|
||||||
Files.createDirectories(path.getParent().resolve("out"));
|
Files.createDirectories(path.getParent().resolve("out"));
|
||||||
var compiler = new JavaTXCompiler(List.of(file), List.of(path.getParent().toFile()), path.getParent().resolve("out").toFile(), false);
|
var compiler = new JavaTXCompiler(List.of(file), List.of(path.getParent().toFile()), path.getParent().resolve("out").toFile(), true);
|
||||||
|
compiler.parseAll();
|
||||||
|
|
||||||
|
List<CompilerWarning> warnings = List.of();
|
||||||
var parsedSource = compiler.sourceFiles.get(file);
|
var parsedSource = compiler.sourceFiles.get(file);
|
||||||
var tiResults = compiler.typeInference(file);
|
var tiResults = compiler.typeInference(file);
|
||||||
|
var classFiles = compiler.generateBytecode(parsedSource, tiResults);
|
||||||
|
|
||||||
Map<JavaClassName, byte[]> bytecode = compiler.generateBytecode(parsedSource, tiResults);
|
try {
|
||||||
Files.createDirectories(path.getParent().resolve("out"));
|
compiler.checkWarnings();
|
||||||
compiler.writeClassFile(bytecode, path.getParent().resolve("out").toFile(), false);
|
compiler.writeClassFile(classFiles, file);
|
||||||
|
} catch(WarningsException e) {
|
||||||
|
warnings = e.compilerWarnings;
|
||||||
|
}
|
||||||
|
|
||||||
return new LanguageServerTransferObject(tiResults, parsedSource, "", compiler.getGeneratedGenerics());
|
return new LanguageServerTransferObject(parsedSource, "", compiler.lastConstraints, compiler.getGeneratedGenerics(), warnings);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e.getMessage(), e);
|
throw new RuntimeException(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-5
@@ -2,8 +2,10 @@ package de.dhbwstuttgart.languageServerInterface.model;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.exceptions.CompilerWarning;
|
||||||
import de.dhbwstuttgart.syntaxtree.SourceFile;
|
import de.dhbwstuttgart.syntaxtree.SourceFile;
|
||||||
import de.dhbwstuttgart.target.generate.GenericsResult;
|
import de.dhbwstuttgart.target.generate.GenericsResult;
|
||||||
|
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
||||||
import de.dhbwstuttgart.typeinference.result.ResultSet;
|
import de.dhbwstuttgart.typeinference.result.ResultSet;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -11,21 +13,23 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class LanguageServerTransferObject {
|
public class LanguageServerTransferObject {
|
||||||
List<ResultSet> resultSets;
|
|
||||||
SourceFile Ast;
|
SourceFile Ast;
|
||||||
String printedAst;
|
String printedAst;
|
||||||
Map<SourceFile, List<GenericsResult>> generatedGenerics = new HashMap<>();
|
Map<SourceFile, List<GenericsResult>> generatedGenerics = new HashMap<>();
|
||||||
|
List<CompilerWarning> warnings;
|
||||||
|
ConstraintSet<?> constraints;
|
||||||
|
|
||||||
|
public LanguageServerTransferObject(SourceFile Ast, String printedAst, ConstraintSet<?> constraints, Map<SourceFile, List<GenericsResult>> generatedGenerics, List<CompilerWarning> warnings) {
|
||||||
public LanguageServerTransferObject(List<ResultSet> resultSets, SourceFile Ast, String printedAst, Map<SourceFile, List<GenericsResult>> generatedGenerics) {
|
|
||||||
this.resultSets = resultSets;
|
|
||||||
this.Ast = Ast;
|
this.Ast = Ast;
|
||||||
this.printedAst = printedAst;
|
this.printedAst = printedAst;
|
||||||
|
this.constraints = constraints;
|
||||||
this.generatedGenerics = generatedGenerics;
|
this.generatedGenerics = generatedGenerics;
|
||||||
|
this.warnings = warnings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ResultSet> getResultSets() {return resultSets;}
|
|
||||||
public SourceFile getAst() {return Ast;}
|
public SourceFile getAst() {return Ast;}
|
||||||
public String getPrintedAst() {return printedAst;}
|
public String getPrintedAst() {return printedAst;}
|
||||||
public Map<SourceFile, List<GenericsResult>> getGeneratedGenerics() {return generatedGenerics;}
|
public Map<SourceFile, List<GenericsResult>> getGeneratedGenerics() {return generatedGenerics;}
|
||||||
|
public List<CompilerWarning> getWarnings() { return warnings; };
|
||||||
|
public ConstraintSet<?> getConstraints() { return constraints; };
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package de.dhbwstuttgart.parser;
|
package de.dhbwstuttgart.parser;
|
||||||
|
|
||||||
import de.dhbwstuttgart.environment.CompilationEnvironment;
|
import de.dhbwstuttgart.environment.CompilationEnvironment;
|
||||||
|
import de.dhbwstuttgart.exceptions.ParserError;
|
||||||
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.SyntaxTreeGenerator;
|
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.SyntaxTreeGenerator;
|
||||||
import de.dhbwstuttgart.parser.antlr.Java17Lexer;
|
import de.dhbwstuttgart.parser.antlr.Java17Lexer;
|
||||||
import de.dhbwstuttgart.parser.antlr.Java17Parser;
|
import de.dhbwstuttgart.parser.antlr.Java17Parser;
|
||||||
@@ -8,9 +9,7 @@ import de.dhbwstuttgart.parser.scope.JavaClassRegistry;
|
|||||||
import de.dhbwstuttgart.syntaxtree.SourceFile;
|
import de.dhbwstuttgart.syntaxtree.SourceFile;
|
||||||
|
|
||||||
import de.dhbwstuttgart.util.Logger;
|
import de.dhbwstuttgart.util.Logger;
|
||||||
import org.antlr.v4.runtime.CharStream;
|
import org.antlr.v4.runtime.*;
|
||||||
import org.antlr.v4.runtime.CharStreams;
|
|
||||||
import org.antlr.v4.runtime.CommonTokenStream;
|
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
@@ -21,13 +20,25 @@ public class JavaTXParser {
|
|||||||
|
|
||||||
public static Logger logger = new Logger("Parser");
|
public static Logger logger = new Logger("Parser");
|
||||||
|
|
||||||
|
public static class ThrowingErrorListener extends BaseErrorListener {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol,
|
||||||
|
int line, int charPositionInLine, String msg, RecognitionException e) {
|
||||||
|
throw new ParserError("Syntax error at line " + line + ":" + charPositionInLine + " - " + msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static Java17Parser.SourceFileContext parse(File source) throws IOException, java.lang.ClassNotFoundException {
|
public static Java17Parser.SourceFileContext parse(File source) throws IOException, java.lang.ClassNotFoundException {
|
||||||
InputStream stream = new FileInputStream(source);
|
InputStream stream = new FileInputStream(source);
|
||||||
// DEPRECATED: ANTLRInputStream input = new ANTLRInputStream(stream);
|
// DEPRECATED: ANTLRInputStream input = new ANTLRInputStream(stream);
|
||||||
|
var errorListener = new ThrowingErrorListener();
|
||||||
CharStream input = CharStreams.fromStream(stream);
|
CharStream input = CharStreams.fromStream(stream);
|
||||||
Java17Lexer lexer = new Java17Lexer(input);
|
Java17Lexer lexer = new Java17Lexer(input);
|
||||||
|
lexer.addErrorListener(errorListener);
|
||||||
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||||
Java17Parser parser = new Java17Parser(tokens);
|
Java17Parser parser = new Java17Parser(tokens);
|
||||||
|
parser.addErrorListener(errorListener);
|
||||||
return parser.sourceFile();
|
return parser.sourceFile();
|
||||||
/*
|
/*
|
||||||
* SyntaxTreeGenerator generator = new SyntaxTreeGenerator(environment.getRegistry(source)); return generator.convert(tree);
|
* SyntaxTreeGenerator generator = new SyntaxTreeGenerator(environment.getRegistry(source)); return generator.convert(tree);
|
||||||
|
|||||||
@@ -149,9 +149,7 @@ public class StatementGenerator {
|
|||||||
if (fp.typeType() != null) {
|
if (fp.typeType() != null) {
|
||||||
type = TypeGenerator.convert(fp.typeType(), reg, generics);
|
type = TypeGenerator.convert(fp.typeType(), reg, generics);
|
||||||
} else {
|
} else {
|
||||||
type = methodparameters?
|
type = TypePlaceholder.fresh(fp.getStart(), 1, false);
|
||||||
TypePlaceholder.fresh(fp.getStart(), 1, false)
|
|
||||||
: TypePlaceholder.fresh(fp.getStart(), 1, false);
|
|
||||||
}
|
}
|
||||||
ret.add(new FormalParameter(paramName, type, fp.getStart()));
|
ret.add(new FormalParameter(paramName, type, fp.getStart()));
|
||||||
localVars.put(paramName, type);
|
localVars.put(paramName, type);
|
||||||
@@ -407,14 +405,16 @@ public class StatementGenerator {
|
|||||||
|
|
||||||
private SwitchBlock convert(Java17Parser.SwitchBlockStatementGroupContext stmt) {
|
private SwitchBlock convert(Java17Parser.SwitchBlockStatementGroupContext stmt) {
|
||||||
List<SwitchLabel> labels = new ArrayList<>();
|
List<SwitchLabel> labels = new ArrayList<>();
|
||||||
stmt.switchLabel().forEach((label) -> {
|
var isDefault = false;
|
||||||
|
for (var label : stmt.switchLabel()) {
|
||||||
|
if (label instanceof SwitchLabelDefaultContext) isDefault = true;
|
||||||
labels.add(convert(label));
|
labels.add(convert(label));
|
||||||
});
|
}
|
||||||
List<Statement> block = new ArrayList<>();
|
List<Statement> block = new ArrayList<>();
|
||||||
stmt.blockStatement().stream().forEach((blockStmt) -> {
|
stmt.blockStatement().stream().forEach((blockStmt) -> {
|
||||||
block.addAll(convert(blockStmt));
|
block.addAll(convert(blockStmt));
|
||||||
});
|
});
|
||||||
return new SwitchBlock(labels, new Block(block, stmt.blockStatement(0).getStart()), false, stmt.getStart());
|
return new SwitchBlock(labels, new Block(block, stmt.blockStatement(0).getStart()), isDefault,false, stmt.getStart());
|
||||||
}
|
}
|
||||||
|
|
||||||
private SwitchLabel convert(SwitchLabelContext switchLabel) {
|
private SwitchLabel convert(SwitchLabelContext switchLabel) {
|
||||||
@@ -484,9 +484,10 @@ public class StatementGenerator {
|
|||||||
IdentifierContext identifierCtx = recordPatternCtx.identifier();
|
IdentifierContext identifierCtx = recordPatternCtx.identifier();
|
||||||
var text = (identifierCtx != null) ? identifierCtx.getText() : null;
|
var text = (identifierCtx != null) ? identifierCtx.getText() : null;
|
||||||
//Hier evtl. Typ anpassen -> wenn kein Typ bekannt ist push neuen Typ auf Hashtable
|
//Hier evtl. Typ anpassen -> wenn kein Typ bekannt ist push neuen Typ auf Hashtable
|
||||||
var type = recordPatternCtx.typeType() == null ? TypePlaceholder.fresh(recordPatternCtx.getStart()) : TypeGenerator.convert(recordPatternCtx.typeType(), reg, generics);
|
var ctor = TypeGenerator.convert(recordPatternCtx.ctor, reg, generics);
|
||||||
|
var type = recordPatternCtx.type == null ? ctor : TypeGenerator.convert(recordPatternCtx.type, reg, generics);
|
||||||
if (text != null) localVars.put(text, type);
|
if (text != null) localVars.put(text, type);
|
||||||
var ret = new RecordPattern(subPattern, text, type, recordPatternCtx.getStart());
|
var ret = new RecordPattern(subPattern, text, type, (RefType)ctor, recordPatternCtx.getStart());
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -700,7 +701,7 @@ public class StatementGenerator {
|
|||||||
case ConditionalassignexpressionContext condassign:
|
case ConditionalassignexpressionContext condassign:
|
||||||
return convert(condassign);
|
return convert(condassign);
|
||||||
default:
|
default:
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException(expression.getClass().toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -983,8 +984,11 @@ public class StatementGenerator {
|
|||||||
} else if (op.getText().equals("!")) {
|
} else if (op.getText().equals("!")) {
|
||||||
ret = new UnaryExpr(UnaryExpr.Operation.NOT, expr, TypePlaceholder.fresh(op), op);
|
ret = new UnaryExpr(UnaryExpr.Operation.NOT, expr, TypePlaceholder.fresh(op), op);
|
||||||
return ret;
|
return ret;
|
||||||
|
} else if (op.getText().equals("-")) {
|
||||||
|
ret = new UnaryExpr(UnaryExpr.Operation.MINUS, expr, TypePlaceholder.fresh(op), op);
|
||||||
|
return ret;
|
||||||
} else {
|
} else {
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException(op.getText());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1031,10 +1035,22 @@ public class StatementGenerator {
|
|||||||
private Expression convert(Java17Parser.LiteralContext literal) {
|
private Expression convert(Java17Parser.LiteralContext literal) {
|
||||||
switch (literal) {
|
switch (literal) {
|
||||||
case IntLiteralContext intliteral:
|
case IntLiteralContext intliteral:
|
||||||
|
var text = intliteral.getText();
|
||||||
|
var radix = 10;
|
||||||
|
if (text.startsWith("0x") || text.startsWith("0X")) {
|
||||||
|
radix = 16;
|
||||||
|
text = text.substring(2);
|
||||||
|
} else if (text.startsWith("0b") || text.startsWith("0B")) {
|
||||||
|
radix = 2;
|
||||||
|
text = text.substring(2);
|
||||||
|
} else if (text.startsWith("0") && text.length() > 1) {
|
||||||
|
radix = 8;
|
||||||
|
text = text.substring(1);
|
||||||
|
}
|
||||||
Number value;
|
Number value;
|
||||||
if (intliteral.getText().endsWith("l") || intliteral.getText().endsWith("L"))
|
if (text.endsWith("l") || text.endsWith("L"))
|
||||||
value = Long.parseLong(intliteral.getText().substring(0, intliteral.getText().length() - 1));
|
value = Long.parseLong(text.substring(0, text.length() - 1), radix);
|
||||||
else value = Integer.parseInt(intliteral.getText());
|
else value = Integer.parseInt(text, radix);
|
||||||
return new Literal(TypePlaceholder.fresh(literal.getStart()), value, intliteral.getStart());
|
return new Literal(TypePlaceholder.fresh(literal.getStart()), value, intliteral.getStart());
|
||||||
case FltLiteralContext floatliteral:
|
case FltLiteralContext floatliteral:
|
||||||
if (floatliteral.getText().endsWith("f") || floatliteral.getText().endsWith("F"))
|
if (floatliteral.getText().endsWith("f") || floatliteral.getText().endsWith("F"))
|
||||||
|
|||||||
+22
-18
@@ -80,7 +80,7 @@ public class SyntaxTreeGenerator {
|
|||||||
HashMap<String, Integer> allmodifiers = new HashMap<>();
|
HashMap<String, Integer> allmodifiers = new HashMap<>();
|
||||||
// PL 2018-11-01 fields eingefuegt, damit die fields immer die gleiche TPH
|
// PL 2018-11-01 fields eingefuegt, damit die fields immer die gleiche TPH
|
||||||
// bekommen
|
// bekommen
|
||||||
private final Map<String, FieldEntry> fields = new HashMap<>();
|
//private final Map<String, FieldEntry> fields = new HashMap<>();
|
||||||
// PL 2019-10-23: Muss für jede Klasse neu initilisiert werden
|
// PL 2019-10-23: Muss für jede Klasse neu initilisiert werden
|
||||||
List<Statement> fieldInitializations = new ArrayList<>();
|
List<Statement> fieldInitializations = new ArrayList<>();
|
||||||
List<Statement> staticFieldInitializations = new ArrayList<>();
|
List<Statement> staticFieldInitializations = new ArrayList<>();
|
||||||
@@ -178,6 +178,7 @@ public class SyntaxTreeGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ClassOrInterface convertClass(Java17Parser.ClassDeclarationContext ctx, int modifiers) {
|
private ClassOrInterface convertClass(Java17Parser.ClassDeclarationContext ctx, int modifiers) {
|
||||||
|
var fieldDecls = new HashMap<String, FieldEntry>();
|
||||||
String className = this.pkgName + (this.pkgName.length() > 0 ? "." : "") + ctx.identifier().getText();
|
String className = this.pkgName + (this.pkgName.length() > 0 ? "." : "") + ctx.identifier().getText();
|
||||||
JavaClassName name = reg.getName(className); // Holt den Package Namen mit dazu
|
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?
|
if (!name.toString().equals(className)) { // Kommt die Klasse schon in einem anderen Package vor?
|
||||||
@@ -204,9 +205,9 @@ public class SyntaxTreeGenerator {
|
|||||||
Boolean isInterface = false;
|
Boolean isInterface = false;
|
||||||
Boolean isFunctionalInterface = false;
|
Boolean isFunctionalInterface = false;
|
||||||
List<RefType> implementedInterfaces = new ArrayList<>();
|
List<RefType> implementedInterfaces = new ArrayList<>();
|
||||||
List<RefType> permittedSubtypes = new ArrayList<>();
|
List<RefType> permittedSubtypes = null;
|
||||||
for (ClassBodyDeclarationContext clsbodydecl : ctx.classBody().classBodyDeclaration()) {
|
for (ClassBodyDeclarationContext clsbodydecl : ctx.classBody().classBodyDeclaration()) {
|
||||||
convert(clsbodydecl, fielddecl, constructors, methods, name, superClass, generics);
|
convert(clsbodydecl, fielddecl, constructors, methods, name, superClass, generics, fieldDecls);
|
||||||
}
|
}
|
||||||
if (constructors.isEmpty()) {
|
if (constructors.isEmpty()) {
|
||||||
constructors.add(generateStandardConstructor(ctx.identifier().getText(), name, superClass, genericClassParameters, offset));
|
constructors.add(generateStandardConstructor(ctx.identifier().getText(), name, superClass, genericClassParameters, offset));
|
||||||
@@ -218,7 +219,7 @@ public class SyntaxTreeGenerator {
|
|||||||
if ((modifiers & 4096) != 0) {
|
if ((modifiers & 4096) != 0) {
|
||||||
if (!Objects.isNull(ctx.PERMITS())) {
|
if (!Objects.isNull(ctx.PERMITS())) {
|
||||||
// permitted subtypes sind letzte typeList (siehe Grammatikregel 'classDeclaration')
|
// permitted subtypes sind letzte typeList (siehe Grammatikregel 'classDeclaration')
|
||||||
permittedSubtypes.addAll(convert(ctx.typeList(ctx.typeList().size() - 1), generics));
|
permittedSubtypes = new ArrayList<>(convert(ctx.typeList(ctx.typeList().size() - 1), generics));
|
||||||
} else {
|
} else {
|
||||||
// falls sealed modifier ohne 'permits'-List oder umgekehrt
|
// falls sealed modifier ohne 'permits'-List oder umgekehrt
|
||||||
throw new NotImplementedException("Invalid sealed class declaration");
|
throw new NotImplementedException("Invalid sealed class declaration");
|
||||||
@@ -255,6 +256,8 @@ public class SyntaxTreeGenerator {
|
|||||||
List<Pattern> constructorParameters = new ArrayList<>();
|
List<Pattern> constructorParameters = new ArrayList<>();
|
||||||
List<Statement> constructorStatements = new ArrayList<>();
|
List<Statement> constructorStatements = new ArrayList<>();
|
||||||
|
|
||||||
|
var fieldDecl = new HashMap<String, FieldEntry>();
|
||||||
|
|
||||||
List<Java17Parser.RecordComponentContext> components = recordDeclaration.recordHeader().recordComponentList() != null ?
|
List<Java17Parser.RecordComponentContext> components = recordDeclaration.recordHeader().recordComponentList() != null ?
|
||||||
recordDeclaration.recordHeader().recordComponentList().recordComponent(): List.of();
|
recordDeclaration.recordHeader().recordComponentList().recordComponent(): List.of();
|
||||||
for (RecordComponentContext component : components) {
|
for (RecordComponentContext component : components) {
|
||||||
@@ -270,6 +273,7 @@ public class SyntaxTreeGenerator {
|
|||||||
fielddecl.add(new Field(fieldname, fieldtype, fieldmodifiers, fieldoffset));
|
fielddecl.add(new Field(fieldname, fieldtype, fieldmodifiers, fieldoffset));
|
||||||
constructorParameters.add(new FormalParameter(fieldname, fieldtype, 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), fieldname, fieldtype, fieldoffset);
|
||||||
|
fieldDecl.put(fieldname, new FieldEntry(fieldname, fieldtype, Modifier.PRIVATE));
|
||||||
constructorStatements.add(new Assign(new AssignToField(fieldvar), new LocalVar(fieldname, fieldtype, fieldoffset), offset));
|
constructorStatements.add(new Assign(new AssignToField(fieldvar), new LocalVar(fieldname, fieldtype, fieldoffset), offset));
|
||||||
Statement returnStatement = new Return(fieldvar, 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));
|
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));
|
||||||
@@ -279,7 +283,7 @@ public class SyntaxTreeGenerator {
|
|||||||
//Optional<Constructor> initializations = Optional.of(implicitConstructor);
|
//Optional<Constructor> initializations = Optional.of(implicitConstructor);
|
||||||
constructors.add(implicitConstructor);
|
constructors.add(implicitConstructor);
|
||||||
for (ClassBodyDeclarationContext bodyDeclaration : recordDeclaration.recordBody().classBodyDeclaration()) {
|
for (ClassBodyDeclarationContext bodyDeclaration : recordDeclaration.recordBody().classBodyDeclaration()) {
|
||||||
convert(bodyDeclaration, fielddecl, constructors, methods, name, superClass, generics);
|
convert(bodyDeclaration, fielddecl, constructors, methods, name, superClass, generics, fieldDecl);
|
||||||
}
|
}
|
||||||
if (!Objects.isNull(recordDeclaration.IMPLEMENTS())) {
|
if (!Objects.isNull(recordDeclaration.IMPLEMENTS())) {
|
||||||
implementedInterfaces.addAll(convert(recordDeclaration.typeList(), generics));
|
implementedInterfaces.addAll(convert(recordDeclaration.typeList(), generics));
|
||||||
@@ -288,7 +292,7 @@ public class SyntaxTreeGenerator {
|
|||||||
return new Record(modifiers, name, fielddecl, Optional.empty(), staticCtor, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, offset, fileName);
|
return new Record(modifiers, name, fielddecl, Optional.empty(), staticCtor, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, offset, fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void convert(ClassBodyDeclarationContext classBody, List<Field> fields, List<Constructor> constructors, List<Method> methods, JavaClassName name, RefType superClass, GenericsRegistry generics) {
|
private void convert(ClassBodyDeclarationContext classBody, List<Field> fields, List<Constructor> constructors, List<Method> methods, JavaClassName name, RefType superClass, GenericsRegistry generics, HashMap<String, FieldEntry> fieldDecls) {
|
||||||
MemberdeclContext member;
|
MemberdeclContext member;
|
||||||
if (classBody instanceof MemberdeclContext) {
|
if (classBody instanceof MemberdeclContext) {
|
||||||
member = (MemberdeclContext) classBody;
|
member = (MemberdeclContext) classBody;
|
||||||
@@ -303,11 +307,11 @@ public class SyntaxTreeGenerator {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MemberfieldContext memberfield: {
|
case MemberfieldContext memberfield: {
|
||||||
fields.addAll(convert(memberfield.fieldDeclaration(), membermodifiers, generics));
|
fields.addAll(convert(memberfield.fieldDeclaration(), membermodifiers, generics, fieldDecls));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MembermethodContext membermethod: {
|
case MembermethodContext membermethod: {
|
||||||
Method convertedMethod = convert(membermodifiers, membermethod.method(), name, superClass, generics);
|
Method convertedMethod = convert(membermodifiers, membermethod.method(), name, superClass, generics, fieldDecls);
|
||||||
if (convertedMethod instanceof Constructor constructor) {
|
if (convertedMethod instanceof Constructor constructor) {
|
||||||
constructors.add(constructor);
|
constructors.add(constructor);
|
||||||
} else {
|
} else {
|
||||||
@@ -316,7 +320,7 @@ public class SyntaxTreeGenerator {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MemberconstructorContext memberconstructor: {
|
case MemberconstructorContext memberconstructor: {
|
||||||
constructors.add(convert(membermodifiers, memberconstructor.constructor(), name, superClass, generics));
|
constructors.add(convert(membermodifiers, memberconstructor.constructor(), name, superClass, generics, fieldDecls));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -324,7 +328,7 @@ public class SyntaxTreeGenerator {
|
|||||||
}
|
}
|
||||||
} else if (classBody instanceof Java17Parser.ClassblockContext ctx && ctx.STATIC() != null) {
|
} else if (classBody instanceof Java17Parser.ClassblockContext ctx && ctx.STATIC() != null) {
|
||||||
// Static blocks
|
// Static blocks
|
||||||
var stmtgen = new StatementGenerator(superClass, compiler, reg, generics, this.fields, new HashMap<>());
|
var stmtgen = new StatementGenerator(superClass, compiler, reg, generics, fieldDecls, new HashMap<>());
|
||||||
var block = stmtgen.convert(((Java17Parser.ClassblockContext) classBody).block(), false);
|
var block = stmtgen.convert(((Java17Parser.ClassblockContext) classBody).block(), false);
|
||||||
staticFieldInitializations.addAll(block.statements);
|
staticFieldInitializations.addAll(block.statements);
|
||||||
}
|
}
|
||||||
@@ -434,7 +438,7 @@ public class SyntaxTreeGenerator {
|
|||||||
retType = new Void(bodydeclaration.refType().getStart());
|
retType = new Void(bodydeclaration.refType().getStart());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StatementGenerator stmtgen = new StatementGenerator(superClass, compiler, reg, generics, fields, new HashMap<>());
|
StatementGenerator stmtgen = new StatementGenerator(superClass, compiler, reg, generics, new HashMap<>(), new HashMap<>());
|
||||||
ParameterList paramlist = stmtgen.convert(bodydeclaration.formalParameters().formalParameterList(), true);
|
ParameterList paramlist = stmtgen.convert(bodydeclaration.formalParameters().formalParameterList(), true);
|
||||||
MethodBodyContext body = bodydeclaration.methodBody();
|
MethodBodyContext body = bodydeclaration.methodBody();
|
||||||
Block block = null;
|
Block block = null;
|
||||||
@@ -507,7 +511,7 @@ public class SyntaxTreeGenerator {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Method convert(int modifiers, Java17Parser.MethodContext methodContext, JavaClassName parentClass, RefType superClass, GenericsRegistry generics) {
|
public Method convert(int modifiers, Java17Parser.MethodContext methodContext, JavaClassName parentClass, RefType superClass, GenericsRegistry generics, Map<String, FieldEntry> fieldDecls) {
|
||||||
GenericsRegistry localgenerics = generics;
|
GenericsRegistry localgenerics = generics;
|
||||||
MethodDeclarationContext methoddeclaration;
|
MethodDeclarationContext methoddeclaration;
|
||||||
GenericDeclarationListContext genericdeclarations;
|
GenericDeclarationListContext genericdeclarations;
|
||||||
@@ -540,7 +544,7 @@ public class SyntaxTreeGenerator {
|
|||||||
retType = new Void(header.refType().getStart());
|
retType = new Void(header.refType().getStart());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StatementGenerator stmtgen = new StatementGenerator(superClass, compiler, reg, localgenerics, fields, new HashMap<>());
|
StatementGenerator stmtgen = new StatementGenerator(superClass, compiler, reg, localgenerics, fieldDecls, new HashMap<>());
|
||||||
ParameterList paramlist = stmtgen.convert(header.formalParameters().formalParameterList(), true);
|
ParameterList paramlist = stmtgen.convert(header.formalParameters().formalParameterList(), true);
|
||||||
MethodBodyContext body = methoddeclaration.methodBody();
|
MethodBodyContext body = methoddeclaration.methodBody();
|
||||||
Block block = null;
|
Block block = null;
|
||||||
@@ -559,7 +563,7 @@ public class SyntaxTreeGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Constructor convert(int modifiers, Java17Parser.ConstructorContext constructorContext, JavaClassName parentClass, RefType superClass, GenericsRegistry generics) {
|
public Constructor convert(int modifiers, Java17Parser.ConstructorContext constructorContext, JavaClassName parentClass, RefType superClass, GenericsRegistry generics, Map<String, FieldEntry> fields) {
|
||||||
GenericsRegistry localgenerics = generics;
|
GenericsRegistry localgenerics = generics;
|
||||||
GenericDeclarationListContext genericdeclarations;
|
GenericDeclarationListContext genericdeclarations;
|
||||||
GenericDeclarationList gtvDeclarations;
|
GenericDeclarationList gtvDeclarations;
|
||||||
@@ -586,7 +590,7 @@ public class SyntaxTreeGenerator {
|
|||||||
return new Constructor(modifiers, name, retType, paramlist, block, gtvDeclarations, constructordeclaration.getStart());
|
return new Constructor(modifiers, name, retType, paramlist, block, gtvDeclarations, constructordeclaration.getStart());
|
||||||
}
|
}
|
||||||
|
|
||||||
List<? extends Field> convert(Java17Parser.FieldDeclarationContext fieldDeclContext, int modifiers, GenericsRegistry generics) {
|
List<? extends Field> convert(Java17Parser.FieldDeclarationContext fieldDeclContext, int modifiers, GenericsRegistry generics, HashMap<String, FieldEntry> fields) {
|
||||||
List<Field> ret = new ArrayList<>();
|
List<Field> ret = new ArrayList<>();
|
||||||
RefTypeOrTPHOrWildcardOrGeneric fieldType;
|
RefTypeOrTPHOrWildcardOrGeneric fieldType;
|
||||||
if (fieldDeclContext.typeType() != null) {
|
if (fieldDeclContext.typeType() != null) {
|
||||||
@@ -598,9 +602,9 @@ public class SyntaxTreeGenerator {
|
|||||||
}
|
}
|
||||||
for (Java17Parser.VariableDeclaratorContext varDecl : fieldDeclContext.variableDeclarators().variableDeclarator()) {
|
for (Java17Parser.VariableDeclaratorContext varDecl : fieldDeclContext.variableDeclarators().variableDeclarator()) {
|
||||||
String fieldName = varDecl.variableDeclaratorId().getText();
|
String fieldName = varDecl.variableDeclaratorId().getText();
|
||||||
this.fields.put(fieldName, new FieldEntry(fieldName, fieldType, modifiers));
|
fields.put(fieldName, new FieldEntry(fieldName, fieldType, modifiers));
|
||||||
if (varDecl.variableInitializer() != null) {
|
if (varDecl.variableInitializer() != null) {
|
||||||
initializeField(varDecl, Modifier.isStatic(modifiers), fieldType, generics);
|
initializeField(varDecl, Modifier.isStatic(modifiers), fieldType, generics, fields);
|
||||||
}
|
}
|
||||||
ret.add(new Field(fieldName, fieldType, modifiers, varDecl.getStart()));
|
ret.add(new Field(fieldName, fieldType, modifiers, varDecl.getStart()));
|
||||||
}
|
}
|
||||||
@@ -612,7 +616,7 @@ public class SyntaxTreeGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initialize a field by creating implicit constructor.
|
// Initialize a field by creating implicit constructor.
|
||||||
private void initializeField(Java17Parser.VariableDeclaratorContext ctx, boolean isStatic, RefTypeOrTPHOrWildcardOrGeneric typeOfField, GenericsRegistry generics) {
|
private void initializeField(Java17Parser.VariableDeclaratorContext ctx, boolean isStatic, RefTypeOrTPHOrWildcardOrGeneric typeOfField, GenericsRegistry generics, Map<String, FieldEntry> fields) {
|
||||||
StatementGenerator statementGenerator = new StatementGenerator(superClass, compiler, reg, generics, fields, new HashMap<>());
|
StatementGenerator statementGenerator = new StatementGenerator(superClass, compiler, reg, generics, fields, new HashMap<>());
|
||||||
var assignment = statementGenerator.generateFieldAssignment(ctx, typeOfField);
|
var assignment = statementGenerator.generateFieldAssignment(ctx, typeOfField);
|
||||||
if (isStatic) {
|
if (isStatic) {
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ public class TypeGenerator {
|
|||||||
switch (typeContext.primitiveType().getText()) {
|
switch (typeContext.primitiveType().getText()) {
|
||||||
case "boolean":
|
case "boolean":
|
||||||
return new RefType(ASTFactory.createClass(Boolean.class).getClassName(), typeContext.getStart());
|
return new RefType(ASTFactory.createClass(Boolean.class).getClassName(), typeContext.getStart());
|
||||||
|
case "char":
|
||||||
|
return new RefType(ASTFactory.createClass(Character.class).getClassName(), typeContext.getStart());
|
||||||
case "int":
|
case "int":
|
||||||
return new RefType(ASTFactory.createClass(Integer.class).getClassName(), typeContext.getStart());
|
return new RefType(ASTFactory.createClass(Integer.class).getClassName(), typeContext.getStart());
|
||||||
case "double":
|
case "double":
|
||||||
@@ -71,7 +73,7 @@ public class TypeGenerator {
|
|||||||
case "float":
|
case "float":
|
||||||
return new RefType(ASTFactory.createClass(Float.class).getClassName(), typeContext.getStart());
|
return new RefType(ASTFactory.createClass(Float.class).getClassName(), typeContext.getStart());
|
||||||
default:
|
default:
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException(typeContext.primitiveType().getText());
|
||||||
}
|
}
|
||||||
} else if (!typeContext.LBRACK().isEmpty()) { // ArrayType über eckige Klammer prüfen
|
} else if (!typeContext.LBRACK().isEmpty()) { // ArrayType über eckige Klammer prüfen
|
||||||
// JavaTXParser.logger.info(unannTypeContext.getText());
|
// JavaTXParser.logger.info(unannTypeContext.getText());
|
||||||
|
|||||||
@@ -14,6 +14,6 @@ import javax.swing.text.html.Option;
|
|||||||
public class Record extends ClassOrInterface {
|
public class Record extends ClassOrInterface {
|
||||||
|
|
||||||
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, String fileName) {
|
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, String fileName) {
|
||||||
super(modifiers, name, fielddecl, fieldInitializations, staticInitializer, methods, constructors, genericClassParameters, superClass, isInterface, methods.size() == 1 ? true : false, implementedInterfaces, new ArrayList<>(), offset, fileName);
|
super(modifiers, name, fielddecl, fieldInitializations, staticInitializer, methods, constructors, genericClassParameters, superClass, isInterface, methods.size() == 1 ? true : false, implementedInterfaces, null, offset, fileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,7 @@ package de.dhbwstuttgart.syntaxtree;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||||
import org.antlr.v4.runtime.Token;
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
@@ -10,21 +11,22 @@ import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
|||||||
public class RecordPattern extends FormalParameter {
|
public class RecordPattern extends FormalParameter {
|
||||||
|
|
||||||
private final List<Pattern> subPattern;
|
private final List<Pattern> subPattern;
|
||||||
|
private final RefType ctor;
|
||||||
|
|
||||||
public RecordPattern(String name, RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
|
public RecordPattern(List<Pattern> subPattern, String name, RefTypeOrTPHOrWildcardOrGeneric type, RefType ctor, Token offset) {
|
||||||
super(name, type, offset);
|
|
||||||
subPattern = new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public RecordPattern(List<Pattern> subPattern, String name, RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
|
|
||||||
super(name, type, offset);
|
super(name, type, offset);
|
||||||
this.subPattern = subPattern;
|
this.subPattern = subPattern;
|
||||||
|
this.ctor = ctor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Pattern> getSubPattern() {
|
public List<Pattern> getSubPattern() {
|
||||||
return this.subPattern;
|
return this.subPattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RefType getCtor() {
|
||||||
|
return ctor;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accept(ASTVisitor visitor) {
|
public void accept(ASTVisitor visitor) {
|
||||||
visitor.visit(this);
|
visitor.visit(this);
|
||||||
|
|||||||
@@ -229,9 +229,6 @@ public class ASTFactory {
|
|||||||
public static Method createMethod(java.lang.reflect.Method jreMethod, String signature, java.lang.Class inClass, Boolean isInherited, Boolean isImplemented) {
|
public static Method createMethod(java.lang.reflect.Method jreMethod, String signature, java.lang.Class inClass, Boolean isInherited, Boolean isImplemented) {
|
||||||
String name = jreMethod.getName();
|
String name = jreMethod.getName();
|
||||||
RefTypeOrTPHOrWildcardOrGeneric returnType;
|
RefTypeOrTPHOrWildcardOrGeneric returnType;
|
||||||
if (inClass.getName().equals("Swap")){
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
Type jreRetType;
|
Type jreRetType;
|
||||||
if (jreMethod.getGenericReturnType() != null) {
|
if (jreMethod.getGenericReturnType() != null) {
|
||||||
jreRetType = jreMethod.getGenericReturnType();
|
jreRetType = jreMethod.getGenericReturnType();
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ public class MethodCall extends Statement
|
|||||||
|
|
||||||
//sind Tphs, repraesentieren im Resultset die Signatur der aufgerufenen Methoden, letztes Element ist der Returntyp
|
//sind Tphs, repraesentieren im Resultset die Signatur der aufgerufenen Methoden, letztes Element ist der Returntyp
|
||||||
public final ArrayList<TypePlaceholder> signature;
|
public final ArrayList<TypePlaceholder> signature;
|
||||||
|
public int modifiers;
|
||||||
|
|
||||||
public MethodCall(RefTypeOrTPHOrWildcardOrGeneric retType, Receiver receiver, String methodName, ArgumentList argumentList,
|
public MethodCall(RefTypeOrTPHOrWildcardOrGeneric retType, Receiver receiver, String methodName, ArgumentList argumentList,
|
||||||
RefTypeOrTPHOrWildcardOrGeneric receiverType, ArrayList<TypePlaceholder> signature, Token offset){
|
RefTypeOrTPHOrWildcardOrGeneric receiverType, ArrayList<TypePlaceholder> signature, Token offset){
|
||||||
@@ -44,6 +45,10 @@ public class MethodCall extends Statement
|
|||||||
return signature.subList(0, signature.size() - 1);
|
return signature.subList(0, signature.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TypePlaceholder returnType() {
|
||||||
|
return signature.getLast();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accept(StatementVisitor visitor) {
|
public void accept(StatementVisitor visitor) {
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,9 @@
|
|||||||
|
package de.dhbwstuttgart.target.generate;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class DiscardResultSet extends RuntimeException {
|
||||||
|
public DiscardResultSet() {}
|
||||||
|
}
|
||||||
@@ -21,6 +21,7 @@ import java.util.stream.Stream;
|
|||||||
public abstract class GenerateGenerics implements IGenerics {
|
public abstract class GenerateGenerics implements IGenerics {
|
||||||
|
|
||||||
private final JavaTXCompiler compiler;
|
private final JavaTXCompiler compiler;
|
||||||
|
private final ResultSet constraints;
|
||||||
|
|
||||||
public class TPH {
|
public class TPH {
|
||||||
private final TypePlaceholder wrap;
|
private final TypePlaceholder wrap;
|
||||||
@@ -129,7 +130,7 @@ public abstract class GenerateGenerics implements IGenerics {
|
|||||||
final Map<Method, Set<Pair>> computedGenericsOfMethods = new HashMap<>();
|
final Map<Method, Set<Pair>> computedGenericsOfMethods = new HashMap<>();
|
||||||
final Map<ClassOrInterface, Set<Pair>> computedGenericsOfClasses = new HashMap<>();
|
final Map<ClassOrInterface, Set<Pair>> computedGenericsOfClasses = new HashMap<>();
|
||||||
|
|
||||||
final Map<Method, Set<TPH>> usedTPHsOfMethods = new HashMap<>();
|
final Map<Method, Set<TPH>> usedTPHsOfMethodSignatures = new HashMap<>();
|
||||||
final Map<Method, Set<Pair>> familyOfMethods = new HashMap<>();
|
final Map<Method, Set<Pair>> familyOfMethods = new HashMap<>();
|
||||||
|
|
||||||
final Set<PairLT> simplifiedConstraints = new HashSet<>();
|
final Set<PairLT> simplifiedConstraints = new HashSet<>();
|
||||||
@@ -138,14 +139,15 @@ public abstract class GenerateGenerics implements IGenerics {
|
|||||||
|
|
||||||
GenerateGenerics(JavaTXCompiler compiler, ResultSet constraints) {
|
GenerateGenerics(JavaTXCompiler compiler, ResultSet constraints) {
|
||||||
this.compiler = compiler;
|
this.compiler = compiler;
|
||||||
|
this.constraints = constraints;
|
||||||
for (var constraint : constraints.results) {
|
for (var constraint : constraints.results) {
|
||||||
if (constraint instanceof PairTPHsmallerTPH p) {
|
if (constraint instanceof PairTPHsmallerTPH p) {
|
||||||
Target.logger.info(p.left + " " + p.left.getVariance());
|
Target.logger.debug(p.left + " " + p.left.getVariance());
|
||||||
simplifiedConstraints.add(new PairLT(new TPH(p.left), new TPH(p.right)));
|
simplifiedConstraints.add(new PairLT(new TPH(p.left), new TPH(p.right)));
|
||||||
} else if (constraint instanceof PairTPHEqualTPH p) {
|
} else if (constraint instanceof PairTPHEqualTPH p) {
|
||||||
equality.put(p.getLeft(), p.getRight());
|
equality.put(p.getLeft(), p.getRight());
|
||||||
} else if (constraint instanceof PairTPHequalRefTypeOrWildcardType p) {
|
} else if (constraint instanceof PairTPHequalRefTypeOrWildcardType p) {
|
||||||
Target.logger.info(p.left + " = " + p.right);
|
Target.logger.debug(p.left + " = " + p.right);
|
||||||
concreteTypes.put(new TPH(p.left), p.right);
|
concreteTypes.put(new TPH(p.left), p.right);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -240,7 +242,7 @@ public abstract class GenerateGenerics implements IGenerics {
|
|||||||
equality.put(entry.getKey(), to);
|
equality.put(entry.getKey(), to);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Target.logger.info(from + " -> " + to + " " + from.getVariance());
|
Target.logger.debug(from + " -> " + to + " " + from.getVariance());
|
||||||
//from.setVariance(to.getVariance());
|
//from.setVariance(to.getVariance());
|
||||||
equality.put(from, to);
|
equality.put(from, to);
|
||||||
referenced.remove(new TPH(from));
|
referenced.remove(new TPH(from));
|
||||||
@@ -309,7 +311,7 @@ public abstract class GenerateGenerics implements IGenerics {
|
|||||||
Set<TPH> T2s = new HashSet<>();
|
Set<TPH> T2s = new HashSet<>();
|
||||||
findTphs(superType, T2s);
|
findTphs(superType, T2s);
|
||||||
|
|
||||||
Target.logger.info("T1s: " + T1s + " T2s: " + T2s);
|
Target.logger.debug("T1s: " + T1s + " T2s: " + T2s);
|
||||||
//Ende
|
//Ende
|
||||||
|
|
||||||
superType = methodCall.receiverType;
|
superType = methodCall.receiverType;
|
||||||
@@ -324,7 +326,7 @@ public abstract class GenerateGenerics implements IGenerics {
|
|||||||
var optMethod = ASTToTargetAST.findMethod(owner, methodCall.name, methodCall.signatureArguments().stream().map(x -> getTargetType(x)).toList(), GenerateGenerics.this, compiler);
|
var optMethod = ASTToTargetAST.findMethod(owner, methodCall.name, methodCall.signatureArguments().stream().map(x -> getTargetType(x)).toList(), GenerateGenerics.this, compiler);
|
||||||
if (optMethod.isEmpty()) return;
|
if (optMethod.isEmpty()) return;
|
||||||
var method2 = optMethod.get();
|
var method2 = optMethod.get();
|
||||||
Target.logger.info("In: " + method.getName() + " Method: " + method2.getName());
|
Target.logger.debug("In: " + method.getName() + " Method: " + method2.getName());
|
||||||
var generics = family(owner, method2);
|
var generics = family(owner, method2);
|
||||||
|
|
||||||
// transitive and
|
// transitive and
|
||||||
@@ -357,7 +359,7 @@ public abstract class GenerateGenerics implements IGenerics {
|
|||||||
if (!T1s.contains(R1) || !T2s.contains(R2)) continue;
|
if (!T1s.contains(R1) || !T2s.contains(R2)) continue;
|
||||||
|
|
||||||
var newPair = new PairLT(R1, R2);
|
var newPair = new PairLT(R1, R2);
|
||||||
Target.logger.info("New pair: " + newPair);
|
Target.logger.debug("New pair: " + newPair);
|
||||||
newPairs.add(newPair);
|
newPairs.add(newPair);
|
||||||
|
|
||||||
if (!containsRelation(result, newPair))
|
if (!containsRelation(result, newPair))
|
||||||
@@ -558,7 +560,7 @@ public abstract class GenerateGenerics implements IGenerics {
|
|||||||
public Set<Pair> generics(ClassOrInterface owner, Method method) {
|
public Set<Pair> generics(ClassOrInterface owner, Method method) {
|
||||||
if (computedGenericsOfMethods.containsKey(method)) {
|
if (computedGenericsOfMethods.containsKey(method)) {
|
||||||
var cached = computedGenericsOfMethods.get(method);
|
var cached = computedGenericsOfMethods.get(method);
|
||||||
Target.logger.info("Cached " + method.getName() + ": " + cached);
|
Target.logger.debug("Cached " + method.getName() + ": " + cached);
|
||||||
return cached;
|
return cached;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -583,11 +585,11 @@ public abstract class GenerateGenerics implements IGenerics {
|
|||||||
referenced.addAll(typeVariablesOfClass);
|
referenced.addAll(typeVariablesOfClass);
|
||||||
|
|
||||||
generics(owner, method, result, referenced);
|
generics(owner, method, result, referenced);
|
||||||
usedTPHsOfMethods.put(method, usedTphs);
|
usedTPHsOfMethodSignatures.put(method, usedTphs);
|
||||||
|
|
||||||
normalize(result, classGenerics, usedTphs);
|
normalize(result, classGenerics, usedTphs);
|
||||||
|
|
||||||
Target.logger.info(this.getClass().getSimpleName() + " " + method.name + ": " + result);
|
Target.logger.debug(this.getClass().getSimpleName() + " " + method.name + ": " + result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -719,7 +721,7 @@ public abstract class GenerateGenerics implements IGenerics {
|
|||||||
if (!added) break;
|
if (!added) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Target.logger.info(chain + " " + chain.stream().map(e -> e.resolve().getVariance()).toList());
|
Target.logger.debug(chain + " " + chain.stream().map(e -> e.resolve().getVariance()).toList());
|
||||||
var variance = chain.get(0).resolve().getVariance();
|
var variance = chain.get(0).resolve().getVariance();
|
||||||
if (variance != 1) continue;
|
if (variance != 1) continue;
|
||||||
var index = 0;
|
var index = 0;
|
||||||
@@ -782,7 +784,7 @@ public abstract class GenerateGenerics implements IGenerics {
|
|||||||
}
|
}
|
||||||
doIterationForMethods(classOrInterface);
|
doIterationForMethods(classOrInterface);
|
||||||
for (var method : classOrInterface.getMethods()) {
|
for (var method : classOrInterface.getMethods()) {
|
||||||
var usedTPHs = usedTPHsOfMethods.get(method);
|
var usedTPHs = usedTPHsOfMethodSignatures.get(method);
|
||||||
if (usedTPHs != null)
|
if (usedTPHs != null)
|
||||||
referenced.addAll(usedTPHs);
|
referenced.addAll(usedTPHs);
|
||||||
}
|
}
|
||||||
@@ -914,7 +916,7 @@ public abstract class GenerateGenerics implements IGenerics {
|
|||||||
for (var pair : infima) {
|
for (var pair : infima) {
|
||||||
var returnTypes = findTypeVariables(method.getReturnType());
|
var returnTypes = findTypeVariables(method.getReturnType());
|
||||||
var chain = findConnectionToReturnType(returnTypes, input, new HashSet<>(), pair.left);
|
var chain = findConnectionToReturnType(returnTypes, input, new HashSet<>(), pair.left);
|
||||||
Target.logger.info("Find: " + pair.left + " " + chain);
|
Target.logger.debug("Find: " + pair.left + " " + chain);
|
||||||
chain.remove(pair.left);
|
chain.remove(pair.left);
|
||||||
if (chain.size() > 0) {
|
if (chain.size() > 0) {
|
||||||
for (var tph : chain)
|
for (var tph : chain)
|
||||||
@@ -952,8 +954,8 @@ public abstract class GenerateGenerics implements IGenerics {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
newTph.setVariance(variance);
|
newTph.setVariance(variance);
|
||||||
Target.logger.info(infima + " " + infima.stream().map(i -> i.right.resolve().getVariance()).toList());
|
Target.logger.debug(infima + " " + infima.stream().map(i -> i.right.resolve().getVariance()).toList());
|
||||||
Target.logger.info("Infima new TPH " + newTph + " variance " + variance);
|
Target.logger.debug("Infima new TPH " + newTph + " variance " + variance);
|
||||||
|
|
||||||
//referenced.add(newTph);
|
//referenced.add(newTph);
|
||||||
addToPairs(input, new PairLT(left, new TPH(newTph)));
|
addToPairs(input, new PairLT(left, new TPH(newTph)));
|
||||||
@@ -981,6 +983,11 @@ public abstract class GenerateGenerics implements IGenerics {
|
|||||||
} while (foundInfima);
|
} while (foundInfima);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultSet getResultSet() {
|
||||||
|
return this.constraints;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypePlaceholder getEqualType(TypePlaceholder tph) {
|
public TypePlaceholder getEqualType(TypePlaceholder tph) {
|
||||||
return this.equality.getOrDefault(tph, tph);
|
return this.equality.getOrDefault(tph, tph);
|
||||||
@@ -1001,7 +1008,9 @@ public abstract class GenerateGenerics implements IGenerics {
|
|||||||
public TargetType getTargetType(RefTypeOrTPHOrWildcardOrGeneric in) {
|
public TargetType getTargetType(RefTypeOrTPHOrWildcardOrGeneric in) {
|
||||||
if (in instanceof TypePlaceholder tph) {
|
if (in instanceof TypePlaceholder tph) {
|
||||||
if (equality.containsKey(tph)) {
|
if (equality.containsKey(tph)) {
|
||||||
return getTargetType(equality.get(tph));
|
var tph2 = equality.get(tph);
|
||||||
|
// Sanity check, they should not be equal!
|
||||||
|
if (!Objects.equals(in, tph2)) return getTargetType(tph2);
|
||||||
}
|
}
|
||||||
var type = concreteTypes.get(new TPH(tph));
|
var type = concreteTypes.get(new TPH(tph));
|
||||||
if (type == null) return new TargetGenericType(tph.getName());
|
if (type == null) return new TargetGenericType(tph.getName());
|
||||||
|
|||||||
@@ -15,6 +15,10 @@ public class GenericsResult {
|
|||||||
this.generics = generics;
|
this.generics = generics;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IGenerics getGenerics() {
|
||||||
|
return this.generics;
|
||||||
|
}
|
||||||
|
|
||||||
public GenericsResultSet get(ClassOrInterface clazz) {
|
public GenericsResultSet get(ClassOrInterface clazz) {
|
||||||
var generics = this.generics.generics(clazz);
|
var generics = this.generics.generics(clazz);
|
||||||
return new GenericsResultSet(generics, this.generics);
|
return new GenericsResultSet(generics, this.generics);
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
package de.dhbwstuttgart.target.generate;
|
package de.dhbwstuttgart.target.generate;
|
||||||
|
|
||||||
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
import de.dhbwstuttgart.typeinference.result.PairTPHequalRefTypeOrWildcardType;
|
import de.dhbwstuttgart.typeinference.result.PairTPHequalRefTypeOrWildcardType;
|
||||||
import de.dhbwstuttgart.typeinference.result.PairTPHsmallerTPH;
|
import de.dhbwstuttgart.typeinference.result.PairTPHsmallerTPH;
|
||||||
import de.dhbwstuttgart.typeinference.result.ResultPair;
|
import de.dhbwstuttgart.typeinference.result.ResultPair;
|
||||||
import org.antlr.v4.codegen.model.decl.ContextRuleListIndexedGetterDecl;
|
import org.antlr.v4.codegen.model.decl.ContextRuleListIndexedGetterDecl;
|
||||||
|
import org.jspecify.annotations.NonNull;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@@ -18,7 +20,12 @@ public class GenericsResultSet extends AbstractSet<GenerateGenerics.Pair> {
|
|||||||
this.generics = generics;
|
this.generics = generics;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IGenerics getGenerics() {
|
||||||
|
return this.generics;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@NonNull
|
||||||
public Iterator<GenerateGenerics.Pair> iterator() {
|
public Iterator<GenerateGenerics.Pair> iterator() {
|
||||||
return backing.iterator();
|
return backing.iterator();
|
||||||
}
|
}
|
||||||
@@ -28,17 +35,8 @@ public class GenericsResultSet extends AbstractSet<GenerateGenerics.Pair> {
|
|||||||
return backing.size();
|
return backing.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<ResultPair<?, ?>> getResultPairFor(TypePlaceholder tph) {
|
public Optional<GenerateGenerics.Pair> getResultPairFor(TypePlaceholder tph) {
|
||||||
var tph2 = generics.getEqualType(tph);
|
var tph2 = generics.getEqualType(tph);
|
||||||
return this.stream().filter(pair -> {
|
return this.stream().filter(pair -> pair.left.resolve().equals(tph2)).findFirst();
|
||||||
return pair.left.resolve().equals(tph2);
|
|
||||||
}).findFirst().map(pair -> {
|
|
||||||
ResultPair<?, ?> res = null;
|
|
||||||
if (pair instanceof GenerateGenerics.PairLT lt)
|
|
||||||
res = new PairTPHsmallerTPH(lt.left.resolve(), lt.right.resolve());
|
|
||||||
else if (pair instanceof GenerateGenerics.PairEQ eq)
|
|
||||||
res = new PairTPHequalRefTypeOrWildcardType(eq.left.resolve(), eq.right);
|
|
||||||
return res;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,7 @@ import de.dhbwstuttgart.syntaxtree.Method;
|
|||||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
import de.dhbwstuttgart.typeinference.result.ResultSet;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@@ -19,4 +20,6 @@ public interface IGenerics {
|
|||||||
TypePlaceholder getEqualType(TypePlaceholder tph);
|
TypePlaceholder getEqualType(TypePlaceholder tph);
|
||||||
|
|
||||||
TargetType getTargetType(RefTypeOrTPHOrWildcardOrGeneric in);
|
TargetType getTargetType(RefTypeOrTPHOrWildcardOrGeneric in);
|
||||||
|
|
||||||
|
ResultSet getResultSet();
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,7 @@ import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
|||||||
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||||
import de.dhbwstuttgart.target.tree.type.TargetGenericType;
|
import de.dhbwstuttgart.target.tree.type.TargetGenericType;
|
||||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
import de.dhbwstuttgart.typeinference.result.ResultSet;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -57,4 +58,9 @@ public class OverlayGenerics implements IGenerics {
|
|||||||
}
|
}
|
||||||
return ASTToTargetAST.convert(in, this, converter.compiler);
|
return ASTToTargetAST.convert(in, this, converter.compiler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultSet getResultSet() {
|
||||||
|
return wrapped.getResultSet();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package de.dhbwstuttgart.target.generate;
|
package de.dhbwstuttgart.target.generate;
|
||||||
|
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||||
import de.dhbwstuttgart.exceptions.DebugException;
|
import de.dhbwstuttgart.exceptions.DebugException;
|
||||||
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||||
@@ -216,6 +217,10 @@ public class StatementToTargetExpression implements ASTVisitor {
|
|||||||
return ASTToTargetAST.findMethod(converter.compiler.getClass(className), name, args, generics, compiler);
|
return ASTToTargetAST.findMethod(converter.compiler.getClass(className), name, args, generics, compiler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Optional<Method> findMethod(JavaClassName className, String name, List<TargetType> args, JavaTXCompiler compiler) {
|
||||||
|
return ASTToTargetAST.findMethod(converter.compiler.getClass(className), name, args, compiler);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(MethodCall methodCall) {
|
public void visit(MethodCall methodCall) {
|
||||||
var receiverType = converter.convert(methodCall.receiver.getType(), generics);
|
var receiverType = converter.convert(methodCall.receiver.getType(), generics);
|
||||||
@@ -223,8 +228,9 @@ public class StatementToTargetExpression implements ASTVisitor {
|
|||||||
|
|
||||||
var returnType = isFunNType ? TargetType.Object : converter.convert(methodCall.signature.getLast(), generics);
|
var returnType = isFunNType ? TargetType.Object : converter.convert(methodCall.signature.getLast(), generics);
|
||||||
var receiverName = new JavaClassName(converter.convert(methodCall.receiver.getType(), generics).name());
|
var receiverName = new JavaClassName(converter.convert(methodCall.receiver.getType(), generics).name());
|
||||||
var argList = methodCall.signature.stream().map(sig -> converter.convert(sig, generics)).toList();
|
var argList = methodCall.signatureArguments().stream().map(sig -> converter.convert(sig, generics)).toList();
|
||||||
argList = argList.subList(0, argList.size() - 1);
|
|
||||||
|
var receiverClass = converter.compiler.getClass(receiverName);
|
||||||
|
|
||||||
Method foundMethod = null;
|
Method foundMethod = null;
|
||||||
var isStatic = false;
|
var isStatic = false;
|
||||||
@@ -237,29 +243,75 @@ public class StatementToTargetExpression implements ASTVisitor {
|
|||||||
converter.addSignaturePair(methodCall.signatureArguments().get(i), methodCall.arglist.getArguments().get(i).getType());
|
converter.addSignaturePair(methodCall.signatureArguments().get(i), methodCall.arglist.getArguments().get(i).getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
var receiverClass = converter.compiler.getClass(receiverName);
|
|
||||||
if (methodCall.receiver instanceof ExpressionReceiver expressionReceiver && expressionReceiver.expr instanceof This) {
|
if (methodCall.receiver instanceof ExpressionReceiver expressionReceiver && expressionReceiver.expr instanceof This) {
|
||||||
if (receiverClass == null) throw new DebugException("Class " + receiverName + " does not exist!");
|
if (receiverClass == null) throw new DebugException("Class " + receiverName + " does not exist!");
|
||||||
var thisMethod = ASTToTargetAST.findMethod(receiverClass, methodCall.name, signature, generics, converter.compiler);
|
var thisMethod = ASTToTargetAST.findMethod(receiverClass, methodCall.name, signature, generics, converter.compiler);
|
||||||
ClassOrInterface finalReceiverClass = receiverClass;
|
ClassOrInterface finalReceiverClass = receiverClass;
|
||||||
foundMethod = thisMethod.orElseGet(() -> findMethod(finalReceiverClass.getSuperClass().getName(), methodCall.name, signature, generics, converter.compiler).orElseThrow());
|
var finalSignature = signature;
|
||||||
|
foundMethod = thisMethod.orElseGet(() -> findMethod(finalReceiverClass.getSuperClass().getName(), methodCall.name, finalSignature, generics, converter.compiler).orElseThrow());
|
||||||
} else if (!isFunNType) {
|
} else if (!isFunNType) {
|
||||||
receiverClass = converter.compiler.getClass(receiverName);
|
receiverClass = converter.compiler.getClass(receiverName);
|
||||||
if (receiverClass == null) throw new DebugException("Class " + receiverName + " does not exist!");
|
if (receiverClass == null) throw new DebugException("Class " + receiverName + " does not exist!");
|
||||||
foundMethod = findMethod(receiverName, methodCall.name, signature, generics, converter.compiler).orElseThrow();
|
var finalSignature = signature;
|
||||||
|
foundMethod = findMethod(receiverName, methodCall.name, signature, converter.compiler).orElseThrow(
|
||||||
|
() -> new DebugException("Method " + methodCall.name + " not found (" + finalSignature + ") on class " + receiverName)
|
||||||
|
);
|
||||||
|
//if (foundMethod != null) {
|
||||||
|
// signature = foundMethod.getParameterList().getFormalparalist().stream().map(pattern -> converter.convert(pattern.getType(), generics)).toList();
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isFunNType) {
|
if (!isFunNType) {
|
||||||
returnType = converter.convert(foundMethod.getReturnType(), generics);
|
// NOTE Not using the direct conversion method on converter to bypass adding the TPH to the used TPH list
|
||||||
argList = foundMethod.getParameterList().getFormalparalist().stream().map(e -> converter.convert(e.getType(), generics)).toList();
|
returnType = ASTToTargetAST.convert(foundMethod.getReturnType(), generics, converter.compiler);
|
||||||
|
signature = foundMethod.getParameterList().getFormalparalist().stream().map(e -> ASTToTargetAST.convert(e.getType(), generics, converter.compiler)).toList();
|
||||||
isStatic = Modifier.isStatic(foundMethod.modifier);
|
isStatic = Modifier.isStatic(foundMethod.modifier);
|
||||||
isPrivate = Modifier.isPrivate(foundMethod.modifier);
|
isPrivate = Modifier.isPrivate(foundMethod.modifier);
|
||||||
isInterface = receiverClass.isInterface();
|
isInterface = receiverClass.isInterface();
|
||||||
}
|
}
|
||||||
|
|
||||||
//System.out.println(argList);
|
// Filter out every case that has a different method signature for the current method
|
||||||
|
// We only want to throw out cases when the method signature matches
|
||||||
|
var conflicitGenerics = new ArrayList<ASTToTargetAST.Generics>();
|
||||||
|
|
||||||
|
if (converter.getCurrentMethod() != null) {
|
||||||
|
var params = converter.convert(converter.getCurrentMethod().getParameterList(), generics);
|
||||||
|
for (var g2 : converter.all) if (g2.javaGenerics() != generics) {
|
||||||
|
var newParams = converter.convert(converter.getCurrentMethod().getParameterList(), g2.javaGenerics());
|
||||||
|
if (Objects.equals(params, newParams)) conflicitGenerics.add(g2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If one of the receiver types is a super type of this one AND there is a method defined that matches the parameters, we discard this result
|
||||||
|
if (!isStatic && receiverType instanceof TargetRefType) {
|
||||||
|
for (var g2 : conflicitGenerics) {
|
||||||
|
var otherReceiver = converter.convert(methodCall.receiver.getType(), g2.javaGenerics());
|
||||||
|
if (!Objects.equals(receiverType, otherReceiver) && ASTToTargetAST.isSubtype(receiverType, otherReceiver, converter.compiler)) {
|
||||||
|
ClassOrInterface clazz = converter.compiler.getClass(new JavaClassName(otherReceiver.name()));
|
||||||
|
if (clazz != null) {
|
||||||
|
var optMethod = ASTToTargetAST.findMethod(clazz, methodCall.name, argList, converter.compiler);
|
||||||
|
if (optMethod.isPresent()) {
|
||||||
|
throw new DiscardResultSet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look at the signature in all result sets and check if a more specific insertion exists.
|
||||||
|
// If so, discard this result set by throwing an exception
|
||||||
|
for (var g2 : conflicitGenerics) {
|
||||||
|
for (var tph : Iterables.concat(methodCall.signatureArguments())) {
|
||||||
|
var currentType = converter.convert(tph, generics);
|
||||||
|
var type = converter.convert(tph, g2.javaGenerics());
|
||||||
|
if (!Objects.equals(type, currentType) && ASTToTargetAST.isSubtype(type, currentType, converter.compiler)) {
|
||||||
|
throw new DiscardResultSet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
result = new TargetMethodCall(
|
result = new TargetMethodCall(
|
||||||
converter.convert(methodCall.getType(), generics), returnType, argList,
|
converter.convert(methodCall.getType(), generics), returnType, signature,
|
||||||
converter.convert(methodCall.receiver, generics),
|
converter.convert(methodCall.receiver, generics),
|
||||||
methodCall.getArgumentList().getArguments().stream().map(arg -> converter.convert(arg, generics)).toList(),
|
methodCall.getArgumentList().getArguments().stream().map(arg -> converter.convert(arg, generics)).toList(),
|
||||||
receiverType, methodCall.name, isStatic, isInterface, isPrivate
|
receiverType, methodCall.name, isStatic, isInterface, isPrivate
|
||||||
@@ -424,7 +476,7 @@ public class StatementToTargetExpression implements ASTVisitor {
|
|||||||
.map(this::extractAllPatterns)
|
.map(this::extractAllPatterns)
|
||||||
.flatMap(List::stream).toList();
|
.flatMap(List::stream).toList();
|
||||||
case FormalParameter param -> List.of(new TypeVariants(param.getType(), converter.findAllVariants(param.getType())));
|
case FormalParameter param -> List.of(new TypeVariants(param.getType(), converter.findAllVariants(param.getType())));
|
||||||
default -> List.of();
|
case null, default -> List.of();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -605,6 +657,7 @@ public class StatementToTargetExpression implements ASTVisitor {
|
|||||||
@Override
|
@Override
|
||||||
public void visit(RecordPattern aRecordPattern) {
|
public void visit(RecordPattern aRecordPattern) {
|
||||||
result = new TargetComplexPattern(
|
result = new TargetComplexPattern(
|
||||||
|
converter.convert(aRecordPattern.getCtor(), generics),
|
||||||
converter.convert(aRecordPattern.getType(), generics),
|
converter.convert(aRecordPattern.getType(), generics),
|
||||||
aRecordPattern.getName(),
|
aRecordPattern.getName(),
|
||||||
aRecordPattern.getSubPattern().stream().map(x -> (TargetPattern) converter.convert(x, generics)).toList()
|
aRecordPattern.getSubPattern().stream().map(x -> (TargetPattern) converter.convert(x, generics)).toList()
|
||||||
|
|||||||
@@ -3,4 +3,9 @@ package de.dhbwstuttgart.target.tree;
|
|||||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
public record TargetGeneric(String name, TargetType bound) {
|
public record TargetGeneric(String name, TargetType bound) {
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
if (bound.equals(TargetType.Object)) return "'" + name;
|
||||||
|
else return "'" + name + " < " + bound;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
package de.dhbwstuttgart.target.tree;
|
package de.dhbwstuttgart.target.tree;
|
||||||
|
|
||||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetRefType;
|
||||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public record TargetInterface(int modifiers, JavaClassName qualifiedName, Set<TargetGeneric> generics, Set<TargetGeneric> txGenerics, List<TargetMethod> methods, List<TargetType> implementingInterfaces, TargetMethod staticConstructor) implements TargetStructure {
|
public record TargetInterface(int modifiers, JavaClassName qualifiedName, Set<TargetGeneric> generics, Set<TargetGeneric> txGenerics, List<TargetMethod> methods, List<TargetType> implementingInterfaces, TargetMethod staticConstructor, List<TargetRefType> permittedSubtypes) implements TargetStructure {
|
||||||
@Override
|
@Override
|
||||||
public TargetType superType() {
|
public TargetType superType() {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package de.dhbwstuttgart.target.tree;
|
package de.dhbwstuttgart.target.tree;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.Method;
|
||||||
|
import de.dhbwstuttgart.target.generate.IGenerics;
|
||||||
import de.dhbwstuttgart.target.tree.expression.TargetBlock;
|
import de.dhbwstuttgart.target.tree.expression.TargetBlock;
|
||||||
|
import de.dhbwstuttgart.target.tree.expression.TargetComplexPattern;
|
||||||
import de.dhbwstuttgart.target.tree.expression.TargetPattern;
|
import de.dhbwstuttgart.target.tree.expression.TargetPattern;
|
||||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
@@ -9,7 +12,18 @@ import java.util.List;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public record TargetMethod(int access, String name, TargetBlock block, Signature signature, Signature txSignature) {
|
public record TargetMethod(int access, String name, TargetBlock block, Signature signature, Signature txSignature, Method base, IGenerics generics) {
|
||||||
|
public TargetMethod(int access, String name, TargetBlock block, Signature signature, Signature txSignature) {
|
||||||
|
this(access, name, block, signature, txSignature, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this was a generated method it has an unwieldy name, this returns the original name
|
||||||
|
// like for instance dup$0$Ljava$lang$Integer$_$ -> dup
|
||||||
|
public String getSimpleName() {
|
||||||
|
if (name.contains("$")) return name.split("\\$")[0];
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
public record Signature(Set<TargetGeneric> generics, List<MethodParameter> parameters, TargetType returnType) {
|
public record Signature(Set<TargetGeneric> generics, List<MethodParameter> parameters, TargetType returnType) {
|
||||||
public String getSignature() {
|
public String getSignature() {
|
||||||
return TargetMethod.getSignature(generics, parameters, returnType);
|
return TargetMethod.getSignature(generics, parameters, returnType);
|
||||||
@@ -24,7 +38,13 @@ public record TargetMethod(int access, String name, TargetBlock block, Signature
|
|||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
Signature signature = (Signature) o;
|
Signature signature = (Signature) o;
|
||||||
return Objects.equals(parameters, signature.parameters);
|
if (this.parameters.size() != signature.parameters.size()) return false;
|
||||||
|
for (var i = 0; i < this.parameters.size(); i++) {
|
||||||
|
var p1 = this.parameters.get(i);
|
||||||
|
var p2 = signature.parameters.get(i);
|
||||||
|
if (!p1.pattern().fuzzyEquals(p2.pattern())) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -3,20 +3,27 @@ package de.dhbwstuttgart.target.tree.expression;
|
|||||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public record TargetComplexPattern(TargetType type, String name, List<TargetPattern> subPatterns) implements TargetPattern {
|
public record TargetComplexPattern(TargetType ctor, TargetType type, String name, List<TargetPattern> subPatterns) implements TargetPattern {
|
||||||
@Override
|
@Override
|
||||||
public TargetComplexPattern withType(TargetType type) {
|
public TargetComplexPattern withType(TargetType type) {
|
||||||
return new TargetComplexPattern(type, name, subPatterns);
|
return new TargetComplexPattern(ctor, type, name, subPatterns);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TargetComplexPattern withName(String name) {
|
public TargetComplexPattern withName(String name) {
|
||||||
return new TargetComplexPattern(type, name, subPatterns);
|
return new TargetComplexPattern(ctor, type, name, subPatterns);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return type + "(" + String.join(", ", subPatterns.stream().map(Object::toString).toList()) + ") " + name;
|
return type + "(" + String.join(", ", subPatterns.stream().map(Object::toString).toList()) + ") " + name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean fuzzyEquals(TargetPattern other) {
|
||||||
|
if (!(other instanceof TargetComplexPattern op)) return false;
|
||||||
|
return Objects.equals(this.type, op.type) && Objects.equals(this.subPatterns, op.subPatterns);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,8 @@ package de.dhbwstuttgart.target.tree.expression;
|
|||||||
|
|
||||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public sealed interface TargetPattern extends TargetExpression permits TargetComplexPattern, TargetExpressionPattern, TargetGuard, TargetTypePattern {
|
public sealed interface TargetPattern extends TargetExpression permits TargetComplexPattern, TargetExpressionPattern, TargetGuard, TargetTypePattern {
|
||||||
default String name() {
|
default String name() {
|
||||||
return null;
|
return null;
|
||||||
@@ -12,4 +14,8 @@ public sealed interface TargetPattern extends TargetExpression permits TargetCom
|
|||||||
TargetType type();
|
TargetType type();
|
||||||
|
|
||||||
TargetPattern withName(String name);
|
TargetPattern withName(String name);
|
||||||
|
|
||||||
|
default boolean fuzzyEquals(TargetPattern other) {
|
||||||
|
return Objects.equals(this.type(), other.type());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -3,8 +3,9 @@ package de.dhbwstuttgart.target.tree.type;
|
|||||||
import de.dhbwstuttgart.bytecode.FunNGenerator;
|
import de.dhbwstuttgart.bytecode.FunNGenerator;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public record TargetFunNType(String name, List<TargetType> funNParams, List<TargetType> params, int returnArguments) implements TargetSpecializedType {
|
public record TargetFunNType(String name, List<TargetType> funNParams, List<TargetType> params, int returnArguments, boolean isInterface) implements TargetSpecializedType {
|
||||||
|
|
||||||
public static TargetFunNType fromParams(List<TargetType> params, int returnArguments) {
|
public static TargetFunNType fromParams(List<TargetType> params, int returnArguments) {
|
||||||
return fromParams(params, params, returnArguments);
|
return fromParams(params, params, returnArguments);
|
||||||
@@ -12,7 +13,7 @@ public record TargetFunNType(String name, List<TargetType> funNParams, List<Targ
|
|||||||
|
|
||||||
public static TargetFunNType fromParams(List<TargetType> params, List<TargetType> realParams, int returnArguments) {
|
public static TargetFunNType fromParams(List<TargetType> params, List<TargetType> realParams, int returnArguments) {
|
||||||
var name = FunNGenerator.getSpecializedClassName(FunNGenerator.getArguments(params), FunNGenerator.getReturnType(params));
|
var name = FunNGenerator.getSpecializedClassName(FunNGenerator.getArguments(params), FunNGenerator.getReturnType(params));
|
||||||
return new TargetFunNType(name, params, realParams, returnArguments);
|
return new TargetFunNType(name, params, realParams, returnArguments, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toMethodDescriptor() {
|
public String toMethodDescriptor() {
|
||||||
@@ -39,4 +40,21 @@ public record TargetFunNType(String name, List<TargetType> funNParams, List<Targ
|
|||||||
var args = FunNGenerator.getArguments(funNParams);
|
var args = FunNGenerator.getArguments(funNParams);
|
||||||
return "LFun" + args.size() + "$$" + TargetSpecializedType.signatureParameters(funNParams) + ";";
|
return "LFun" + args.size() + "$$" + TargetSpecializedType.signatureParameters(funNParams) + ";";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object other) {
|
||||||
|
if (!(other instanceof TargetFunNType otfn)) return false;
|
||||||
|
if (!isInterface && !otfn.isInterface) {
|
||||||
|
if (!Objects.equals(name, otfn.name)) return false;
|
||||||
|
if (funNParams.size() != otfn.funNParams.size()) return false;
|
||||||
|
|
||||||
|
for (var i = 0; i < funNParams.size(); i++) {
|
||||||
|
var p1 = funNParams.get(i);
|
||||||
|
var p2 = otfn.funNParams.get(i);
|
||||||
|
if (p1 instanceof TargetGenericType || p2 instanceof TargetGenericType) continue;
|
||||||
|
if (!Objects.equals(p1, p2)) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return Objects.equals(name, otfn.name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -187,14 +187,14 @@ class TypeToInsertString implements ResultSetVisitor{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(TypePlaceholder typePlaceholder) {
|
public void visit(TypePlaceholder typePlaceholder) {
|
||||||
ResultPair<?, ?> resultPair = null;
|
GenerateGenerics.Pair resultPair = null;
|
||||||
if (constraints != null)
|
if (constraints != null)
|
||||||
resultPair = constraints.getResultPairFor(typePlaceholder).orElse(null);
|
resultPair = constraints.getResultPairFor(typePlaceholder).orElse(null);
|
||||||
if (resultPair == null)
|
if (resultPair == null)
|
||||||
resultPair = classConstraints.getResultPairFor(typePlaceholder).orElse(null);
|
resultPair = classConstraints.getResultPairFor(typePlaceholder).orElse(null);
|
||||||
|
|
||||||
if (resultPair != null)
|
if (resultPair != null)
|
||||||
insert += ((TypePlaceholder)resultPair.getLeft()).getName();
|
insert += resultPair.left.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -120,10 +120,12 @@ public class TYPE {
|
|||||||
|
|
||||||
var subPatternList = recordPattern.getSubPattern();
|
var subPatternList = recordPattern.getSubPattern();
|
||||||
var resolver = new GenericsResolverSameName();
|
var resolver = new GenericsResolverSameName();
|
||||||
var refType = (RefType) recordPattern.getType();
|
var ctorType = recordPattern.getCtor();
|
||||||
|
|
||||||
|
constraintSet.addUndConstraint(new Pair(ctorType, recordPattern.getType(), PairOperator.SMALLERDOT));
|
||||||
|
|
||||||
var allClasses = blockInformation.getAvailableClasses();
|
var allClasses = blockInformation.getAvailableClasses();
|
||||||
var typename = refType.getName().getClassName();
|
var typename = ctorType.getName().getClassName();
|
||||||
|
|
||||||
ClassOrInterface allClass = allClasses.stream().filter(c -> c.getClassName().getClassName().equals(typename)).findFirst().orElseThrow();
|
ClassOrInterface allClass = allClasses.stream().filter(c -> c.getClassName().getClassName().equals(typename)).findFirst().orElseThrow();
|
||||||
|
|
||||||
@@ -136,12 +138,12 @@ public class TYPE {
|
|||||||
FieldAssumption assumption = new FieldAssumption(param.getName(), allClass, param.getType(), blockInformation.getCurrentTypeScope());
|
FieldAssumption assumption = new FieldAssumption(param.getName(), allClass, param.getType(), blockInformation.getCurrentTypeScope());
|
||||||
|
|
||||||
var fieldCons = new Pair(el.getType(), assumption.getType(resolver), PairOperator.SMALLERDOT);
|
var fieldCons = new Pair(el.getType(), assumption.getType(resolver), PairOperator.SMALLERDOT);
|
||||||
var recvCons = new Pair(refType, assumption.getReceiverType(resolver), PairOperator.EQUALSDOT);
|
var recvCons = new Pair(ctorType, assumption.getReceiverType(resolver), PairOperator.EQUALSDOT);
|
||||||
constraintSet.addUndConstraint(fieldCons);
|
constraintSet.addUndConstraint(fieldCons);
|
||||||
constraintSet.addUndConstraint(recvCons);
|
constraintSet.addUndConstraint(recvCons);
|
||||||
|
|
||||||
for (var i = 0; i < refType.getParaList().size(); i++) {
|
for (var i = 0; i < ctorType.getParaList().size(); i++) {
|
||||||
constraintSet.addUndConstraint(new Pair(refType.getParaList().get(i),
|
constraintSet.addUndConstraint(new Pair(ctorType.getParaList().get(i),
|
||||||
((RefType)assumption.getReceiverType(resolver)).getParaList().get(i),
|
((RefType)assumption.getReceiverType(resolver)).getParaList().get(i),
|
||||||
PairOperator.EQUALSDOT));
|
PairOperator.EQUALSDOT));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,6 +254,9 @@ public class TYPEStmt implements StatementVisitor {
|
|||||||
} else if (unaryExpr.operation == UnaryExpr.Operation.NOT) {
|
} else if (unaryExpr.operation == UnaryExpr.Operation.NOT) {
|
||||||
constraintsSet.addUndConstraint(new Pair(unaryExpr.expr.getType(), unaryExpr.getType(), PairOperator.EQUALSDOT, loc(unaryExpr.getOffset())));
|
constraintsSet.addUndConstraint(new Pair(unaryExpr.expr.getType(), unaryExpr.getType(), PairOperator.EQUALSDOT, loc(unaryExpr.getOffset())));
|
||||||
constraintsSet.addUndConstraint(new Pair(unaryExpr.expr.getType(), new RefType(ASTFactory.createClass(java.lang.Boolean.class).getClassName(), new NullToken()), PairOperator.EQUALSDOT, loc(unaryExpr.getOffset())));
|
constraintsSet.addUndConstraint(new Pair(unaryExpr.expr.getType(), new RefType(ASTFactory.createClass(java.lang.Boolean.class).getClassName(), new NullToken()), PairOperator.EQUALSDOT, loc(unaryExpr.getOffset())));
|
||||||
|
} else if (unaryExpr.operation == UnaryExpr.Operation.MINUS) {
|
||||||
|
constraintsSet.addUndConstraint(new Pair(unaryExpr.expr.getType(), number, PairOperator.SMALLERDOT, loc(unaryExpr.getOffset())));
|
||||||
|
constraintsSet.addUndConstraint(new Pair(unaryExpr.expr.getType(), unaryExpr.getType(), PairOperator.EQUALSDOT, loc(unaryExpr.getOffset())));
|
||||||
} else {
|
} else {
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
@@ -392,6 +395,8 @@ public class TYPEStmt implements StatementVisitor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(BoolExpression expr) {
|
public void visit(BoolExpression expr) {
|
||||||
|
expr.lexpr.accept(this);
|
||||||
|
expr.rexpr.accept(this);
|
||||||
|
|
||||||
constraintsSet.addUndConstraint(new Pair(bool, expr.getType(), PairOperator.EQUALSDOT, loc(expr.getOffset())));
|
constraintsSet.addUndConstraint(new Pair(bool, expr.getType(), PairOperator.EQUALSDOT, loc(expr.getOffset())));
|
||||||
constraintsSet.addUndConstraint(new Pair(bool, expr.lexpr.getType(), PairOperator.EQUALSDOT, loc(expr.getOffset())));
|
constraintsSet.addUndConstraint(new Pair(bool, expr.lexpr.getType(), PairOperator.EQUALSDOT, loc(expr.getOffset())));
|
||||||
@@ -736,12 +741,12 @@ public class TYPEStmt implements StatementVisitor {
|
|||||||
|
|
||||||
for (int i = 0; i < foMethod.arglist.getArguments().size(); i++) {
|
for (int i = 0; i < foMethod.arglist.getArguments().size(); i++) {
|
||||||
// Zuordnung von MethoCall.signature (Argumenttypen) zu der Argumenttypen der ausgewaehlten Methode (assumption.params)
|
// Zuordnung von MethoCall.signature (Argumenttypen) zu der Argumenttypen der ausgewaehlten Methode (assumption.params)
|
||||||
ret.add(new Pair(foMethod.signature.get(i), assumption.getArgTypes().get(i), PairOperator.EQUALSDOT));
|
ret.add(new Pair(resolver.resolve(foMethod.signature.get(i)), resolver.resolve(assumption.getArgTypes().get(i)), PairOperator.EQUALSDOT));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Zuordnung von MethodCall.signature(ReturnType) zu dem ReturnType der ausgewaehlten Methode (assumption.returnType)
|
// Zuordnung von MethodCall.signature(ReturnType) zu dem ReturnType der ausgewaehlten Methode (assumption.returnType)
|
||||||
ret.add(new Pair(foMethod.signature.getLast(), assumption.getReturnType(), PairOperator.EQUALSDOT));
|
ret.add(new Pair(resolver.resolve(foMethod.signature.getLast()), resolver.resolve(assumption.getReturnType()), PairOperator.EQUALSDOT));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -870,8 +875,8 @@ public class TYPEStmt implements StatementVisitor {
|
|||||||
if (caseExpressionType == null) {
|
if (caseExpressionType == null) {
|
||||||
for (var child : switchStmt.getBlocks()) {
|
for (var child : switchStmt.getBlocks()) {
|
||||||
for (var label : child.getLabels()) {
|
for (var label : child.getLabels()) {
|
||||||
if (label.getPattern() == null) {
|
if (label.getPattern() == null && switchStmt.getSwitch().getType() instanceof TypePlaceholder) {
|
||||||
constraintsSet.addUndConstraint(new Pair(new RefType(new JavaClassName("java.lang.Object"), new NullToken()), switchStmt.getSwitch().getType(), PairOperator.SMALLERDOT, loc(label.getOffset())));
|
constraintsSet.addUndConstraint(new Pair(new RefType(new JavaClassName("java.lang.Object"), new NullToken()), switchStmt.getSwitch().getType(), PairOperator.EQUALSDOT, loc(label.getOffset())));
|
||||||
}
|
}
|
||||||
if (label.getPattern() instanceof RecordPattern) {
|
if (label.getPattern() instanceof RecordPattern) {
|
||||||
RecordPattern recordPattern = (RecordPattern) label.getPattern();
|
RecordPattern recordPattern = (RecordPattern) label.getPattern();
|
||||||
|
|||||||
@@ -755,7 +755,7 @@ public class RuleSet implements IRuleSet{
|
|||||||
|
|
||||||
UnifyType lhsType = pair.getLhsType();
|
UnifyType lhsType = pair.getLhsType();
|
||||||
UnifyType rhsType = pair.getRhsType();
|
UnifyType rhsType = pair.getRhsType();
|
||||||
if(!(lhsType instanceof ReferenceType) || !(rhsType instanceof ExtendsType))
|
if((!(lhsType instanceof ReferenceType) && !(lhsType instanceof FunNType)) || !(rhsType instanceof ExtendsType))
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
|
|
||||||
return Optional.of(new UnifyPair(lhsType, ((ExtendsType) rhsType).getExtendedType(), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair()));
|
return Optional.of(new UnifyPair(lhsType, ((ExtendsType) rhsType).getExtendedType(), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair()));
|
||||||
@@ -781,7 +781,7 @@ public class RuleSet implements IRuleSet{
|
|||||||
|
|
||||||
UnifyType lhsType = pair.getLhsType();
|
UnifyType lhsType = pair.getLhsType();
|
||||||
UnifyType rhsType = pair.getRhsType();
|
UnifyType rhsType = pair.getRhsType();
|
||||||
if(!(lhsType instanceof ReferenceType) || !(rhsType instanceof SuperType))
|
if((!(lhsType instanceof ReferenceType) && !(lhsType instanceof FunNType)) || !(rhsType instanceof SuperType))
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
|
|
||||||
return Optional.of(new UnifyPair(((SuperType) rhsType).getSuperedType(), lhsType, PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair()));
|
return Optional.of(new UnifyPair(((SuperType) rhsType).getSuperedType(), lhsType, PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair()));
|
||||||
@@ -904,7 +904,7 @@ public class RuleSet implements IRuleSet{
|
|||||||
|
|
||||||
var fiArgs = intf.getFunctionalInterfaceTypeArguments(refType);
|
var fiArgs = intf.getFunctionalInterfaceTypeArguments(refType);
|
||||||
var retType = fiArgs.getFirst();
|
var retType = fiArgs.getFirst();
|
||||||
var lhsArgs = intf.getFunctionalInterfaceTypeArguments(lhsType);
|
var lhsArgs = intf.getFunctionalInterfaceTypeArguments(lhsType); //FALSCHRUM????
|
||||||
var lhsRet = lhsArgs.getFirst();
|
var lhsRet = lhsArgs.getFirst();
|
||||||
|
|
||||||
Set<UnifyPair> result = new HashSet<>();
|
Set<UnifyPair> result = new HashSet<>();
|
||||||
@@ -972,16 +972,66 @@ public class RuleSet implements IRuleSet{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Set<UnifyPair>> smallerFunN(UnifyPair pair) {
|
public Optional<Set<UnifyPair>> smallerFunN(UnifyPair pair, IFiniteClosure fc) {
|
||||||
if(pair.getPairOp() != PairOperator.SMALLERDOT)
|
if(pair.getPairOp() != PairOperator.SMALLERDOT)
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
|
|
||||||
UnifyType lhsType = pair.getLhsType();
|
UnifyType lhsType = pair.getLhsType();
|
||||||
UnifyType rhsType = pair.getRhsType();
|
UnifyType rhsType = pair.getRhsType();
|
||||||
|
|
||||||
if(!(lhsType instanceof PlaceholderType) || !(rhsType instanceof FunNType))
|
if(!(rhsType instanceof FunNType))
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
|
|
||||||
|
/* muss nach angepasst werden */
|
||||||
|
//FunN$$<...> <. FunctinalInterface<...> wird umgewandelt in FunN$$<...> <. FunN$$<... args aus FuntionalInterface ...>
|
||||||
|
if (lhsType instanceof ReferenceType) {
|
||||||
|
UnifyType typeFI = pair.getLhsType();
|
||||||
|
|
||||||
|
Optional<UnifyType> opt = fc.getRightHandedFunctionalInterfaceType(typeFI.getName());
|
||||||
|
if(!opt.isPresent())
|
||||||
|
return Optional.empty();
|
||||||
|
|
||||||
|
if (!(typeFI instanceof ReferenceType refType) || !(refType instanceof FunInterfaceType intf))
|
||||||
|
return Optional.empty();
|
||||||
|
|
||||||
|
var fiArgs = intf.getFunctionalInterfaceTypeArguments(refType);
|
||||||
|
var retType = fiArgs.getFirst();
|
||||||
|
var rhsArgs = intf.getFunctionalInterfaceTypeArguments(rhsType);
|
||||||
|
var rhsRet = rhsArgs.getFirst();
|
||||||
|
|
||||||
|
Set<UnifyPair> result = new HashSet<>();
|
||||||
|
//if (retType instanceof ExtendsType) {
|
||||||
|
result.add(new UnifyPair(retType, rhsRet, PairOperator.SMALLER));
|
||||||
|
//} else if (retType instanceof SuperType) {
|
||||||
|
// return Optional.empty();
|
||||||
|
//} else {
|
||||||
|
// result.add(new UnifyPair(lhsRet, retType, PairOperator.EQUALSDOT));
|
||||||
|
//}
|
||||||
|
|
||||||
|
for (var i = 1; i < fiArgs.size(); i++) {
|
||||||
|
var rh = rhsArgs.get(i);
|
||||||
|
var lh = fiArgs.get(i);
|
||||||
|
|
||||||
|
//if (rh instanceof SuperType) {
|
||||||
|
result.add(new UnifyPair(rh, lh, PairOperator.SMALLER));
|
||||||
|
//} else if (rh instanceof ExtendsType) {
|
||||||
|
// return Optional.empty();
|
||||||
|
//} else {
|
||||||
|
// result.add(new UnifyPair(lh, rh, PairOperator.EQUALSDOT));
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Optional.of(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
if(!(lhsType instanceof PlaceholderType))
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FunNType funNRhsType = (FunNType) rhsType;
|
FunNType funNRhsType = (FunNType) rhsType;
|
||||||
|
|
||||||
Set<UnifyPair> result = new HashSet<UnifyPair>();
|
Set<UnifyPair> result = new HashSet<UnifyPair>();
|
||||||
@@ -1018,6 +1068,121 @@ public class RuleSet implements IRuleSet{
|
|||||||
return Optional.of(result);
|
return Optional.of(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Set<UnifyPair>> reduceFIFunN(UnifyPair pair, IFiniteClosure fc) {
|
||||||
|
if(pair.getPairOp() != PairOperator.EQUALSDOT)
|
||||||
|
return Optional.empty();
|
||||||
|
|
||||||
|
UnifyType lhsType = pair.getLhsType();
|
||||||
|
UnifyType rhsType = pair.getRhsType();
|
||||||
|
|
||||||
|
if(!(rhsType instanceof FunNType))
|
||||||
|
return Optional.empty();
|
||||||
|
|
||||||
|
/* muss nach angepasst werden */
|
||||||
|
//FunN$$<...> <. FunctinalInterface<...> wird umgewandelt in FunN$$<...> <. FunN$$<... args aus FuntionalInterface ...>
|
||||||
|
if (lhsType instanceof ReferenceType) {
|
||||||
|
UnifyType typeFI = pair.getLhsType();
|
||||||
|
|
||||||
|
Optional<UnifyType> opt = fc.getRightHandedFunctionalInterfaceType(typeFI.getName());
|
||||||
|
if(!opt.isPresent())
|
||||||
|
return Optional.empty();
|
||||||
|
|
||||||
|
if (!(typeFI instanceof ReferenceType refType) || !(refType instanceof FunInterfaceType intf))
|
||||||
|
return Optional.empty();
|
||||||
|
|
||||||
|
var fiArgs = intf.getFunctionalInterfaceTypeArguments(refType);
|
||||||
|
var retType = fiArgs.getFirst();
|
||||||
|
var rhsArgs = intf.getFunctionalInterfaceTypeArguments(rhsType);
|
||||||
|
var rhsRet = rhsArgs.getFirst();
|
||||||
|
|
||||||
|
Set<UnifyPair> result = new HashSet<>();
|
||||||
|
//if (retType instanceof ExtendsType) {
|
||||||
|
result.add(new UnifyPair(retType, rhsRet, PairOperator.EQUALSDOT));
|
||||||
|
//} else if (retType instanceof SuperType) {
|
||||||
|
// return Optional.empty();
|
||||||
|
//} else {
|
||||||
|
// result.add(new UnifyPair(lhsRet, retType, PairOperator.EQUALSDOT));
|
||||||
|
//}
|
||||||
|
|
||||||
|
for (var i = 1; i < fiArgs.size(); i++) {
|
||||||
|
var rh = rhsArgs.get(i);
|
||||||
|
var lh = fiArgs.get(i);
|
||||||
|
|
||||||
|
//if (rh instanceof SuperType) {
|
||||||
|
result.add(new UnifyPair(rh, lh, PairOperator.EQUALSDOT));
|
||||||
|
//} else if (rh instanceof ExtendsType) {
|
||||||
|
// return Optional.empty();
|
||||||
|
//} else {
|
||||||
|
// result.add(new UnifyPair(lh, rh, PairOperator.EQUALSDOT));
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Optional.of(result);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Set<UnifyPair>> reduceFunNFi(UnifyPair pair, IFiniteClosure fc) {
|
||||||
|
if(pair.getPairOp() != PairOperator.EQUALSDOT)
|
||||||
|
return Optional.empty();
|
||||||
|
|
||||||
|
UnifyType lhsType = pair.getLhsType();
|
||||||
|
UnifyType rhsType = pair.getRhsType();
|
||||||
|
|
||||||
|
if(!(lhsType instanceof FunNType))
|
||||||
|
return Optional.empty();
|
||||||
|
|
||||||
|
//FunN$$<...> <. FunctinalInterface<...> wird umgewandelt in FunN$$<...> <. FunN$$<... args aus FuntionalInterface ...>
|
||||||
|
if (rhsType instanceof ReferenceType) {
|
||||||
|
UnifyType typeFI = pair.getRhsType();
|
||||||
|
|
||||||
|
Optional<UnifyType> opt = fc.getRightHandedFunctionalInterfaceType(typeFI.getName());
|
||||||
|
if(!opt.isPresent())
|
||||||
|
return Optional.empty();
|
||||||
|
|
||||||
|
if (!(typeFI instanceof ReferenceType refType) || !(refType instanceof FunInterfaceType intf))
|
||||||
|
return Optional.empty();
|
||||||
|
|
||||||
|
var fiArgs = intf.getFunctionalInterfaceTypeArguments(refType);
|
||||||
|
var retType = fiArgs.getFirst();
|
||||||
|
var lhsArgs = intf.getFunctionalInterfaceTypeArguments(lhsType);
|
||||||
|
var lhsRet = lhsArgs.getFirst();
|
||||||
|
|
||||||
|
Set<UnifyPair> result = new HashSet<>();
|
||||||
|
//if (retType instanceof ExtendsType) {
|
||||||
|
// result.add(new UnifyPair(lhsRet, retType, PairOperator.SMALLERDOTWC));
|
||||||
|
//} else if (retType instanceof SuperType) {
|
||||||
|
// return Optional.empty();
|
||||||
|
//} else {
|
||||||
|
result.add(new UnifyPair(lhsRet, retType, PairOperator.EQUALSDOT));
|
||||||
|
//}
|
||||||
|
|
||||||
|
for (var i = 1; i < fiArgs.size(); i++) {
|
||||||
|
var lh = lhsArgs.get(i);
|
||||||
|
var rh = fiArgs.get(i);
|
||||||
|
|
||||||
|
//if (rh instanceof SuperType) {
|
||||||
|
// result.add(new UnifyPair(lh, rh, PairOperator.SMALLERDOTWC));
|
||||||
|
//} else if (rh instanceof ExtendsType) {
|
||||||
|
// return Optional.empty();
|
||||||
|
//} else {
|
||||||
|
result.add(new UnifyPair(lh, rh, PairOperator.EQUALSDOT));
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Optional.of(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<UnifyPair> reduceTph(UnifyPair pair) {
|
public Optional<UnifyPair> reduceTph(UnifyPair pair) {
|
||||||
if(pair.getPairOp() != PairOperator.SMALLERDOTWC)
|
if(pair.getPairOp() != PairOperator.SMALLERDOTWC)
|
||||||
@@ -1025,7 +1190,7 @@ public class RuleSet implements IRuleSet{
|
|||||||
|
|
||||||
UnifyType lhsType = pair.getLhsType();
|
UnifyType lhsType = pair.getLhsType();
|
||||||
UnifyType rhsType = pair.getRhsType();
|
UnifyType rhsType = pair.getRhsType();
|
||||||
if(!(lhsType instanceof PlaceholderType) || !(rhsType instanceof ReferenceType))
|
if(!(lhsType instanceof PlaceholderType) || (!(rhsType instanceof ReferenceType) && !(rhsType instanceof FunNType)))
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
|
|
||||||
return Optional.of(new UnifyPair(lhsType, rhsType, PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair()));
|
return Optional.of(new UnifyPair(lhsType, rhsType, PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair()));
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import de.dhbwstuttgart.util.Logger;
|
|||||||
import de.dhbwstuttgart.util.Pair;
|
import de.dhbwstuttgart.util.Pair;
|
||||||
import de.dhbwstuttgart.util.Tuple;
|
import de.dhbwstuttgart.util.Tuple;
|
||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -150,12 +151,15 @@ public class TypeUnifyTask extends CancellableTask<CompletableFuture<Set<Set<Uni
|
|||||||
this.fc = fc;
|
this.fc = fc;
|
||||||
this.oup = new OrderingUnifyPair(fc, context);
|
this.oup = new OrderingUnifyPair(fc, context);
|
||||||
|
|
||||||
this.context = (!ConsoleInterface.writeLogFiles || context.logger() instanceof ServerTaskLogger) ? context : context.newWithLogger(
|
if (!ConsoleInterface.writeLogFiles || context.logger() instanceof ServerTaskLogger) this.context = context;
|
||||||
|
else {
|
||||||
|
var baseFolder = Path.of(System.getProperty("user.dir"), "logFiles");
|
||||||
|
this.context = context.newWithLogger(
|
||||||
Logger.forFile(
|
Logger.forFile(
|
||||||
System.getProperty("user.dir") + "/logFiles/" + "Thread",
|
baseFolder.resolve("Thread_" + Thread.currentThread().hashCode() + ".txt").toString(), "Unify"
|
||||||
"Unify"
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/*Abbruchtest
|
/*Abbruchtest
|
||||||
if (thNo > 10) {
|
if (thNo > 10) {
|
||||||
@@ -1239,7 +1243,7 @@ public class TypeUnifyTask extends CancellableTask<CompletableFuture<Set<Set<Uni
|
|||||||
// FunN Rules
|
// FunN Rules
|
||||||
optSet = optSet.isPresent() ? optSet : rules.reduceFunN(pair);
|
optSet = optSet.isPresent() ? optSet : rules.reduceFunN(pair);
|
||||||
optSet = optSet.isPresent() ? optSet : rules.greaterFunN(pair, fc);
|
optSet = optSet.isPresent() ? optSet : rules.greaterFunN(pair, fc);
|
||||||
optSet = optSet.isPresent() ? optSet : rules.smallerFunN(pair);
|
optSet = optSet.isPresent() ? optSet : rules.smallerFunN(pair, fc);
|
||||||
|
|
||||||
// One of the rules has been applied
|
// One of the rules has been applied
|
||||||
if (optSet.isPresent()) {
|
if (optSet.isPresent()) {
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ public class UnifyResultModel {
|
|||||||
public void notify(Set<Set<UnifyPair>> eqPrimePrimeSet, UnifyContext context) {
|
public void notify(Set<Set<UnifyPair>> eqPrimePrimeSet, UnifyContext context) {
|
||||||
Set<Set<UnifyPair>> eqPrimePrimeSetRet = eqPrimePrimeSet.stream().map(x -> {
|
Set<Set<UnifyPair>> eqPrimePrimeSetRet = eqPrimePrimeSet.stream().map(x -> {
|
||||||
Optional<Set<UnifyPair>> res = new RuleSet(context.placeholderRegistry()).subst(x.stream().map(y -> {
|
Optional<Set<UnifyPair>> res = new RuleSet(context.placeholderRegistry()).subst(x.stream().map(y -> {
|
||||||
if (y.getPairOp() == PairOperator.SMALLERDOTWC) y.setPairOp(PairOperator.EQUALSDOT);
|
if (y.getPairOp() == PairOperator.SMALLERDOTWC)
|
||||||
|
y.setPairOp(PairOperator.EQUALSDOT);
|
||||||
return y; //alle Paare a <.? b erden durch a =. b ersetzt
|
return y; //alle Paare a <.? b erden durch a =. b ersetzt
|
||||||
}).collect(Collectors.toCollection(HashSet::new)));
|
}).collect(Collectors.toCollection(HashSet::new)));
|
||||||
if (res.isPresent()) {//wenn subst ein Erg liefert wurde was veraendert
|
if (res.isPresent()) {//wenn subst ein Erg liefert wurde was veraendert
|
||||||
|
|||||||
@@ -61,7 +61,9 @@ public interface IRuleSet {
|
|||||||
*/
|
*/
|
||||||
public Optional<Set<UnifyPair>> reduceFunN(UnifyPair pair);
|
public Optional<Set<UnifyPair>> reduceFunN(UnifyPair pair);
|
||||||
public Optional<Set<UnifyPair>> greaterFunN(UnifyPair pair, IFiniteClosure fc);
|
public Optional<Set<UnifyPair>> greaterFunN(UnifyPair pair, IFiniteClosure fc);
|
||||||
public Optional<Set<UnifyPair>> smallerFunN(UnifyPair pair);
|
public Optional<Set<UnifyPair>> smallerFunN(UnifyPair pair, IFiniteClosure fc);
|
||||||
|
public Optional<Set<UnifyPair>> reduceFIFunN(UnifyPair pair, IFiniteClosure fc);
|
||||||
|
public Optional<Set<UnifyPair>> reduceFunNFi(UnifyPair pair, IFiniteClosure fc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the erase1-Rule applies to the pair.
|
* Checks whether the erase1-Rule applies to the pair.
|
||||||
|
|||||||
@@ -685,6 +685,7 @@ public class FiniteClosure //extends Ordering<UnifyType> //entfernt PL 2018-12-1
|
|||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<UnifyType> getAncestors(UnifyType t) {
|
public Set<UnifyType> getAncestors(UnifyType t) {
|
||||||
if (!inheritanceGraph.containsKey(t))
|
if (!inheritanceGraph.containsKey(t))
|
||||||
|
|||||||
@@ -3,11 +3,13 @@ package de.dhbwstuttgart.util;
|
|||||||
import com.diogonunes.jcolor.Attribute;
|
import com.diogonunes.jcolor.Attribute;
|
||||||
import de.dhbwstuttgart.core.ConsoleInterface;
|
import de.dhbwstuttgart.core.ConsoleInterface;
|
||||||
import de.dhbwstuttgart.server.SocketServer;
|
import de.dhbwstuttgart.server.SocketServer;
|
||||||
import java.io.File;
|
import org.apache.commons.io.FileUtils;
|
||||||
import java.io.FileWriter;
|
import org.apache.commons.io.output.NullOutputStream;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.Writer;
|
import java.io.*;
|
||||||
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.sql.Timestamp;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -19,12 +21,42 @@ import static com.diogonunes.jcolor.Ansi.colorize;
|
|||||||
|
|
||||||
public class Logger {
|
public class Logger {
|
||||||
|
|
||||||
public static final Logger NULL_LOGGER = new NullLogger();
|
|
||||||
private static final DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
private static final DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
protected final Writer writer;
|
protected final Writer writer;
|
||||||
protected final String prefix;
|
protected final String prefix;
|
||||||
|
|
||||||
|
private static final File logFolder = new File(System.getProperty("user.dir") + "/logFiles/");
|
||||||
|
public static final Logger NULL_LOGGER = new NullLogger();
|
||||||
|
|
||||||
|
private static Writer defaultWriter;
|
||||||
|
private static void initLogger() {
|
||||||
|
if (defaultWriter != null) return;
|
||||||
|
if (!ConsoleInterface.writeLogFiles) return;
|
||||||
|
try {
|
||||||
|
Files.createDirectories(logFolder.toPath());
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Could not create directory for log files: " + logFolder, e);
|
||||||
|
}
|
||||||
|
var formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss");
|
||||||
|
var currentTimestamp = LocalDateTime.now().format(formatter);
|
||||||
|
try {
|
||||||
|
defaultWriter = new FileWriter(new File(logFolder, currentTimestamp + ".txt"));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void resetLogs() {
|
||||||
|
defaultWriter = null;
|
||||||
|
try {
|
||||||
|
FileUtils.cleanDirectory(logFolder);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
initLogger();
|
||||||
|
}
|
||||||
|
|
||||||
public Logger() {
|
public Logger() {
|
||||||
this(null, "");
|
this(null, "");
|
||||||
}
|
}
|
||||||
@@ -35,9 +67,15 @@ public class Logger {
|
|||||||
|
|
||||||
public Logger(Writer writer, String prefix) {
|
public Logger(Writer writer, String prefix) {
|
||||||
this.prefix = (Objects.equals(prefix, "")) ? "" : "["+prefix+"] ";
|
this.prefix = (Objects.equals(prefix, "")) ? "" : "["+prefix+"] ";
|
||||||
|
initLogger();
|
||||||
this.writer = writer;
|
this.writer = writer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Writer getWriter() {
|
||||||
|
if (writer != null) return writer;
|
||||||
|
return defaultWriter;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new logger object from the path provided
|
* Create a new logger object from the path provided
|
||||||
*
|
*
|
||||||
@@ -87,6 +125,7 @@ public class Logger {
|
|||||||
* @param logLevel If logLevel == error, then print to stderr or print to stdout otherwise
|
* @param logLevel If logLevel == error, then print to stderr or print to stdout otherwise
|
||||||
*/
|
*/
|
||||||
protected void print(String s, LogLevel logLevel) {
|
protected void print(String s, LogLevel logLevel) {
|
||||||
|
if (!ConsoleInterface.writeToConsole) return;
|
||||||
String coloredPrefix = this.getPrefix(logLevel);
|
String coloredPrefix = this.getPrefix(logLevel);
|
||||||
|
|
||||||
// if we are running the server, prepend the timestamp
|
// if we are running the server, prepend the timestamp
|
||||||
@@ -113,11 +152,13 @@ public class Logger {
|
|||||||
* @param s The string to print
|
* @param s The string to print
|
||||||
*/
|
*/
|
||||||
protected void write(String s) {
|
protected void write(String s) {
|
||||||
|
var writer = getWriter();
|
||||||
if (writer != null && ConsoleInterface.writeLogFiles) {
|
if (writer != null && ConsoleInterface.writeLogFiles) {
|
||||||
// writing to file should only be done when necessary
|
// writing to file should only be done when necessary
|
||||||
synchronized (writer) {
|
synchronized (writer) {
|
||||||
try {
|
try {
|
||||||
writer.write(s);
|
writer.write(s + "\n");
|
||||||
|
writer.flush();
|
||||||
}
|
}
|
||||||
catch (IOException exception) {
|
catch (IOException exception) {
|
||||||
throw new RuntimeException("Failed writing to file", exception);
|
throw new RuntimeException("Failed writing to file", exception);
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ import org.junit.jupiter.api.Test;
|
|||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.core.ConsoleInterface;
|
||||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||||
|
import de.dhbwstuttgart.util.Logger.LogLevel;
|
||||||
|
|
||||||
public class AllgemeinTest {
|
public class AllgemeinTest {
|
||||||
|
|
||||||
@@ -29,6 +31,7 @@ public class AllgemeinTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() throws Exception {
|
public void test() throws Exception {
|
||||||
|
ConsoleInterface.logLevel = LogLevel.DEBUG;
|
||||||
//String className = "GenTest";
|
//String className = "GenTest";
|
||||||
//String className = "Overloading_Generics";
|
//String className = "Overloading_Generics";
|
||||||
//String className = "Generics";
|
//String className = "Generics";
|
||||||
@@ -55,6 +58,7 @@ public class AllgemeinTest {
|
|||||||
//String className = "WildcardCaptureConversionTest";
|
//String className = "WildcardCaptureConversionTest";
|
||||||
//String className = "CaptureConversion";
|
//String className = "CaptureConversion";
|
||||||
//String className = "Pair";
|
//String className = "Pair";
|
||||||
|
//String className = "DublicateWildcard";
|
||||||
//String className = "UseWildcardPair";
|
//String className = "UseWildcardPair";
|
||||||
//String className = "Assign";
|
//String className = "Assign";
|
||||||
//String className = "StreamTest";
|
//String className = "StreamTest";
|
||||||
@@ -63,11 +67,14 @@ public class AllgemeinTest {
|
|||||||
//String className = "Cycle";
|
//String className = "Cycle";
|
||||||
//String className = "TripleTest";
|
//String className = "TripleTest";
|
||||||
//String className = "WildcardList";
|
//String className = "WildcardList";
|
||||||
String className = "List";
|
//String className = "List";
|
||||||
//String className = "Box";
|
//String className = "Box";
|
||||||
//String className = "GenBox";
|
//String className = "GenBox";
|
||||||
//String className = "InnerInf";
|
//String className = "InnerInf";
|
||||||
//String className = "Foo";
|
//String className = "Foo";
|
||||||
|
//String className = "Kombinatoren_failure";
|
||||||
|
String className = "Kombinatoren_After_Lazy";
|
||||||
|
//String className = "Parser";
|
||||||
//PL 2019-10-24: genutzt fuer unterschiedliche Tests
|
//PL 2019-10-24: genutzt fuer unterschiedliche Tests
|
||||||
path = System.getProperty("user.dir")+"/resources/AllgemeinTest/" + className + ".jav";
|
path = System.getProperty("user.dir")+"/resources/AllgemeinTest/" + className + ".jav";
|
||||||
//path = System.getProperty("user.dir")+"/src/test/resources/AllgemeinTest/Overloading_Generics.jav";
|
//path = System.getProperty("user.dir")+"/src/test/resources/AllgemeinTest/Overloading_Generics.jav";
|
||||||
@@ -76,7 +83,7 @@ public class AllgemeinTest {
|
|||||||
///*
|
///*
|
||||||
compiler = new JavaTXCompiler(
|
compiler = new JavaTXCompiler(
|
||||||
Lists.newArrayList(new File(path)),
|
Lists.newArrayList(new File(path)),
|
||||||
Lists.newArrayList(new File(System.getProperty("user.dir")+"/resources/bytecode/classFiles/")),
|
Lists.newArrayList(new File(System.getProperty("user.dir")+"/resources/AllgemeinTest/")),
|
||||||
new File(System.getProperty("user.dir")+"/resources/bytecode/classFiles/"), true);
|
new File(System.getProperty("user.dir")+"/resources/bytecode/classFiles/"), true);
|
||||||
//*/
|
//*/
|
||||||
compiler.generateBytecode();
|
compiler.generateBytecode();
|
||||||
|
|||||||
@@ -1,9 +1,19 @@
|
|||||||
|
|
||||||
|
import de.dhbwstuttgart.bytecode.CodeGenException;
|
||||||
import de.dhbwstuttgart.core.ConsoleInterface;
|
import de.dhbwstuttgart.core.ConsoleInterface;
|
||||||
|
import de.dhbwstuttgart.exceptions.CompilerException;
|
||||||
|
import de.dhbwstuttgart.exceptions.ParserError;
|
||||||
|
import de.dhbwstuttgart.exceptions.WarningsException;
|
||||||
import de.dhbwstuttgart.util.Logger;
|
import de.dhbwstuttgart.util.Logger;
|
||||||
|
import de.dhbwstuttgart.util.Logger.LogLevel;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -17,8 +27,14 @@ import static org.junit.jupiter.api.Assertions.*;
|
|||||||
import static targetast.TestCodegen.createClassLoader;
|
import static targetast.TestCodegen.createClassLoader;
|
||||||
import static targetast.TestCodegen.generateClassFiles;
|
import static targetast.TestCodegen.generateClassFiles;
|
||||||
|
|
||||||
@Execution(ExecutionMode.CONCURRENT)
|
|
||||||
public class TestComplete {
|
public class TestComplete {
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setup() throws IOException {
|
||||||
|
TestCodegen.outputPath.toFile().mkdirs();
|
||||||
|
FileUtils.cleanDirectory(TestCodegen.outputPath.toFile());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void applyLambdaTest() throws Exception {
|
public void applyLambdaTest() throws Exception {
|
||||||
var classFiles = generateClassFiles(createClassLoader(), "applyLambda.jav");
|
var classFiles = generateClassFiles(createClassLoader(), "applyLambda.jav");
|
||||||
@@ -318,9 +334,17 @@ public class TestComplete {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void overloadingSortingTest() throws Exception {
|
public void sortingTest() throws Exception {
|
||||||
var classFiles = generateClassFiles(createClassLoader(), "Sorting.jav");
|
var classFiles = generateClassFiles(createClassLoader(), "Sorting.jav");
|
||||||
var instance = classFiles.get("Sorting").getDeclaredConstructor().newInstance();
|
var Sorting = classFiles.get("Sorting");
|
||||||
|
var instance = Sorting.getDeclaredConstructor().newInstance();
|
||||||
|
|
||||||
|
var unsorted = List.of(10, 2, 1, 20, -1, 5);
|
||||||
|
var sorted = List.of(-1, 1, 2, 5, 10, 20);
|
||||||
|
var sort = Sorting.getDeclaredMethod("sort", List.class);
|
||||||
|
|
||||||
|
var result = sort.invoke(instance, unsorted);
|
||||||
|
assertEquals(sorted, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -655,6 +679,15 @@ public class TestComplete {
|
|||||||
System.out.println(clazz.getDeclaredMethod("toString").invoke(instance));
|
System.out.println(clazz.getDeclaredMethod("toString").invoke(instance));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void recordTestInstanceVariables() throws Exception {
|
||||||
|
var classFiles = generateClassFiles(createClassLoader(), "RecordTestInstanceVariables.jav");
|
||||||
|
var clazz = classFiles.get("RecordTestInstanceVariables");
|
||||||
|
var instance = clazz.getDeclaredConstructor(Integer.class, Integer.class).newInstance(10, 20);
|
||||||
|
assertEquals(10, clazz.getDeclaredMethod("getA").invoke(instance));
|
||||||
|
assertEquals(20, clazz.getDeclaredMethod("getB").invoke(instance));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void genericRecordTest() throws Exception {
|
public void genericRecordTest() throws Exception {
|
||||||
var classFiles = generateClassFiles(createClassLoader(), "GenericRecord.jav");
|
var classFiles = generateClassFiles(createClassLoader(), "GenericRecord.jav");
|
||||||
@@ -764,6 +797,8 @@ public class TestComplete {
|
|||||||
assertEquals("Second Element is a Text", swtch.invoke(instance, r1));
|
assertEquals("Second Element is a Text", swtch.invoke(instance, r1));
|
||||||
assertEquals("Second Element is a Number", swtch.invoke(instance, r2));
|
assertEquals("Second Element is a Number", swtch.invoke(instance, r2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Disabled("Infinite loop in type inference")
|
||||||
@Test
|
@Test
|
||||||
public void testSwitchListRecord() throws Exception {
|
public void testSwitchListRecord() throws Exception {
|
||||||
var classFiles = generateClassFiles(createClassLoader(), "SwitchRecordList.jav");
|
var classFiles = generateClassFiles(createClassLoader(), "SwitchRecordList.jav");
|
||||||
@@ -953,25 +988,83 @@ public class TestComplete {
|
|||||||
var list1 = ConsCtor.newInstance(1, ConsCtor.newInstance(2, ConsCtor.newInstance(3, EmptyCtor.newInstance())));
|
var list1 = ConsCtor.newInstance(1, ConsCtor.newInstance(2, ConsCtor.newInstance(3, EmptyCtor.newInstance())));
|
||||||
var list2 = ConsCtor.newInstance(4, ConsCtor.newInstance(5, ConsCtor.newInstance(6, EmptyCtor.newInstance())));
|
var list2 = ConsCtor.newInstance(4, ConsCtor.newInstance(5, ConsCtor.newInstance(6, EmptyCtor.newInstance())));
|
||||||
|
|
||||||
var append = clazz.getDeclaredMethod("append", Cons, Cons);
|
var append = clazz.getDeclaredMethod("append", List, List);
|
||||||
System.out.println(append.invoke(instance, list1, list2));
|
System.out.println(append.invoke(instance, list1, list2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPatternMatchingSpecificity() throws Exception {
|
||||||
|
var classFiles = generateClassFiles(createClassLoader(), "PatternMatchingSpecificity.jav");
|
||||||
|
|
||||||
|
var clazz = classFiles.get("PatternMatchingSpecificity");
|
||||||
|
var instance = clazz.getDeclaredConstructor().newInstance();
|
||||||
|
var R = classFiles.get("R");
|
||||||
|
|
||||||
|
Integer i = 20;
|
||||||
|
var r = R.getDeclaredConstructor(Number.class).newInstance(i);
|
||||||
|
|
||||||
|
var m = clazz.getDeclaredMethod("m", R);
|
||||||
|
assertEquals(1, m.invoke(instance, r));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPatternMatchingCaptures() throws Exception {
|
||||||
|
var classFiles = generateClassFiles(createClassLoader(), "PatternMatchingCaptures.jav");
|
||||||
|
|
||||||
|
var clazz = classFiles.get("PatternMatchingCaptures");
|
||||||
|
var R = classFiles.get("R");
|
||||||
|
var Base = classFiles.get("Base");
|
||||||
|
var r = R.getDeclaredConstructor(Integer.class).newInstance(10);
|
||||||
|
|
||||||
|
var instance = clazz.getDeclaredConstructor().newInstance();
|
||||||
|
var test1 = clazz.getDeclaredMethod("test1", Base);
|
||||||
|
assertEquals(10, test1.invoke(instance, r));
|
||||||
|
|
||||||
|
var test2 = clazz.getDeclaredMethod("test2", Base);
|
||||||
|
assertEquals(10, test1.invoke(instance, r));
|
||||||
|
|
||||||
|
var test3 = clazz.getDeclaredMethod("test3", R);
|
||||||
|
assertEquals(10, test1.invoke(instance, r));
|
||||||
|
|
||||||
|
var test4 = clazz.getDeclaredMethod("test4", R);
|
||||||
|
assertEquals(10, test1.invoke(instance, r));
|
||||||
|
|
||||||
|
var test5 = clazz.getDeclaredMethod("test5", R);
|
||||||
|
assertEquals(10, test1.invoke(instance, r));
|
||||||
|
|
||||||
|
var test6 = clazz.getDeclaredMethod("test6", R);
|
||||||
|
assertEquals(10, test1.invoke(instance, r));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPatternMatchingZip() throws Exception {
|
public void testPatternMatchingZip() throws Exception {
|
||||||
var classFiles = generateClassFiles(createClassLoader(), "PatternMatching.jav");
|
var classFiles = generateClassFiles(createClassLoader(), "PatternMatching.jav");
|
||||||
var clazz = classFiles.get("PatternMatching");
|
var clazz = classFiles.get("PatternMatching");
|
||||||
var instance = clazz.getDeclaredConstructor().newInstance();
|
var instance = clazz.getDeclaredConstructor().newInstance();
|
||||||
|
|
||||||
|
var Cons = classFiles.get("Cons");
|
||||||
|
var Empty = classFiles.get("Empty");
|
||||||
|
var List = classFiles.get("List");
|
||||||
|
|
||||||
|
var ConsCtor = Cons.getDeclaredConstructor(Object.class, List);
|
||||||
|
var EmptyCtor = Empty.getDeclaredConstructor();
|
||||||
|
|
||||||
|
var list1 = ConsCtor.newInstance(1, ConsCtor.newInstance(2, ConsCtor.newInstance(3, EmptyCtor.newInstance())));
|
||||||
|
var list2 = ConsCtor.newInstance(4, ConsCtor.newInstance(5, ConsCtor.newInstance(6, EmptyCtor.newInstance())));
|
||||||
|
|
||||||
|
var zip = clazz.getDeclaredMethod("zip", List, List);
|
||||||
|
System.out.println(zip.invoke(instance, list1, list2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Disabled("Invalid file, check this later")
|
||||||
@Test
|
@Test
|
||||||
public void testPatternMatchingZipJava() throws Exception {
|
public void testPatternMatchingZipJava() throws Exception {
|
||||||
ConsoleInterface.logLevel = Logger.LogLevel.DEBUG;
|
|
||||||
var classFiles = generateClassFiles(createClassLoader(), false, "PatternMatchingJava.jav", "PatternMatchingJava2.jav");
|
var classFiles = generateClassFiles(createClassLoader(), false, "PatternMatchingJava.jav", "PatternMatchingJava2.jav");
|
||||||
var clazz = classFiles.get("PatternMatchingJava");
|
var clazz = classFiles.get("PatternMatchingJava");
|
||||||
var instance = clazz.getDeclaredConstructor().newInstance();
|
var instance = clazz.getDeclaredConstructor().newInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Disabled("Feature nicht implementiert")
|
||||||
@Test
|
@Test
|
||||||
public void testOverloadSwitch() throws Exception {
|
public void testOverloadSwitch() throws Exception {
|
||||||
var classFiles = generateClassFiles(createClassLoader(), "SwitchOverload.jav");
|
var classFiles = generateClassFiles(createClassLoader(), "SwitchOverload.jav");
|
||||||
@@ -990,6 +1083,30 @@ public class TestComplete {
|
|||||||
assertEquals(40.0, m.invoke(instance, d, 0));
|
assertEquals(40.0, m.invoke(instance, d, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Disabled("Waiting for #407, skipping for now")
|
||||||
|
@Test
|
||||||
|
public void testPatternMatchingInterface() throws Exception {
|
||||||
|
var classFiles = generateClassFiles(createClassLoader(), false, "Matcher.jav", "PatternMatchingInterface.jav");
|
||||||
|
var Intf = classFiles.get("Interface");
|
||||||
|
var clazz = classFiles.get("PatternMatchingInterface");
|
||||||
|
var M = classFiles.get("M");
|
||||||
|
var Matcher = classFiles.get("Matcher");
|
||||||
|
|
||||||
|
var a = classFiles.get("A").getDeclaredConstructor().newInstance();
|
||||||
|
var b = classFiles.get("B").getDeclaredConstructor().newInstance();
|
||||||
|
|
||||||
|
//var match = clazz.getDeclaredMethod("match", Intf);
|
||||||
|
|
||||||
|
//assertEquals(0, match.invoke(null, a));
|
||||||
|
//assertEquals(1, match.invoke(null, b));
|
||||||
|
|
||||||
|
var matcher = M.getDeclaredConstructor().newInstance();
|
||||||
|
var match2 = clazz.getDeclaredMethod("match", Matcher, Intf);
|
||||||
|
|
||||||
|
assertEquals(0, match2.invoke(null, matcher, a));
|
||||||
|
assertEquals(1, match2.invoke(null, matcher, b));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInterfaces() throws Exception {
|
public void testInterfaces() throws Exception {
|
||||||
var classFiles = generateClassFiles(createClassLoader(), "Interfaces.jav");
|
var classFiles = generateClassFiles(createClassLoader(), "Interfaces.jav");
|
||||||
@@ -1005,6 +1122,16 @@ public class TestComplete {
|
|||||||
assertEquals(50, m.invoke(null));
|
assertEquals(50, m.invoke(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStaticFail() throws Exception {
|
||||||
|
try {
|
||||||
|
generateClassFiles(createClassLoader(), "StaticFail.jav");
|
||||||
|
fail("No exception thrown!");
|
||||||
|
} catch (CodeGenException e) {
|
||||||
|
assertEquals("Attempted to call instance method nonStaticM with descriptor ()V from a static context", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFor() throws Exception {
|
public void testFor() throws Exception {
|
||||||
var classFiles = generateClassFiles(createClassLoader(), "For.jav");
|
var classFiles = generateClassFiles(createClassLoader(), "For.jav");
|
||||||
@@ -1103,6 +1230,10 @@ public class TestComplete {
|
|||||||
assertEquals('C', clazz.getDeclaredMethod("m2").invoke(instance));
|
assertEquals('C', clazz.getDeclaredMethod("m2").invoke(instance));
|
||||||
assertEquals(10L, clazz.getDeclaredMethod("m3").invoke(instance));
|
assertEquals(10L, clazz.getDeclaredMethod("m3").invoke(instance));
|
||||||
assertEquals(10.5F, clazz.getDeclaredMethod("m4").invoke(instance));
|
assertEquals(10.5F, clazz.getDeclaredMethod("m4").invoke(instance));
|
||||||
|
assertEquals(10.5D, clazz.getDeclaredMethod("m5").invoke(instance));
|
||||||
|
assertEquals(0xFF, clazz.getDeclaredMethod("m6").invoke(instance));
|
||||||
|
assertEquals(0b101010, clazz.getDeclaredMethod("m7").invoke(instance));
|
||||||
|
assertEquals(010, clazz.getDeclaredMethod("m8").invoke(instance));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -1225,6 +1356,15 @@ public class TestComplete {
|
|||||||
m.invoke(null, List.of("foo", "bar", "baz"));
|
m.invoke(null, List.of("foo", "bar", "baz"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Disabled("See #405")
|
||||||
|
@Test
|
||||||
|
public void testLazy() throws Exception {
|
||||||
|
var classFiles = generateClassFiles(createClassLoader(), false, "LazyList.jav", "Primzahlen.jav");
|
||||||
|
var clazz = classFiles.get("Primzahlen");
|
||||||
|
var main = clazz.getDeclaredMethod("main", List.class);
|
||||||
|
main.invoke(null, List.of());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBug122() throws Exception {
|
public void testBug122() throws Exception {
|
||||||
var classFiles = generateClassFiles(createClassLoader(), "Bug122.jav");
|
var classFiles = generateClassFiles(createClassLoader(), "Bug122.jav");
|
||||||
@@ -1472,7 +1612,9 @@ public class TestComplete {
|
|||||||
var m = clazz.getDeclaredMethod("ex1");
|
var m = clazz.getDeclaredMethod("ex1");
|
||||||
assertEquals("ABC", m.invoke(instance));
|
assertEquals("ABC", m.invoke(instance));
|
||||||
var ex2 = clazz.getDeclaredMethod("ex2");
|
var ex2 = clazz.getDeclaredMethod("ex2");
|
||||||
assertEquals("BAC", ex2.invoke(instance));
|
assertEquals("CBA", ex2.invoke(instance));
|
||||||
|
var ex3 = clazz.getDeclaredMethod("ex3");
|
||||||
|
assertEquals("BA", ex3.invoke(instance));
|
||||||
}
|
}
|
||||||
@Test
|
@Test
|
||||||
public void testBug366() throws Exception {
|
public void testBug366() throws Exception {
|
||||||
@@ -1536,10 +1678,95 @@ public class TestComplete {
|
|||||||
// TODO This logs output that we should validate
|
// TODO This logs output that we should validate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBug389() throws Exception {
|
||||||
|
var classFiles = generateClassFiles(createClassLoader(), false, "Bug389.jav", "Bug389Main.jav");
|
||||||
|
var clazz = classFiles.get("Bug389Main");
|
||||||
|
clazz.getDeclaredMethod("main", List.class).invoke(null, List.of());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBug390() throws Exception {
|
public void testBug390() throws Exception {
|
||||||
var classFiles = generateClassFiles(createClassLoader(), "Bug390.jav");
|
var classFiles = generateClassFiles(createClassLoader(), "Bug390.jav");
|
||||||
var clazz = classFiles.get("Bug390");
|
var clazz = classFiles.get("Bug390");
|
||||||
clazz.getDeclaredMethod("main", List.class).invoke(null, List.of());
|
clazz.getDeclaredMethod("main", List.class).invoke(null, List.of());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBug395() throws Exception {
|
||||||
|
try {
|
||||||
|
var classFiles = generateClassFiles(createClassLoader(), "Bug395.jav");
|
||||||
|
fail("Shouldn't compile!");
|
||||||
|
} catch (WarningsException e) {
|
||||||
|
assertEquals(1, e.compilerWarnings.size());
|
||||||
|
var warning = e.compilerWarnings.get(0);
|
||||||
|
assertEquals("Duplicate Method definition dup found, signature (Ljava/lang/Integer;)Ljava/lang/Integer; clashes with signature (Ljava/lang/Integer;)Ljava/lang/Integer;", warning.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBug406() throws Exception {
|
||||||
|
var classFiles = generateClassFiles(createClassLoader(), "Bug406.jav");
|
||||||
|
var clazz = classFiles.get("Bug406");
|
||||||
|
clazz.getDeclaredMethod("main", List.class).invoke(null, List.of());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBug423() throws Exception {
|
||||||
|
try {
|
||||||
|
var classFiles = generateClassFiles(createClassLoader(), "Bug423.jav");
|
||||||
|
fail("No exception thrown!");
|
||||||
|
} catch (CodeGenException e) {
|
||||||
|
assertEquals("Class Bug423 does not implement method f from interface Bug423I", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBug422() throws Exception {
|
||||||
|
try {
|
||||||
|
var classFiles = generateClassFiles(createClassLoader(), "Bug422.jav");
|
||||||
|
fail("Shouldn't compile!");
|
||||||
|
} catch (CompilerException e) {
|
||||||
|
assertEquals("Duplicate class definition: Bug422", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBug421() throws Exception {
|
||||||
|
try {
|
||||||
|
var classFiles = generateClassFiles(createClassLoader(), "Bug421.jav");
|
||||||
|
fail("Shouldn't compile!");
|
||||||
|
} catch (ParserError e) {
|
||||||
|
assertEquals("Syntax error at line 2:26 - no viable alternative at input 'm() { return 1 }'", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBug409() throws Exception {
|
||||||
|
var classFiles = generateClassFiles(createClassLoader(), "Bug409.jav");
|
||||||
|
var clazz = classFiles.get("Bug409");
|
||||||
|
var instance = clazz.getDeclaredConstructor().newInstance();
|
||||||
|
var m = clazz.getDeclaredMethod("m");
|
||||||
|
assertEquals(5, m.invoke(instance));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBug417() throws Exception {
|
||||||
|
var classFiles = generateClassFiles(createClassLoader(), "Bug417.jav");
|
||||||
|
var clazz = classFiles.get("Bug417");
|
||||||
|
var instance = clazz.getDeclaredConstructor().newInstance();
|
||||||
|
var name = clazz.getDeclaredMethod("name", Integer.class);
|
||||||
|
assertEquals("one", name.invoke(instance, 1));
|
||||||
|
assertEquals("many", name.invoke(instance, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBug412() throws Exception {
|
||||||
|
var classFiles = generateClassFiles(createClassLoader(), "Bug412.jav");
|
||||||
|
var clazz = classFiles.get("Bug412");
|
||||||
|
var instance = clazz.getDeclaredConstructor().newInstance();
|
||||||
|
var m = clazz.getDeclaredMethod("m", Integer.class);
|
||||||
|
assertEquals(10, m.invoke(instance, 1));
|
||||||
|
assertEquals(20, m.invoke(instance, 2));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -19,14 +19,11 @@ public class TestTypeDeployment {
|
|||||||
var path = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Cycle.jav");
|
var path = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Cycle.jav");
|
||||||
var file = path.toFile();
|
var file = path.toFile();
|
||||||
var compiler = new JavaTXCompiler(file);
|
var compiler = new JavaTXCompiler(file);
|
||||||
|
compiler.generateBytecode();
|
||||||
var parsedSource = compiler.sourceFiles.get(file);
|
var parsedSource = compiler.sourceFiles.get(file);
|
||||||
var tiResults = compiler.typeInference(file);
|
var tiResults = compiler.typeInference(file);
|
||||||
Set<TypeInsert> tips = new HashSet<>();
|
Set<TypeInsert> tips = new HashSet<>();
|
||||||
|
|
||||||
for (var sf : compiler.sourceFiles.values()) {
|
|
||||||
Map<JavaClassName, byte[]> bytecode = compiler.generateBytecode(sf, tiResults);
|
|
||||||
}
|
|
||||||
|
|
||||||
System.out.println(compiler.getGeneratedGenerics());
|
System.out.println(compiler.getGeneratedGenerics());
|
||||||
|
|
||||||
for (int i = 0; i < tiResults.size(); i++) {
|
for (int i = 0; i < tiResults.size(); i++) {
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ public class ServerTest {
|
|||||||
|
|
||||||
// get information from the compiler
|
// get information from the compiler
|
||||||
JavaTXCompiler compiler = new JavaTXCompiler(List.of(file));
|
JavaTXCompiler compiler = new JavaTXCompiler(List.of(file));
|
||||||
|
compiler.parseAll();
|
||||||
|
|
||||||
// NOW: simulate the call to method typeInference. Once via server and once locally
|
// NOW: simulate the call to method typeInference. Once via server and once locally
|
||||||
// if everything works, they should neither interfere with each other nor differ in their result
|
// if everything works, they should neither interfere with each other nor differ in their result
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ public class InheritTest {
|
|||||||
public static void setUpBeforeClass() throws Exception {
|
public static void setUpBeforeClass() throws Exception {
|
||||||
var classLoader = TestCodegen.createClassLoader();
|
var classLoader = TestCodegen.createClassLoader();
|
||||||
|
|
||||||
var classes = TestCodegen.generateClassFiles(classLoader, "Inherit.jav", "AA.jav", "BB.jav", "CC.jav", "DD.jav");
|
var classes = TestCodegen.generateClassFiles(classLoader, false, "AA.jav", "BB.jav", "CC.jav", "DD.jav", "Inherit.jav");
|
||||||
classToTest = classes.get("Inherit");
|
classToTest = classes.get("Inherit");
|
||||||
classToTestAA = classes.get("AA");
|
classToTestAA = classes.get("AA");
|
||||||
classToTestBB = classes.get("BB");
|
classToTestBB = classes.get("BB");
|
||||||
@@ -52,7 +52,7 @@ public class InheritTest {
|
|||||||
public void testmainCC() throws Exception {
|
public void testmainCC() throws Exception {
|
||||||
Method m = classToTestCC.getDeclaredMethod("m", Integer.class);
|
Method m = classToTestCC.getDeclaredMethod("m", Integer.class);
|
||||||
assertEquals("CC", m.invoke(instanceOfClassCC, 5));
|
assertEquals("CC", m.invoke(instanceOfClassCC, 5));
|
||||||
Method main = classToTest.getDeclaredMethod("main", classToTestCC, Integer.class);
|
Method main = classToTest.getDeclaredMethod("main", classToTestAA, Integer.class);
|
||||||
assertEquals("CC", main.invoke(instanceOfClass, instanceOfClassCC, 5));
|
assertEquals("CC", main.invoke(instanceOfClass, instanceOfClassCC, 5));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ public class InheritTest {
|
|||||||
public void testmainDD() throws Exception {
|
public void testmainDD() throws Exception {
|
||||||
Method m = classToTestCC.getDeclaredMethod("m", Integer.class);
|
Method m = classToTestCC.getDeclaredMethod("m", Integer.class);
|
||||||
assertEquals("CC", m.invoke(instanceOfClassDD, 5));
|
assertEquals("CC", m.invoke(instanceOfClassDD, 5));
|
||||||
Method main = classToTest.getDeclaredMethod("main", classToTestCC, Integer.class);
|
Method main = classToTest.getDeclaredMethod("main", classToTestAA, Integer.class);
|
||||||
assertEquals("CC", main.invoke(instanceOfClass, instanceOfClassDD, 5));
|
assertEquals("CC", main.invoke(instanceOfClass, instanceOfClassDD, 5));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ public class PutTest {
|
|||||||
Method m = classToTest.getDeclaredMethod("putElement", Object.class, Stack.class);
|
Method m = classToTest.getDeclaredMethod("putElement", Object.class, Stack.class);
|
||||||
Stack<Integer> s_invoke = new Stack<>();
|
Stack<Integer> s_invoke = new Stack<>();
|
||||||
m.invoke(instanceOfClass, 5, s_invoke);
|
m.invoke(instanceOfClass, 5, s_invoke);
|
||||||
assertEquals(new Integer(5), s_invoke.pop());
|
assertEquals(5, s_invoke.pop());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -53,6 +53,6 @@ public class PutTest {
|
|||||||
Method m = classToTest.getDeclaredMethod("main", Object.class, Stack.class);
|
Method m = classToTest.getDeclaredMethod("main", Object.class, Stack.class);
|
||||||
Stack<Integer> s_invoke = new Stack<>();
|
Stack<Integer> s_invoke = new Stack<>();
|
||||||
m.invoke(instanceOfClass, 6, s_invoke);
|
m.invoke(instanceOfClass, 6, s_invoke);
|
||||||
assertEquals(new Integer(6), s_invoke.pop());
|
assertEquals(6, s_invoke.pop());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,7 @@ import de.dhbwstuttgart.bytecode.Codegen;
|
|||||||
import de.dhbwstuttgart.environment.DirectoryClassLoader;
|
import de.dhbwstuttgart.environment.DirectoryClassLoader;
|
||||||
import de.dhbwstuttgart.environment.IByteArrayClassLoader;
|
import de.dhbwstuttgart.environment.IByteArrayClassLoader;
|
||||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter;
|
||||||
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
|
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
|
||||||
import de.dhbwstuttgart.target.tree.MethodParameter;
|
import de.dhbwstuttgart.target.tree.MethodParameter;
|
||||||
import de.dhbwstuttgart.target.tree.TargetClass;
|
import de.dhbwstuttgart.target.tree.TargetClass;
|
||||||
@@ -14,6 +15,7 @@ import de.dhbwstuttgart.target.tree.expression.*;
|
|||||||
import de.dhbwstuttgart.target.tree.type.TargetFunNType;
|
import de.dhbwstuttgart.target.tree.type.TargetFunNType;
|
||||||
import de.dhbwstuttgart.target.tree.type.TargetRefType;
|
import de.dhbwstuttgart.target.tree.type.TargetRefType;
|
||||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
import de.dhbwstuttgart.typeinference.result.ResultSet;
|
||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
@@ -30,7 +32,7 @@ import java.util.function.Function;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class TestCodegen {
|
public class TestCodegen {
|
||||||
static final Path outputPath = Path.of(System.getProperty("user.dir"), "/targetTest");
|
public static final Path outputPath = Path.of(System.getProperty("user.dir"), "/targetTest");
|
||||||
|
|
||||||
private static void writeClassFile(String name, byte[] code) throws IOException {
|
private static void writeClassFile(String name, byte[] code) throws IOException {
|
||||||
Files.createDirectories(outputPath);
|
Files.createDirectories(outputPath);
|
||||||
@@ -56,7 +58,8 @@ public class TestCodegen {
|
|||||||
try(var newClassLoader = new DirectoryClassLoader(List.of(outputPath.toFile()), (ClassLoader)classLoader)) {
|
try(var newClassLoader = new DirectoryClassLoader(List.of(outputPath.toFile()), (ClassLoader)classLoader)) {
|
||||||
var result = new HashMap<String, Class<?>>();
|
var result = new HashMap<String, Class<?>>();
|
||||||
for (var file : filenames) {
|
for (var file : filenames) {
|
||||||
var classes = compiler.sourceFiles.get(file).getClasses();
|
var sf = compiler.sourceFiles.get(file);
|
||||||
|
var classes = sf.getClasses();
|
||||||
|
|
||||||
result.putAll(classes.stream().map(cli -> {
|
result.putAll(classes.stream().map(cli -> {
|
||||||
try {
|
try {
|
||||||
@@ -71,7 +74,8 @@ public class TestCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Class<?> generateClass(TargetStructure clazz, IByteArrayClassLoader classLoader) throws IOException, ClassNotFoundException {
|
public static Class<?> generateClass(TargetStructure clazz, IByteArrayClassLoader classLoader) throws IOException, ClassNotFoundException {
|
||||||
Codegen codegen = new Codegen(clazz, new JavaTXCompiler(List.of()), null);
|
ASTToTargetAST converter = new ASTToTargetAST(List.of(new ResultSet(Set.of())), classLoader);
|
||||||
|
Codegen codegen = new Codegen(clazz, new JavaTXCompiler(List.of()), converter);
|
||||||
var code = codegen.generate();
|
var code = codegen.generate();
|
||||||
writeClassFile(clazz.qualifiedName().getClassName(), code);
|
writeClassFile(clazz.qualifiedName().getClassName(), code);
|
||||||
return classLoader.loadClass(code);
|
return classLoader.loadClass(code);
|
||||||
@@ -198,9 +202,20 @@ public class TestCodegen {
|
|||||||
@Test
|
@Test
|
||||||
public void testFor() throws Exception {
|
public void testFor() throws Exception {
|
||||||
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, new JavaClassName("For"));
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, new JavaClassName("For"));
|
||||||
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "forLoop", List.of(), TargetType.Integer, new TargetBlock(List.of(new TargetVarDecl(TargetType.Integer, "sum", new TargetLiteral.IntLiteral(0)), new TargetFor(List.of(new TargetVarDecl(TargetType.Integer, "i", new TargetLiteral.IntLiteral(0))), new TargetBinaryOp.Less(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetLiteral.IntLiteral(10)), List.of(new TargetAssign(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetBinaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetLiteral.IntLiteral(1)))), new TargetBlock(List.of(new TargetAssign(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "sum"), new TargetBinaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "sum"), new TargetLocalVar(TargetType.Integer, "i")))))), new TargetReturn(new TargetLocalVar(TargetType.Integer, "sum")))));
|
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "forLoop", List.of(), TargetType.Integer,
|
||||||
|
new TargetBlock(List.of(new TargetVarDecl(TargetType.Integer, "sum", new TargetLiteral.IntLiteral(0)),
|
||||||
|
new TargetFor(List.of(new TargetVarDecl(TargetType.Integer, "i", new TargetLiteral.IntLiteral(0))),
|
||||||
|
new TargetBinaryOp.Less(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"),
|
||||||
|
new TargetLiteral.IntLiteral(10)), List.of(new TargetAssign(TargetType.Integer,
|
||||||
|
new TargetLocalVar(TargetType.Integer, "i"),
|
||||||
|
new TargetBinaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetLiteral.IntLiteral(1)))),
|
||||||
|
new TargetBlock(List.of(
|
||||||
|
new TargetAssign(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "sum"),
|
||||||
|
new TargetBinaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "sum"),
|
||||||
|
new TargetLocalVar(TargetType.Integer, "i")))))),
|
||||||
|
new TargetReturn(new TargetLocalVar(TargetType.Integer, "sum")))));
|
||||||
var clazz = generateClass(targetClass, createClassLoader());
|
var clazz = generateClass(targetClass, createClassLoader());
|
||||||
assertEquals(clazz.getDeclaredMethod("forLoop").invoke(null), 45);
|
assertEquals(45, clazz.getDeclaredMethod("forLoop").invoke(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ public class TestGenerics {
|
|||||||
private static Result computeGenerics(String filename) throws IOException, ClassNotFoundException {
|
private static Result computeGenerics(String filename) throws IOException, ClassNotFoundException {
|
||||||
var file = Path.of(rootDirectory + filename).toFile();
|
var file = Path.of(rootDirectory + filename).toFile();
|
||||||
var compiler = new JavaTXCompiler(List.of(file), List.of(file.getParentFile()), new File(bytecodeDirectory), true);
|
var compiler = new JavaTXCompiler(List.of(file), List.of(file.getParentFile()), new File(bytecodeDirectory), true);
|
||||||
|
compiler.parseAll();
|
||||||
var inference = compiler.typeInference(file);
|
var inference = compiler.typeInference(file);
|
||||||
compiler.generateBytecode(new File(bytecodeDirectory), inference);
|
compiler.generateBytecode(new File(bytecodeDirectory), inference);
|
||||||
var sf = compiler.sourceFiles.get(file);
|
var sf = compiler.sourceFiles.get(file);
|
||||||
|
|||||||
Reference in new issue
Block a user