forked from JavaTX/JavaCompilerCore
Compare commits
97 Commits
targetByte
...
targetByte
Author | SHA1 | Date | |
---|---|---|---|
9801f8a5ae | |||
f0b9bea23e | |||
ce4347dd96 | |||
7785c2d0aa | |||
a654f55deb | |||
|
7037bdf9ef | ||
|
d9860497df | ||
|
fdffc11580 | ||
|
c10de35ca2 | ||
|
56b73332c0 | ||
|
bdcd5ea3cf | ||
edafbbc5a0 | |||
ba8810e5df | |||
63493ed0f7 | |||
|
4dba867f9e | ||
|
06caf0ff66 | ||
ec92b5d5e1 | |||
091a6b8f1f | |||
60a1f3b220 | |||
7e6aeaf728 | |||
|
ea217d16d5 | ||
|
7650813bb7 | ||
|
5d03995f10 | ||
|
1bc58573c7 | ||
4880527d4d | |||
50f2a29e1e | |||
99f219de3b | |||
12bb613eb0 | |||
141e1cbc94 | |||
|
5b4ea5a0c5 | ||
b824680508 | |||
295bf079b9 | |||
974582f7e5 | |||
2ded0c9044 | |||
|
c3343959c5 | ||
|
39f04b1a1b | ||
|
3d2b935c60 | ||
|
db01b0c8dd | ||
662756ac18 | |||
b0bf41968e | |||
|
2221b559ca | ||
|
021b7ec9fe | ||
|
154d4823e4 | ||
|
71dfe5d9e1 | ||
|
58110c474a | ||
df2ec4b1ba | |||
2c66a1d6e6 | |||
c76ee355d8 | |||
a5c314c5c5 | |||
cba35a4bec | |||
b774281cbb | |||
9358130468 | |||
708aa64283 | |||
c21e5202d6 | |||
b3bd5cde10 | |||
df78937ef3 | |||
7fb4824f8d | |||
e0d71a6003 | |||
49803385cf | |||
39d02f792c | |||
4fc78f494c | |||
b752219d8c | |||
ec890356e4 | |||
d405b0c3a2 | |||
6c8657b7a8 | |||
|
bcce4cee19 | ||
e6cd4038e2 | |||
e50f941b79 | |||
cb7d0e22cc | |||
|
0d5be89310 | ||
0b7f07108f | |||
6b0816c1c4 | |||
f66b9099f3 | |||
da74898f9d | |||
46a7f61234 | |||
e59accf7ee | |||
|
4b110244f2 | ||
|
e37040f367 | ||
6850a8fa21 | |||
877e5ed38a | |||
82b4450857 | |||
b70e435120 | |||
3b14cd609f | |||
8fdfbf875b | |||
bc61fc2e1d | |||
62f2e05f35 | |||
606ce8b82d | |||
c84befae51 | |||
7f3c1686ec | |||
43da2ffbdc | |||
9472b5c86f | |||
7cb0e9dbb7 | |||
e07521d9b6 | |||
c2ee12397f | |||
e6321ff8bc | |||
786e0a7a23 | |||
1c63321b30 |
14
pom.xml
14
pom.xml
@ -29,14 +29,14 @@ http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<version>2.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>22.0</version>
|
||||
<groupId>io.github.classgraph</groupId>
|
||||
<artifactId>classgraph</artifactId>
|
||||
<version>4.8.172</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.reflections</groupId>
|
||||
<artifactId>reflections</artifactId>
|
||||
<version>0.9.11</version>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>33.2.0-jre</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.ow2.asm/asm -->
|
||||
<dependency>
|
||||
@ -66,7 +66,7 @@ http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<redirectTestOutputToFile>true</redirectTestOutputToFile>
|
||||
<reportsDirectory>${project.build.directory}/test-reports</reportsDirectory>
|
||||
<argLine>--enable-preview</argLine>
|
||||
<trimStackTrace>true</trimStackTrace>
|
||||
<trimStackTrace>false</trimStackTrace>
|
||||
<excludes>
|
||||
<exclude>**/JavaTXCompilerTest.java</exclude>
|
||||
<exclude>**/AllgemeinTest.java</exclude>
|
||||
|
10
resources/AllgemeinTest/Bar.java
Normal file
10
resources/AllgemeinTest/Bar.java
Normal file
@ -0,0 +1,10 @@
|
||||
public class Bar{
|
||||
|
||||
void visit(Object o){
|
||||
System.out.println("Object");
|
||||
}
|
||||
|
||||
void visit(Bla f){
|
||||
System.out.println("Foo");
|
||||
}
|
||||
}
|
9
resources/AllgemeinTest/Box.jav
Normal file
9
resources/AllgemeinTest/Box.jav
Normal file
@ -0,0 +1,9 @@
|
||||
public class Box<A> {
|
||||
|
||||
A a;
|
||||
|
||||
public Box() { }
|
||||
public Box(A a) {
|
||||
//this.a = a;
|
||||
}
|
||||
}
|
6
resources/AllgemeinTest/Foo.jav
Normal file
6
resources/AllgemeinTest/Foo.jav
Normal file
@ -0,0 +1,6 @@
|
||||
public class Foo{
|
||||
|
||||
public accept(Bar b){
|
||||
b.visit(this);
|
||||
}
|
||||
}
|
46
resources/AllgemeinTest/List.jav
Normal file
46
resources/AllgemeinTest/List.jav
Normal file
@ -0,0 +1,46 @@
|
||||
import java.lang.Boolean;
|
||||
import java.lang.Object;
|
||||
|
||||
class List {
|
||||
elem;
|
||||
next;
|
||||
|
||||
List() {
|
||||
super();
|
||||
}
|
||||
|
||||
List(elem, next) {
|
||||
this.elem = elem;
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
addElement(newElem) {
|
||||
return new List(newElem, this);
|
||||
}
|
||||
|
||||
append(l) {
|
||||
if (next == null) {
|
||||
return l;
|
||||
}
|
||||
else {
|
||||
return new List(elem, next.append(l));
|
||||
}
|
||||
}
|
||||
/*
|
||||
addAll(l) {
|
||||
var nextLoc = next;
|
||||
while (//nextLoc != null
|
||||
true) {
|
||||
nextLoc = nextLoc.next;
|
||||
}
|
||||
nextLoc = l;
|
||||
}
|
||||
|
||||
void m() {
|
||||
List<? extends Object> l; // = new List<Integer>(1, null);
|
||||
List<? extends Object> l2; // = new List<String>("SSS", null);
|
||||
l.addAll(l2);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
class B { }
|
||||
class Box_Main extends B {
|
||||
m(b) {
|
||||
b.m(new Box_Main());
|
||||
b.m(new B());
|
||||
public class Box<A> {
|
||||
|
||||
A a;
|
||||
|
||||
public Box() { }
|
||||
public Box(A a) {
|
||||
//this.a = a;
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
class Box<A> {
|
||||
void m(A a) { }
|
||||
}
|
@ -2,18 +2,16 @@ import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.lang.Integer;
|
||||
import java.lang.System;
|
||||
import java.lang.Boolean;
|
||||
import java.io.PrintStream;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class Bug298 {
|
||||
public <R, T> Stream<R> takes(Stream<T> s, Function<? super T, ? super R> fun) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void m() {
|
||||
List<Integer> list = new ArrayList<>();
|
||||
Stream<Integer> a = list.stream();
|
||||
takes(a, x -> 2 * x);
|
||||
list.stream().map(x -> 2 * x);
|
||||
|
||||
Function<Integer, Boolean> filter = x -> true;
|
||||
}
|
||||
}
|
||||
|
17
resources/bytecode/javFiles/Bug300.jav
Normal file
17
resources/bytecode/javFiles/Bug300.jav
Normal file
@ -0,0 +1,17 @@
|
||||
import java.lang.String;
|
||||
|
||||
class Base {
|
||||
toString() {
|
||||
return "Base";
|
||||
}
|
||||
}
|
||||
|
||||
public class Bug300 extends Base {
|
||||
public m() {
|
||||
return super.toString();
|
||||
}
|
||||
|
||||
toString() {
|
||||
return "Derived";
|
||||
}
|
||||
}
|
4
resources/bytecode/javFiles/Bug301.jav
Normal file
4
resources/bytecode/javFiles/Bug301.jav
Normal file
@ -0,0 +1,4 @@
|
||||
import java.util.HashSet;
|
||||
|
||||
public class Bug301<A> extends HashSet<A> {
|
||||
}
|
11
resources/bytecode/javFiles/Bug302.jav
Normal file
11
resources/bytecode/javFiles/Bug302.jav
Normal file
@ -0,0 +1,11 @@
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.lang.Integer;
|
||||
|
||||
public class Bug302 {
|
||||
public Bug302(List<Integer> a){}
|
||||
|
||||
public static m() {
|
||||
new Bug302(new ArrayList<Integer>());
|
||||
}
|
||||
}
|
13
resources/bytecode/javFiles/Bug306.jav
Normal file
13
resources/bytecode/javFiles/Bug306.jav
Normal file
@ -0,0 +1,13 @@
|
||||
import java.lang.Integer;
|
||||
import java.util.List;
|
||||
|
||||
class Base {
|
||||
m(List<Integer> a) {}
|
||||
}
|
||||
|
||||
public class Bug306 extends Base {
|
||||
@Override
|
||||
m(List<Integer> b) {
|
||||
b.add(1);
|
||||
}
|
||||
}
|
46
resources/bytecode/javFiles/Bug307.jav
Normal file
46
resources/bytecode/javFiles/Bug307.jav
Normal file
@ -0,0 +1,46 @@
|
||||
public class Bug307 {
|
||||
public void main() {
|
||||
IVisitor v = new Visitor();
|
||||
Impl2 f = new Impl2();
|
||||
Impl1 g = new Impl1();
|
||||
|
||||
f.accept(v);
|
||||
g.accept(v);
|
||||
}
|
||||
}
|
||||
|
||||
interface IVisitor {
|
||||
void visit(Impl1 f);
|
||||
void visit(Impl2 fb);
|
||||
}
|
||||
|
||||
interface IAcceptor {
|
||||
void accept(IVisitor v);
|
||||
}
|
||||
|
||||
class Visitor implements IVisitor {
|
||||
|
||||
@Override
|
||||
public void visit(Impl1 f) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Impl2 fb) {
|
||||
}
|
||||
}
|
||||
|
||||
class Impl1 implements IAcceptor {
|
||||
|
||||
@Override
|
||||
public void accept(IVisitor v) {
|
||||
v.visit(this);
|
||||
}
|
||||
}
|
||||
|
||||
class Impl2 implements IAcceptor {
|
||||
|
||||
@Override
|
||||
public void accept(IVisitor v) {
|
||||
v.visit(this);
|
||||
}
|
||||
}
|
16
resources/bytecode/javFiles/Bug309.jav
Normal file
16
resources/bytecode/javFiles/Bug309.jav
Normal file
@ -0,0 +1,16 @@
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.lang.Integer;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.Optional;
|
||||
|
||||
public class Bug309 {
|
||||
public main() {
|
||||
List<Integer> list = new ArrayList<>(List.of(1,2,3,4,5,6,7,8,9));
|
||||
var res = list.stream().filter(x -> x == 5).map(x -> x * 2).findFirst();
|
||||
return res;
|
||||
}
|
||||
}
|
9
resources/bytecode/javFiles/Bug310.jav
Normal file
9
resources/bytecode/javFiles/Bug310.jav
Normal file
@ -0,0 +1,9 @@
|
||||
import java.lang.Integer;
|
||||
import java.lang.String;
|
||||
|
||||
public class Bug310 {
|
||||
Integer i = 3;
|
||||
public toString() {
|
||||
return i.toString();
|
||||
}
|
||||
}
|
10
resources/bytecode/javFiles/Bug311.jav
Normal file
10
resources/bytecode/javFiles/Bug311.jav
Normal file
@ -0,0 +1,10 @@
|
||||
import java.lang.String;
|
||||
|
||||
public class Bug311 {
|
||||
Bug311A i = new Bug311A();
|
||||
public toString() {
|
||||
return i.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class Bug311A {}
|
8
resources/bytecode/javFiles/Bug312.jav
Normal file
8
resources/bytecode/javFiles/Bug312.jav
Normal file
@ -0,0 +1,8 @@
|
||||
public class Bug312 {
|
||||
Bug312A i = new Bug312A();
|
||||
public main() {
|
||||
if (i == null) {}
|
||||
}
|
||||
}
|
||||
|
||||
class Bug312A {}
|
13
resources/bytecode/javFiles/Bug314.jav
Normal file
13
resources/bytecode/javFiles/Bug314.jav
Normal file
@ -0,0 +1,13 @@
|
||||
import java.lang.Integer;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Bug314 {
|
||||
public List<Integer> convert(List<Integer> in) {
|
||||
return in.stream().filter(x -> x > 5).collect(Collectors.toList());
|
||||
}
|
||||
}
|
13
resources/bytecode/javFiles/Bug325.jav
Normal file
13
resources/bytecode/javFiles/Bug325.jav
Normal file
@ -0,0 +1,13 @@
|
||||
import java.lang.Integer;
|
||||
import java.util.function.Function;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class Bug325 {
|
||||
public main() {
|
||||
List<Integer> list = new ArrayList<>(List.of(1,2,3,4,5));
|
||||
var func = x -> x*2;
|
||||
return list.stream().map(func).toList();
|
||||
}
|
||||
}
|
8
resources/bytecode/javFiles/Bug326.jav
Normal file
8
resources/bytecode/javFiles/Bug326.jav
Normal file
@ -0,0 +1,8 @@
|
||||
import java.lang.Integer;
|
||||
|
||||
public class Bug326 {
|
||||
public Bug326() {
|
||||
var func = x -> y -> x * y;
|
||||
return func.apply(3).apply(4);
|
||||
}
|
||||
}
|
8
resources/bytecode/javFiles/Bug328.jav
Normal file
8
resources/bytecode/javFiles/Bug328.jav
Normal file
@ -0,0 +1,8 @@
|
||||
import java.lang.Integer;
|
||||
import Bug328B;
|
||||
|
||||
public class Bug328 extends Bug328B {
|
||||
public Bug328() {
|
||||
super(1);
|
||||
}
|
||||
}
|
BIN
resources/bytecode/javFiles/Bug328B.class
Normal file
BIN
resources/bytecode/javFiles/Bug328B.class
Normal file
Binary file not shown.
3
resources/bytecode/javFiles/Bug328B.java
Normal file
3
resources/bytecode/javFiles/Bug328B.java
Normal file
@ -0,0 +1,3 @@
|
||||
public class Bug328B {
|
||||
public Bug328B(int a) {}
|
||||
}
|
15
resources/bytecode/javFiles/Bug332.jav
Normal file
15
resources/bytecode/javFiles/Bug332.jav
Normal file
@ -0,0 +1,15 @@
|
||||
import java.lang.Object;
|
||||
|
||||
interface Visitor {
|
||||
public void visit(Object obj);
|
||||
public void visit(ClassA a);
|
||||
}
|
||||
|
||||
class ClassA {
|
||||
void accept(Visitor v) {
|
||||
v.visit(this);
|
||||
}
|
||||
}
|
||||
|
||||
public class Bug332 {
|
||||
}
|
11
resources/bytecode/javFiles/Bug333.jav
Normal file
11
resources/bytecode/javFiles/Bug333.jav
Normal file
@ -0,0 +1,11 @@
|
||||
import java.lang.String;
|
||||
|
||||
public class Bug333 {
|
||||
public static String Bar = "Bar";
|
||||
}
|
||||
|
||||
class Bar {
|
||||
public bar() {
|
||||
String s = Bug333.Bar;
|
||||
}
|
||||
}
|
10
resources/bytecode/javFiles/Bug337.jav
Normal file
10
resources/bytecode/javFiles/Bug337.jav
Normal file
@ -0,0 +1,10 @@
|
||||
import java.lang.Integer;
|
||||
import java.lang.Number;
|
||||
import java.lang.Object;
|
||||
|
||||
public class Bug337 {
|
||||
public void main() {
|
||||
Fun1$$<Object, Integer> fun1 = x -> x.hashCode() + 1;
|
||||
Fun1$$<Number, Number> fun2 = fun1;
|
||||
}
|
||||
}
|
11
resources/bytecode/javFiles/Bug338.jav
Normal file
11
resources/bytecode/javFiles/Bug338.jav
Normal file
@ -0,0 +1,11 @@
|
||||
import java.util.List;
|
||||
import java.lang.Integer;
|
||||
import java.lang.String;
|
||||
import java.lang.Object;
|
||||
import java.util.List;
|
||||
|
||||
public class Bug338 {
|
||||
public hashCode() {
|
||||
return List.of(42);
|
||||
}
|
||||
}
|
2
resources/bytecode/javFiles/Bug343.jav
Normal file
2
resources/bytecode/javFiles/Bug343.jav
Normal file
@ -0,0 +1,2 @@
|
||||
public record Bug343() {
|
||||
}
|
16
resources/bytecode/javFiles/BugXXX.jav
Normal file
16
resources/bytecode/javFiles/BugXXX.jav
Normal file
@ -0,0 +1,16 @@
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.lang.String;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.lang.Integer;
|
||||
|
||||
class BugXXX {
|
||||
public main() {
|
||||
List<Integer> i = new ArrayList<>(List.of(1,2,3,4,5,6,7,8,9,10));
|
||||
Optional<Integer> tmp = i.stream().filter(x -> x == 5).map(x -> x*2).findFirst();
|
||||
return tmp;
|
||||
}
|
||||
}
|
5
resources/bytecode/javFiles/ImportWildcard.jav
Normal file
5
resources/bytecode/javFiles/ImportWildcard.jav
Normal file
@ -0,0 +1,5 @@
|
||||
import java.lang.*;
|
||||
|
||||
public class ImportWildcard {
|
||||
m(a, b) { return a * b; }
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
import java.lang.Runnable;
|
||||
import java.lang.System;
|
||||
import java.lang.String;
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class LamRunnable {
|
||||
|
||||
public LamRunnable() {
|
||||
Runnable lam = () -> {
|
||||
System.out.println("lambda");
|
||||
};
|
||||
|
||||
lam.run();
|
||||
}
|
||||
}
|
||||
|
@ -3,4 +3,6 @@ import java.lang.Character;
|
||||
public class Literal {
|
||||
public m() { return null; }
|
||||
public m2() { return 'C'; }
|
||||
public m3() { return 10L; }
|
||||
public m4() { return 10.5F; }
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
import java.util.List;
|
||||
import java.util.AbstractList;
|
||||
import java.util.Vector;
|
||||
import java.lang.Integer;
|
||||
//import java.lang.Float;
|
||||
@ -30,8 +32,8 @@ public class Matrix extends Vector<Vector<Integer>> {
|
||||
var erg = 0;
|
||||
var k = 0;
|
||||
while(k < v1.size()) {
|
||||
erg = erg + v1.elementAt(k)
|
||||
* m.elementAt(k).elementAt(j);
|
||||
erg = erg + v1.get(k)
|
||||
* m.get(k).get(j);
|
||||
k++; }
|
||||
// v2.addElement(new Integer(erg));
|
||||
v2.addElement(erg);
|
||||
|
@ -1,11 +1,34 @@
|
||||
public class Op1{
|
||||
public Op1() {
|
||||
import java.lang.Boolean;
|
||||
import java.lang.Integer;
|
||||
|
||||
Runnable lam = () -> {
|
||||
String test = "";
|
||||
String b = "b";
|
||||
test = b;
|
||||
System.out.println(test);};
|
||||
//lam.run();
|
||||
public class Op1 {
|
||||
public not() {
|
||||
var b = false;
|
||||
var c = !b;
|
||||
return c;
|
||||
}
|
||||
|
||||
public or() {
|
||||
var a = 10;
|
||||
var b = 20;
|
||||
return a | b;
|
||||
}
|
||||
|
||||
public and() {
|
||||
var a = 10;
|
||||
var b = 20;
|
||||
return a & b;
|
||||
}
|
||||
|
||||
public xor() {
|
||||
var a = 10;
|
||||
var b = 20;
|
||||
return a ^ b;
|
||||
}
|
||||
|
||||
public mod() {
|
||||
var a = 10;
|
||||
var b = 2;
|
||||
return a % b;
|
||||
}
|
||||
}
|
12
resources/bytecode/javFiles/OverrideEquals.jav
Normal file
12
resources/bytecode/javFiles/OverrideEquals.jav
Normal file
@ -0,0 +1,12 @@
|
||||
import java.lang.Object;
|
||||
import java.lang.Boolean;
|
||||
|
||||
public class OverrideEquals extends OverrideRoot {
|
||||
public boolean equals(Object o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public int method(int var1, float var2) {
|
||||
return 0;
|
||||
}
|
||||
}
|
BIN
resources/bytecode/javFiles/OverrideRoot.class
Normal file
BIN
resources/bytecode/javFiles/OverrideRoot.class
Normal file
Binary file not shown.
3
resources/bytecode/javFiles/OverrideRoot.java
Normal file
3
resources/bytecode/javFiles/OverrideRoot.java
Normal file
@ -0,0 +1,3 @@
|
||||
public abstract class OverrideRoot {
|
||||
public abstract int method(int a, float b);
|
||||
}
|
@ -11,9 +11,9 @@ record Rec(Integer a, Integer b) {}
|
||||
}*/
|
||||
|
||||
public class RecordTest {
|
||||
a = new Rec(10, 20);
|
||||
b = new Rec(10, 20);
|
||||
c = new Rec(20, 40);
|
||||
Rec a = new Rec(10, 20);
|
||||
Rec b = new Rec(10, 20);
|
||||
Rec c = new Rec(20, 40);
|
||||
|
||||
public doesEqual() { return a.equals(b); }
|
||||
public doesNotEqual() { return b.equals(c); }
|
||||
|
9
resources/bytecode/javFiles/Ternary.jav
Normal file
9
resources/bytecode/javFiles/Ternary.jav
Normal file
@ -0,0 +1,9 @@
|
||||
import java.lang.Boolean;
|
||||
import java.lang.String;
|
||||
import java.lang.Integer;
|
||||
|
||||
public class Ternary {
|
||||
public main(x) {
|
||||
return x > 10 ? "big" : "small";
|
||||
}
|
||||
}
|
@ -9,4 +9,13 @@ public class While {
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
public m2() {
|
||||
int i = 0;
|
||||
do {
|
||||
++i;
|
||||
} while(i < 10);
|
||||
|
||||
return i;
|
||||
}
|
||||
}
|
@ -2,41 +2,21 @@ import java.lang.Integer;
|
||||
|
||||
public class Y {
|
||||
y;
|
||||
//factorial;
|
||||
|
||||
public Y() {
|
||||
y = f -> t -> f.apply(y.apply(f)).apply(t);
|
||||
//factorial = y.apply(f -> n -> { if (n == 0) return 1; else return n * f.apply(n - 1); });
|
||||
}
|
||||
/*
|
||||
getY() {
|
||||
return y;
|
||||
}
|
||||
*/
|
||||
}
|
||||
/*
|
||||
class fac1 {
|
||||
factorial;
|
||||
|
||||
fac1() {
|
||||
public class Fac1 {
|
||||
public factorial;
|
||||
public Fac1() {
|
||||
var y;
|
||||
y = new Y<Integer,Integer,Integer,Integer,Integer>().getY();
|
||||
var tmp = new Y<>(); // TODO Having new Y<>().y on one line doesn't work, see FIXME in StatementGenerator
|
||||
y = tmp.y;
|
||||
factorial = y.apply(f -> n -> { if (n == 0) return 1; else return n * f.apply(n - 1); });
|
||||
}
|
||||
}
|
||||
|
||||
ergibt Parse-Error
|
||||
class fac1 {
|
||||
factorial;
|
||||
|
||||
fac1() {
|
||||
var y;
|
||||
y = new Y<>().y;
|
||||
factorial = y.apply(f -> n -> { if (n == 0) return 1; else return n * f.apply(n - 1); });
|
||||
public fac(v) {
|
||||
return factorial.apply(v);
|
||||
}
|
||||
public static void main(String args[]) {
|
||||
System.out.println(new fac1().factorial.apply(3));
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
3
resources/packageTest/pkg/sub/Interface.jav
Normal file
3
resources/packageTest/pkg/sub/Interface.jav
Normal file
@ -0,0 +1,3 @@
|
||||
package pkg.sub;
|
||||
|
||||
public interface Interface {}
|
@ -5,7 +5,11 @@ import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||
import de.dhbwstuttgart.parser.NullToken;
|
||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
|
||||
import de.dhbwstuttgart.syntaxtree.Method;
|
||||
import de.dhbwstuttgart.syntaxtree.Pattern;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
|
||||
import de.dhbwstuttgart.target.generate.StatementToTargetExpression;
|
||||
import de.dhbwstuttgart.target.tree.*;
|
||||
import de.dhbwstuttgart.target.tree.expression.*;
|
||||
import de.dhbwstuttgart.target.tree.type.*;
|
||||
@ -14,6 +18,7 @@ import org.objectweb.asm.*;
|
||||
import java.lang.invoke.*;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.*;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static org.objectweb.asm.Opcodes.*;
|
||||
import static de.dhbwstuttgart.target.tree.expression.TargetBinaryOp.*;
|
||||
@ -26,17 +31,25 @@ public class Codegen {
|
||||
private int lambdaCounter = 0;
|
||||
private final HashMap<TargetLambdaExpression, TargetMethod> lambdas = new HashMap<>();
|
||||
private final JavaTXCompiler compiler;
|
||||
private final ASTToTargetAST converter;
|
||||
|
||||
private class CustomClassWriter extends ClassWriter {
|
||||
public CustomClassWriter() {
|
||||
super(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
|
||||
}
|
||||
|
||||
public Codegen(TargetStructure clazz, JavaTXCompiler compiler) {
|
||||
this.clazz = clazz;
|
||||
this.className = clazz.qualifiedName().getClassName();
|
||||
this.cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS) {
|
||||
@Override
|
||||
protected ClassLoader getClassLoader() {
|
||||
return compiler.getClassLoader();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public Codegen(TargetStructure clazz, JavaTXCompiler compiler, ASTToTargetAST converter) {
|
||||
this.clazz = clazz;
|
||||
this.className = clazz.qualifiedName().getClassName();
|
||||
this.cw = new CustomClassWriter();
|
||||
this.compiler = compiler;
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
private record LocalVar(int index, String name, TargetType type) {
|
||||
@ -77,8 +90,6 @@ public class Codegen {
|
||||
int localCounter;
|
||||
MethodVisitor mv;
|
||||
TargetType returnType;
|
||||
// This is used to remember the type from lambda expressions
|
||||
TargetType contextType;
|
||||
|
||||
Stack<BreakEnv> breakStack = new Stack<>();
|
||||
Stack<Integer> switchResultValue = new Stack<>();
|
||||
@ -265,13 +276,43 @@ public class Codegen {
|
||||
mv.visitInsn(I2F);
|
||||
else if (dest.equals(TargetType.Double))
|
||||
mv.visitInsn(I2D);
|
||||
} else if (isFunctionalInterface(source) && isFunctionalInterface(dest) &&
|
||||
!(source instanceof TargetFunNType && dest instanceof TargetFunNType)) {
|
||||
boxFunctionalInterface(state, source, dest);
|
||||
} else if (!(dest instanceof TargetGenericType)) {
|
||||
boxPrimitive(state, source);
|
||||
//boxPrimitive(state, source);
|
||||
mv.visitTypeInsn(CHECKCAST, dest.getInternalName());
|
||||
unboxPrimitive(state, dest);
|
||||
}
|
||||
}
|
||||
|
||||
record TypePair(TargetType from, TargetType to) {}
|
||||
private Map<TypePair, String> funWrapperClasses = new HashMap<>();
|
||||
|
||||
private void boxFunctionalInterface(State state, TargetType source, TargetType dest) {
|
||||
var mv = state.mv;
|
||||
var className = "FunWrapper$$" +
|
||||
source.name().replaceAll("\\.", "\\$") +
|
||||
"$_$" +
|
||||
dest.name().replaceAll("\\.", "\\$");
|
||||
|
||||
funWrapperClasses.put(new TypePair(source, dest), className);
|
||||
mv.visitTypeInsn(NEW, className);
|
||||
mv.visitInsn(DUP_X1);
|
||||
mv.visitInsn(SWAP);
|
||||
mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "(" + source.toDescriptor() + ")V", false);
|
||||
}
|
||||
|
||||
private boolean isFunctionalInterface(TargetType type) {
|
||||
if (type instanceof TargetFunNType) return true;
|
||||
if (type instanceof TargetRefType) {
|
||||
var clazz = compiler.getClass(new JavaClassName(type.name()));
|
||||
return (clazz.getModifiers() & Modifier.INTERFACE) != 0 && clazz.isFunctionalInterface();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private TargetType largerType(TargetType left, TargetType right) {
|
||||
if (left.equals(TargetType.String) || right.equals(TargetType.String)) {
|
||||
return TargetType.String;
|
||||
@ -281,9 +322,12 @@ public class Codegen {
|
||||
return TargetType.Float;
|
||||
} else if (left.equals(TargetType.Long) || right.equals(TargetType.Long)) {
|
||||
return TargetType.Long;
|
||||
} else {
|
||||
} else if (left.equals(TargetType.Integer) || right.equals(TargetType.Integer)) {
|
||||
return TargetType.Integer;
|
||||
} else if (left.equals(TargetType.Short) || right.equals(TargetType.Short)) {
|
||||
return TargetType.Short;
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
private void generateBinaryOp(State state, TargetBinaryOp op) {
|
||||
@ -718,15 +762,23 @@ public class Codegen {
|
||||
private void generateLambdaExpression(State state, TargetLambdaExpression lambda) {
|
||||
var mv = state.mv;
|
||||
|
||||
String methodName = "apply";
|
||||
TargetMethod.Signature signature = new TargetMethod.Signature(Set.of(),
|
||||
lambda.signature().parameters().stream().map(
|
||||
par -> par.withType(TargetType.Object)).toList(),
|
||||
lambda.signature().returnType() != null ? TargetType.Object : null);
|
||||
|
||||
var parameters = new ArrayList<>(lambda.captures());
|
||||
parameters.addAll(signature.parameters());
|
||||
var implSignature = new TargetMethod.Signature(Set.of(), parameters, lambda.signature().returnType());
|
||||
|
||||
TargetMethod impl;
|
||||
if (lambdas.containsKey(lambda)) {
|
||||
impl = lambdas.get(lambda);
|
||||
} else {
|
||||
var name = "lambda$" + lambdaCounter++;
|
||||
var parameters = new ArrayList<>(lambda.captures());
|
||||
parameters.addAll(lambda.params().stream().map(param -> param.pattern().type() instanceof TargetGenericType ? param.withType(TargetType.Object) : param).toList());
|
||||
|
||||
impl = new TargetMethod(0, name, lambda.block(), new TargetMethod.Signature(Set.of(), parameters, lambda.returnType() instanceof TargetGenericType ? TargetType.Object : lambda.returnType()), null);
|
||||
impl = new TargetMethod(0, name, lambda.block(), implSignature, null);
|
||||
generateMethod(impl);
|
||||
lambdas.put(lambda, impl);
|
||||
}
|
||||
@ -734,35 +786,55 @@ public class Codegen {
|
||||
var mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, MethodType.class, MethodHandle.class, MethodType.class);
|
||||
|
||||
var bootstrap = new Handle(H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "metafactory", mt.toMethodDescriptorString(), false);
|
||||
var handle = new Handle(H_INVOKEVIRTUAL, clazz.getName(), impl.name(), impl.getDescriptor(), false);
|
||||
|
||||
// TODO maybe make this a function?
|
||||
var desugared = "(";
|
||||
for (var param : lambda.params())
|
||||
desugared += "Ljava/lang/Object;";
|
||||
desugared += ")";
|
||||
if (lambda.returnType() != null)
|
||||
desugared += "Ljava/lang/Object;";
|
||||
else
|
||||
desugared += "V";
|
||||
var handle = new Handle(H_INVOKEVIRTUAL, clazz.getName(), impl.name(), implSignature.getDescriptor(), false);
|
||||
|
||||
var params = new ArrayList<TargetType>();
|
||||
params.add(new TargetRefType(clazz.qualifiedName().getClassName()));
|
||||
params.addAll(lambda.captures().stream().map(mp -> mp.pattern().type()).toList());
|
||||
|
||||
var descriptor = TargetMethod.getDescriptor(state.contextType, params.toArray(TargetType[]::new));
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
for (var capture : lambda.captures()) {
|
||||
for (var index = 0; index < lambda.captures().size(); index++) {
|
||||
var capture = lambda.captures().get(index);
|
||||
var pattern = (TargetTypePattern) capture.pattern();
|
||||
mv.visitVarInsn(ALOAD, state.scope.get(pattern.name()).index);
|
||||
var variable = state.scope.get(pattern.name());
|
||||
mv.visitVarInsn(ALOAD, variable.index);
|
||||
mv.visitTypeInsn(CHECKCAST, capture.pattern().type().getInternalName());
|
||||
}
|
||||
|
||||
String methodName;
|
||||
var intf = compiler.getClass(new JavaClassName(state.contextType.name()));
|
||||
if (intf == null) methodName = "apply"; // TODO Weird fallback logic here
|
||||
else methodName = intf.getMethods().stream().filter(m -> Modifier.isAbstract(m.modifier)).findFirst().orElseThrow().getName();
|
||||
var descriptor = TargetMethod.getDescriptor(lambda.type(), params.toArray(TargetType[]::new));
|
||||
mv.visitInvokeDynamicInsn(methodName, descriptor, bootstrap, Type.getType(signature.getSignature()), handle, Type.getType(signature.getDescriptor()));
|
||||
}
|
||||
|
||||
mv.visitInvokeDynamicInsn(methodName, descriptor, bootstrap, Type.getType(desugared), handle, Type.getType(TargetMethod.getDescriptor(impl.signature().returnType(), lambda.params().stream().map(mp -> mp.pattern().type()).toArray(TargetType[]::new))));
|
||||
private int findReturnCode(TargetType returnType) {
|
||||
if (returnType.equals(TargetType.boolean_)
|
||||
|| returnType.equals(TargetType.char_)
|
||||
|| returnType.equals(TargetType.int_)
|
||||
|| returnType.equals(TargetType.short_)
|
||||
|| returnType.equals(TargetType.byte_))
|
||||
return IRETURN;
|
||||
else if (returnType.equals(TargetType.long_))
|
||||
return LRETURN;
|
||||
else if (returnType.equals(TargetType.float_))
|
||||
return FRETURN;
|
||||
else if (returnType.equals(TargetType.double_))
|
||||
return DRETURN;
|
||||
return ARETURN;
|
||||
}
|
||||
|
||||
private int findLoadCode(TargetType loadType) {
|
||||
if (loadType.equals(TargetType.boolean_)
|
||||
|| loadType.equals(TargetType.char_)
|
||||
|| loadType.equals(TargetType.int_)
|
||||
|| loadType.equals(TargetType.short_)
|
||||
|| loadType.equals(TargetType.byte_))
|
||||
return ILOAD;
|
||||
else if (loadType.equals(TargetType.long_))
|
||||
return LLOAD;
|
||||
else if (loadType.equals(TargetType.float_))
|
||||
return FLOAD;
|
||||
else if (loadType.equals(TargetType.double_))
|
||||
return DLOAD;
|
||||
return ALOAD;
|
||||
}
|
||||
|
||||
private void generate(State state, TargetExpression expr) {
|
||||
@ -789,10 +861,7 @@ public class Codegen {
|
||||
break;
|
||||
}
|
||||
case TargetCast cast:
|
||||
var ctx = state.contextType;
|
||||
state.contextType = cast.type();
|
||||
generate(state, cast.expr());
|
||||
state.contextType = ctx;
|
||||
convertTo(state, cast.expr().type(), cast.type());
|
||||
break;
|
||||
case TargetInstanceOf instanceOf:
|
||||
@ -837,10 +906,7 @@ public class Codegen {
|
||||
case TargetAssign assign: {
|
||||
switch (assign.left()) {
|
||||
case TargetLocalVar localVar -> {
|
||||
var ctype = state.contextType;
|
||||
state.contextType = localVar.type();
|
||||
generate(state, assign.right());
|
||||
state.contextType = ctype;
|
||||
|
||||
convertTo(state, assign.right().type(), localVar.type());
|
||||
boxPrimitive(state, localVar.type());
|
||||
@ -853,10 +919,7 @@ public class Codegen {
|
||||
if (!(dot.left() instanceof TargetThis && dot.isStatic()))
|
||||
generate(state, dot.left());
|
||||
|
||||
var ctype = state.contextType;
|
||||
state.contextType = fieldType;
|
||||
generate(state, assign.right());
|
||||
state.contextType = ctype;
|
||||
|
||||
convertTo(state, assign.right().type(), fieldType);
|
||||
boxPrimitive(state, fieldType);
|
||||
@ -873,6 +936,8 @@ public class Codegen {
|
||||
case TargetLocalVar localVar: {
|
||||
LocalVar local = state.scope.get(localVar.name());
|
||||
mv.visitVarInsn(ALOAD, local.index());
|
||||
// This is a bit weird but sometimes the types don't match (see lambda expressions)
|
||||
convertTo(state, local.type(), localVar.type());
|
||||
unboxPrimitive(state, local.type());
|
||||
break;
|
||||
}
|
||||
@ -946,6 +1011,27 @@ public class Codegen {
|
||||
mv.visitLabel(end);
|
||||
break;
|
||||
}
|
||||
case TargetDo _do: {
|
||||
Label start = new Label();
|
||||
Label end = new Label();
|
||||
Label check = new Label();
|
||||
|
||||
var env = new BreakEnv();
|
||||
env.startLabel = check;
|
||||
env.endLabel = end;
|
||||
|
||||
mv.visitLabel(start);
|
||||
state.breakStack.push(env);
|
||||
generate(state, _do.body());
|
||||
state.breakStack.pop();
|
||||
|
||||
mv.visitLabel(check);
|
||||
generate(state, _do.cond());
|
||||
mv.visitJumpInsn(IFEQ, end);
|
||||
mv.visitJumpInsn(GOTO, start);
|
||||
mv.visitLabel(end);
|
||||
break;
|
||||
}
|
||||
case TargetIf _if: {
|
||||
generate(state, _if.cond());
|
||||
Label _else = new Label();
|
||||
@ -962,13 +1048,17 @@ public class Codegen {
|
||||
}
|
||||
case TargetReturn ret: {
|
||||
if (ret.expression() != null && state.returnType != null) {
|
||||
var ctype = state.contextType;
|
||||
state.contextType = state.returnType;
|
||||
if (state.returnType instanceof TargetPrimitiveType) {
|
||||
generate(state, ret.expression());
|
||||
|
||||
unboxPrimitive(state, state.returnType);
|
||||
mv.visitInsn(findReturnCode(state.returnType));
|
||||
} else {
|
||||
generate(state, ret.expression());
|
||||
state.contextType = ctype;
|
||||
boxPrimitive(state, ret.expression().type());
|
||||
convertTo(state, ret.expression().type(), state.returnType);
|
||||
mv.visitInsn(ARETURN);
|
||||
}
|
||||
} else
|
||||
mv.visitInsn(RETURN);
|
||||
break;
|
||||
@ -1008,23 +1098,28 @@ public class Codegen {
|
||||
break;
|
||||
}
|
||||
case TargetMethodCall call: {
|
||||
if (!call.isStatic())
|
||||
if (!call.isStatic()) {
|
||||
generate(state, call.expr());
|
||||
boxPrimitive(state, call.expr().type());
|
||||
}
|
||||
for (var i = 0; i < call.args().size(); i++) {
|
||||
var e = call.args().get(i);
|
||||
var arg = call.parameterTypes().get(i);
|
||||
var ctype = state.contextType;
|
||||
state.contextType = arg;
|
||||
generate(state, e);
|
||||
convertTo(state, e.type(), arg);
|
||||
if (!(arg instanceof TargetPrimitiveType))
|
||||
boxPrimitive(state, e.type());
|
||||
state.contextType = ctype;
|
||||
}
|
||||
var descriptor = call.getDescriptor();
|
||||
if (call.owner() instanceof TargetFunNType) // Decay FunN
|
||||
descriptor = TargetMethod.getDescriptor(call.returnType() == null ? null : TargetType.Object, call.parameterTypes().stream().map(x -> TargetType.Object).toArray(TargetType[]::new));
|
||||
|
||||
mv.visitMethodInsn(call.isInterface() ? INVOKEINTERFACE : call.isStatic() ? INVOKESTATIC : call.name().equals("<init>") ? INVOKESPECIAL : INVOKEVIRTUAL, call.owner().getInternalName(), call.name(), descriptor, call.isInterface());
|
||||
int insn = INVOKEVIRTUAL;
|
||||
if (call.isStatic()) insn = INVOKESTATIC;
|
||||
else if (call.isInterface()) insn = INVOKEINTERFACE;
|
||||
else if (call.name().equals("<init>") || call.expr() instanceof TargetSuper || call.isPrivate()) insn = INVOKESPECIAL;
|
||||
|
||||
mv.visitMethodInsn(insn, call.owner().getInternalName(), call.name(), descriptor, call.isInterface());
|
||||
|
||||
if (call.type() != null && call.returnType() != null && !(call.returnType() instanceof TargetPrimitiveType)) {
|
||||
if (!call.returnType().equals(call.type()) && !(call.type() instanceof TargetGenericType))
|
||||
@ -1051,6 +1146,20 @@ public class Codegen {
|
||||
mv.visitInsn(ATHROW);
|
||||
break;
|
||||
}
|
||||
case TargetTernary ternary: {
|
||||
generate(state, ternary.cond());
|
||||
var iffalse = new Label();
|
||||
var end = new Label();
|
||||
mv.visitJumpInsn(IFEQ, iffalse);
|
||||
generate(state, ternary.iftrue());
|
||||
convertTo(state, ternary.iftrue().type(), ternary.type());
|
||||
mv.visitJumpInsn(GOTO, end);
|
||||
mv.visitLabel(iffalse);
|
||||
generate(state, ternary.iffalse());
|
||||
convertTo(state, ternary.iffalse().type(), ternary.type());
|
||||
mv.visitLabel(end);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new CodeGenException("Unexpected value: " + expr);
|
||||
}
|
||||
@ -1502,6 +1611,85 @@ public class Codegen {
|
||||
if (clazz instanceof TargetRecord)
|
||||
generateRecordMethods();
|
||||
|
||||
// Generate wrapper classes for function types
|
||||
for (var pair : funWrapperClasses.keySet()) {
|
||||
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 ctor = cw2.visitMethod(ACC_PUBLIC, "<init>", "(" + pair.from.toDescriptor() + ")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", pair.from.toDescriptor());
|
||||
ctor.visitInsn(RETURN);
|
||||
ctor.visitMaxs(0, 0);
|
||||
ctor.visitEnd();
|
||||
|
||||
String methodName = "apply";
|
||||
String fromDescriptor = null;
|
||||
TargetType fromReturn = null;
|
||||
if (!(pair.from instanceof TargetFunNType funNType)) {
|
||||
var fromClass = compiler.getClass(new JavaClassName(pair.from.name()));
|
||||
var fromMethod = fromClass.getMethods().stream().filter(m -> (m.modifier & ACC_ABSTRACT) != 0).findFirst().orElseThrow();
|
||||
methodName = fromMethod.name;
|
||||
|
||||
fromReturn = converter.convert(fromMethod.getReturnType());
|
||||
var fromParams = converter.convert(fromMethod.getParameterList(), converter.generics.javaGenerics()).stream().map(m -> m.pattern().type()).toArray(TargetType[]::new);
|
||||
fromDescriptor = TargetMethod.getDescriptor(fromReturn, fromParams);
|
||||
} else {
|
||||
fromReturn = funNType.returnArguments() > 0 ? TargetType.Object : null;
|
||||
fromDescriptor = funNType.toMethodDescriptor();
|
||||
}
|
||||
|
||||
var toClass = compiler.getClass(new JavaClassName(pair.to.name()));
|
||||
var toMethod = toClass.getMethods().stream().filter(m -> (m.modifier & ACC_ABSTRACT) != 0).findFirst().orElseThrow();
|
||||
var toReturn = converter.convert(toMethod.getReturnType());
|
||||
var toParams = converter.convert(toMethod.getParameterList(), converter.generics.javaGenerics()).stream().map(m -> m.pattern().type()).toArray(TargetType[]::new);
|
||||
var toDescriptor = TargetMethod.getDescriptor(toReturn, toParams);
|
||||
|
||||
// Generate wrapper method
|
||||
var mv = cw2.visitMethod(ACC_PUBLIC, toMethod.name, toDescriptor, null, null);
|
||||
var state = new State(null, mv, 0);
|
||||
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, className, "wrapped", pair.from.toDescriptor());
|
||||
for (var i = 0; i < toParams.length; i++) {
|
||||
var arg = toParams[i];
|
||||
mv.visitVarInsn(findLoadCode(arg), i + 1);
|
||||
}
|
||||
mv.visitMethodInsn(INVOKEINTERFACE, pair.from.getInternalName(), methodName, fromDescriptor, true);
|
||||
if (fromReturn != null) {
|
||||
if (toReturn instanceof TargetPrimitiveType) {
|
||||
convertTo(state, fromReturn, TargetType.toWrapper(toReturn));
|
||||
} else convertTo(state, fromReturn, toReturn);
|
||||
}
|
||||
|
||||
if (toReturn != null)
|
||||
mv.visitInsn(findReturnCode(toReturn));
|
||||
|
||||
else mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
|
||||
cw2.visitEnd();
|
||||
var bytes = cw2.toByteArray();
|
||||
converter.auxiliaries.put(className, bytes);
|
||||
|
||||
// TODO These class loading shenanigans happen in a few places, the tests load the classes individually.
|
||||
// Instead we should just look at the folder.
|
||||
try {
|
||||
converter.classLoader.findClass(className);
|
||||
} catch (ClassNotFoundException e) {
|
||||
try {
|
||||
converter.classLoader.loadClass(bytes);
|
||||
} catch (LinkageError ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
cw.visitEnd();
|
||||
return cw.toByteArray();
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
package de.dhbwstuttgart.bytecode;
|
||||
|
||||
import de.dhbwstuttgart.syntaxtree.statement.Break;
|
||||
import de.dhbwstuttgart.target.tree.TargetGeneric;
|
||||
import de.dhbwstuttgart.target.tree.type.*;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Type;
|
||||
|
||||
import java.sql.Array;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
@ -33,6 +35,36 @@ public class FunNGenerator {
|
||||
public static class GenericParameters {
|
||||
int start;
|
||||
public List<TargetType> parameters = new ArrayList<>();
|
||||
final String descriptor;
|
||||
public final List<TargetType> inParams;
|
||||
public final List<TargetType> realParams;
|
||||
|
||||
public GenericParameters(List<TargetType> params, int numReturns) {
|
||||
this.realParams = params;
|
||||
this.inParams = flattenTypeParams(params);
|
||||
var type = new TargetRefType(FunNGenerator.getSuperClassName(params.size() - 1, numReturns), params);
|
||||
descriptor = applyDescriptor(type, this);
|
||||
}
|
||||
|
||||
private static List<TargetType> flattenTypeParams(List<TargetType> params) {
|
||||
var res = new ArrayList<TargetType>();
|
||||
for (var param : params) {
|
||||
if (param instanceof TargetSpecializedType tspec) {
|
||||
res.addAll(flattenTypeParams(tspec.params()));
|
||||
} else {
|
||||
res.add(param);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public TargetType getReturnType() {
|
||||
return FunNGenerator.getReturnType(realParams);
|
||||
}
|
||||
|
||||
public List<TargetType> getArguments() {
|
||||
return FunNGenerator.getArguments(realParams);
|
||||
}
|
||||
}
|
||||
|
||||
private static String applyDescriptor(TargetType type, GenericParameters gep) {
|
||||
@ -69,7 +101,7 @@ public class FunNGenerator {
|
||||
return applyNameDescriptor(type).replace("/", "$").replace(";", "$_$");
|
||||
}
|
||||
|
||||
public static byte[] generateSuperBytecode(int numberArguments) {
|
||||
public static byte[] generateSuperBytecode(int numberArguments, int numReturnTypes) {
|
||||
StringBuilder superFunNClassSignature = new StringBuilder("<");
|
||||
StringBuilder superFunNMethodSignature = new StringBuilder("(");
|
||||
StringBuilder superFunNMethodDescriptor = new StringBuilder("(");
|
||||
@ -80,30 +112,34 @@ public class FunNGenerator {
|
||||
superFunNMethodDescriptor.append(objectSignature);
|
||||
}
|
||||
superFunNClassSignature.append(String.format("%s:%s>%s", returnGeneric, objectSignature, objectSignature));
|
||||
if (numReturnTypes > 0) {
|
||||
superFunNMethodSignature.append(String.format(")T%s;", returnGeneric));
|
||||
superFunNMethodDescriptor.append(String.format(")%s", objectSignature));
|
||||
} else {
|
||||
superFunNMethodSignature.append(")V");
|
||||
superFunNMethodDescriptor.append(")V");
|
||||
}
|
||||
|
||||
System.out.println(superFunNMethodSignature);
|
||||
|
||||
ClassWriter classWriter = new ClassWriter(0);
|
||||
MethodVisitor methodVisitor;
|
||||
classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, getSuperClassName(numberArguments), superFunNClassSignature.toString(), objectSuperType, null);
|
||||
classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, getSuperClassName(numberArguments, numReturnTypes), superFunNClassSignature.toString(), objectSuperType, null);
|
||||
methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, methodName, superFunNMethodDescriptor.toString(), superFunNMethodSignature.toString(), null);
|
||||
methodVisitor.visitEnd();
|
||||
classWriter.visitEnd();
|
||||
return classWriter.toByteArray();
|
||||
}
|
||||
|
||||
public static String getSuperClassName(int numberArguments) {
|
||||
return String.format("Fun%d$$", numberArguments);
|
||||
public static String getSuperClassName(int numberArguments, int returnArguments) {
|
||||
return returnArguments > 0 ? String.format("Fun%d$$", numberArguments) : String.format("FunVoid%d$$", numberArguments);
|
||||
}
|
||||
|
||||
public static byte[] generateSpecializedBytecode(List<TargetType> argumentTypes, TargetType returnType, GenericParameters gep) {
|
||||
List<TargetType> parameters = Stream
|
||||
.concat(argumentTypes.stream(), Stream.of(returnType))
|
||||
.toList();
|
||||
public static byte[] generateSpecializedBytecode(GenericParameters gep, List<String> superInterfaces) {
|
||||
var argumentTypes = gep.getArguments();
|
||||
var returnType = gep.getReturnType();
|
||||
|
||||
StringBuilder funNClassSignature = new StringBuilder(objectSignature + applyDescriptor(new TargetRefType(getSuperClassName(argumentTypes.size()), parameters), gep));
|
||||
StringBuilder funNClassSignature = new StringBuilder(objectSignature + gep.descriptor);
|
||||
boolean containsGeneric = false;
|
||||
|
||||
String genericSignature = "<";
|
||||
@ -114,10 +150,18 @@ public class FunNGenerator {
|
||||
|
||||
genericSignature += ">";
|
||||
if (containsGeneric) funNClassSignature.insert(0, genericSignature);
|
||||
System.out.println(funNClassSignature.toString());
|
||||
|
||||
for (var superInterface : superInterfaces) {
|
||||
funNClassSignature.append('L');
|
||||
funNClassSignature.append(superInterface);
|
||||
funNClassSignature.append(';');
|
||||
}
|
||||
|
||||
var interfaces = new ArrayList<>(superInterfaces);
|
||||
interfaces.add(getSuperClassName(argumentTypes.size(), returnType != null ? 1 : 0));
|
||||
|
||||
ClassWriter classWriter = new ClassWriter(0);
|
||||
classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, getSpecializedClassName(argumentTypes, returnType), funNClassSignature.toString(), objectSuperType, new String[]{getSuperClassName(argumentTypes.size())});
|
||||
classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, getSpecializedClassName(argumentTypes, returnType), funNClassSignature.toString(), objectSuperType, interfaces.toArray(String[]::new));
|
||||
classWriter.visitEnd();
|
||||
return classWriter.toByteArray();
|
||||
}
|
||||
@ -133,14 +177,24 @@ public class FunNGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
public static String getSpecializedClassName(GenericParameters gep) {
|
||||
return getSpecializedClassName(gep.getArguments(), gep.getReturnType());
|
||||
}
|
||||
|
||||
public static String getSpecializedClassName(List<TargetType> argumentTypes, TargetType returnType) {
|
||||
return String.format("Fun%d$$%s%s",
|
||||
argumentTypes.size(),
|
||||
argumentTypes
|
||||
var arguments = argumentTypes
|
||||
.stream()
|
||||
.map(FunNGenerator::encodeType)
|
||||
.collect(Collectors.joining()),
|
||||
.collect(Collectors.joining());
|
||||
|
||||
if (returnType != null)
|
||||
return String.format("Fun%d$$%s%s",
|
||||
argumentTypes.size(),
|
||||
arguments,
|
||||
encodeType(returnType));
|
||||
else return String.format("FunVoidImpl%d$$%s",
|
||||
argumentTypes.size(),
|
||||
arguments);
|
||||
}
|
||||
|
||||
public static List<TargetType> getArguments(List<TargetType> list) {
|
||||
@ -151,8 +205,8 @@ public class FunNGenerator {
|
||||
}
|
||||
|
||||
public static TargetType getReturnType(List<TargetType> list) {
|
||||
if(list.size() == 0)
|
||||
if(list.isEmpty())
|
||||
throw new IndexOutOfBoundsException();
|
||||
return list.get(list.size() - 1);
|
||||
return list.getLast();
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package de.dhbwstuttgart.core;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.*;
|
||||
public class ConsoleInterface {
|
||||
private static final String directory = System.getProperty("user.dir");
|
||||
@ -35,9 +37,9 @@ public class ConsoleInterface {
|
||||
input.add(new File(arg));
|
||||
}
|
||||
}
|
||||
JavaTXCompiler compiler = new JavaTXCompiler(input, classpath);
|
||||
JavaTXCompiler compiler = new JavaTXCompiler(input, classpath, outputPath != null ? new File(outputPath) : null);
|
||||
//compiler.typeInference();
|
||||
compiler.generateBytecode(outputPath);
|
||||
compiler.generateBytecode();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
//PL 2018-12-19: typeInferenceOld nach typeInference uebertragen
|
||||
package de.dhbwstuttgart.core;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import de.dhbwstuttgart.bytecode.Codegen;
|
||||
import de.dhbwstuttgart.environment.CompilationEnvironment;
|
||||
import de.dhbwstuttgart.environment.DirectoryClassLoader;
|
||||
@ -31,7 +30,6 @@ import de.dhbwstuttgart.syntaxtree.type.TypeVisitor;
|
||||
import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter;
|
||||
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
|
||||
import de.dhbwstuttgart.target.generate.GenericsResult;
|
||||
import de.dhbwstuttgart.target.tree.expression.TargetBinaryOp;
|
||||
import de.dhbwstuttgart.typeinference.constraints.Constraint;
|
||||
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
||||
import de.dhbwstuttgart.typeinference.constraints.Pair;
|
||||
@ -51,13 +49,9 @@ import de.dhbwstuttgart.typeinference.unify.UnifyResultListenerImpl;
|
||||
import de.dhbwstuttgart.typeinference.unify.UnifyResultModel;
|
||||
import de.dhbwstuttgart.typeinference.unify.UnifyTaskModel;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.sql.Array;
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.function.Function;
|
||||
@ -74,16 +68,17 @@ public class JavaTXCompiler {
|
||||
|
||||
Boolean log = false; //gibt an ob ein Log-File nach System.getProperty("user.dir")+""/logFiles/"" geschrieben werden soll?
|
||||
public volatile UnifyTaskModel usedTasks = new UnifyTaskModel();
|
||||
private final DirectoryClassLoader classLoader;
|
||||
public final DirectoryClassLoader classLoader;
|
||||
|
||||
private final List<File> classPath;
|
||||
public final List<File> classPath;
|
||||
private final File outputPath;
|
||||
|
||||
public DirectoryClassLoader getClassLoader() {
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
public JavaTXCompiler(File sourceFile) throws IOException, ClassNotFoundException {
|
||||
this(Arrays.asList(sourceFile), null);
|
||||
this(Arrays.asList(sourceFile), List.of(), new File("."));
|
||||
}
|
||||
|
||||
public JavaTXCompiler(File sourceFile, Boolean log) throws IOException, ClassNotFoundException {
|
||||
@ -92,17 +87,20 @@ public class JavaTXCompiler {
|
||||
}
|
||||
|
||||
public JavaTXCompiler(List<File> sourceFiles) throws IOException, ClassNotFoundException {
|
||||
this(sourceFiles, null);
|
||||
this(sourceFiles, List.of(), new File("."));
|
||||
}
|
||||
|
||||
public JavaTXCompiler(List<File> sources, List<File> contextPath) throws IOException, ClassNotFoundException {
|
||||
if (contextPath == null || contextPath.isEmpty()) {
|
||||
public JavaTXCompiler(List<File> sources, List<File> contextPath, File outputPath) throws IOException, ClassNotFoundException {
|
||||
var path = new ArrayList<>(contextPath);
|
||||
if (contextPath.isEmpty()) {
|
||||
// When no contextPaths are given, the working directory is the sources root
|
||||
contextPath = Lists.newArrayList(new File(System.getProperty("user.dir")));
|
||||
path.add(new File(System.getProperty("user.dir")));
|
||||
}
|
||||
classLoader = new DirectoryClassLoader(contextPath, ClassLoader.getSystemClassLoader());
|
||||
environment = new CompilationEnvironment(sources);
|
||||
classPath = contextPath;
|
||||
if (outputPath != null) path.add(outputPath);
|
||||
classLoader = new DirectoryClassLoader(path, ClassLoader.getSystemClassLoader());
|
||||
environment = new CompilationEnvironment(sources, classLoader);
|
||||
classPath = path;
|
||||
this.outputPath = outputPath;
|
||||
|
||||
for (File s : sources) {
|
||||
parse(s);
|
||||
@ -115,6 +113,7 @@ public class JavaTXCompiler {
|
||||
}
|
||||
|
||||
public ClassOrInterface getClass(JavaClassName name) {
|
||||
if (loadedClasses.containsKey(name)) return loadedClasses.get(name).cif();
|
||||
for (var sf : sourceFiles.values()) {
|
||||
for (var clazz : sf.KlassenVektor) {
|
||||
if (clazz.getClassName().equals(name)) return clazz;
|
||||
@ -128,32 +127,48 @@ public class JavaTXCompiler {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ConstraintSet<Pair> getConstraints() throws ClassNotFoundException, IOException {
|
||||
public ConstraintSet<Pair> getConstraints(File sourceFile) throws ClassNotFoundException, IOException {
|
||||
Set<ClassOrInterface> allClasses = new HashSet<>();// environment.getAllAvailableClasses();
|
||||
ClassOrInterface objectClass = ASTFactory.createClass(classLoader.loadClass(new JavaClassName("java.lang.Object").toString()));
|
||||
// Alle Importierten Klassen in allen geparsten Sourcefiles kommen ins FC
|
||||
for (Entry<File, SourceFile> source : sourceFiles.entrySet()) {
|
||||
ClassOrInterface objectClass = ASTFactory.createClass(Object.class);
|
||||
var recordClass = ASTFactory.createClass(Record.class);
|
||||
allClasses.add(objectClass);
|
||||
allClasses.add(recordClass);
|
||||
|
||||
var sf = sourceFiles.get(sourceFile);
|
||||
var importedClasses = new ArrayList<ClassOrInterface>();
|
||||
for (JavaClassName name : source.getValue().getImports()) {
|
||||
for (JavaClassName name : sf.getImports()) {
|
||||
importedClasses.addAll(getAvailableClasses(name));
|
||||
}
|
||||
for (Class c : CompilationEnvironment.loadDefaultPackageClasses(source.getValue().getPkgName(), source.getKey(), this)) {
|
||||
for (Class c : CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), sourceFile, this)) {
|
||||
ClassOrInterface importedClass = ASTFactory.createClass(c);
|
||||
importedClasses.add(importedClass);
|
||||
}
|
||||
source.getValue().availableClasses.addAll(importedClasses);
|
||||
}
|
||||
for (File f : this.sourceFiles.keySet()) {
|
||||
SourceFile sf = sourceFiles.get(f);
|
||||
sf.availableClasses.addAll(importedClasses);
|
||||
|
||||
SourceFile sf_new = new SourceFile(sf.getPkgName(), sf.KlassenVektor.stream().map(cl -> new ClassOrInterface(cl)).collect(Collectors.toCollection(ArrayList::new)), sf.imports);
|
||||
// sf enthaelt neues Source-File, neue Klassen-Objekte und neue
|
||||
// ArrayListen-Objekte fuer Fields, Construktoren und Methoden
|
||||
// Alle anderen Objekte werden nur kopiert.
|
||||
var isCached = false;
|
||||
for (var clazz : sf.availableClasses) {
|
||||
if (loadedClasses.containsKey(clazz.getClassName())) {
|
||||
allClasses.removeIf(cl -> cl.getClassName().equals(clazz.getClassName()));
|
||||
var cif = loadedClasses.get(clazz.getClassName()).cif();
|
||||
allClasses.add(cif);
|
||||
isCached = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isCached) {
|
||||
sf_new.KlassenVektor.forEach(cl -> addMethods(sf_new, cl, sf.availableClasses, objectClass));
|
||||
allClasses.addAll(sf_new.getClasses());
|
||||
}
|
||||
TYPE ty = new TYPE(sourceFiles.values(), allClasses);
|
||||
return ty.getConstraints();
|
||||
|
||||
allClasses.addAll(sf.KlassenVektor);
|
||||
|
||||
TYPE ty = new TYPE(sf, allClasses);
|
||||
var constraints = ty.getConstraints();
|
||||
return constraints;
|
||||
}
|
||||
|
||||
void addMethods(SourceFile sf, ClassOrInterface cl, List<ClassOrInterface> importedClasses, ClassOrInterface objectClass) {
|
||||
@ -183,36 +198,35 @@ public class JavaTXCompiler {
|
||||
while (paraIt.hasNext()) {
|
||||
gtvs.put(tvarVarIt.next().getName(), paraIt.next());
|
||||
}
|
||||
Iterator<Method> methodIt = superclass.getMethods().iterator();
|
||||
// TODO: PL 2020-05-06: Hier müssen ueberschriebene Methoden noch rausgefiltert
|
||||
// werden
|
||||
while (methodIt.hasNext()) {
|
||||
Method m = methodIt.next();
|
||||
|
||||
for (Method m : superclass.getMethods()) {
|
||||
if (m.isInherited || Modifier.isStatic(m.modifier)) continue;
|
||||
// TODO: Add gtvs from method itself
|
||||
|
||||
ParameterList newParaList = new ParameterList(m.getParameterList().getFormalparalist().stream().map(fp -> fp.withType(fp.getType().acceptTV(new TypeExchanger(gtvs)))).collect(Collectors.toCollection(ArrayList::new)), m.getParameterList().getOffset());
|
||||
cl.getMethods().add(new Method(m.modifier, m.name, m.getReturnType().acceptTV(new TypeExchanger(gtvs)), newParaList, m.block,
|
||||
// new GenericDeclarationList(newGenericsList,
|
||||
// ((GenericDeclarationList)m.getGenerics()).getOffset()),
|
||||
(GenericDeclarationList) m.getGenerics(), m.getOffset(), true));
|
||||
(GenericDeclarationList) m.getGenerics(), m.getOffset(), true, false));
|
||||
}
|
||||
|
||||
}
|
||||
cl.setMethodsAdded();
|
||||
}
|
||||
|
||||
private List<ClassOrInterface> getAvailableClasses(JavaClassName name) throws ClassNotFoundException {
|
||||
private Set<ClassOrInterface> getAvailableClasses(JavaClassName name) throws ClassNotFoundException {
|
||||
Set<ClassOrInterface> allClasses = new HashSet<>();
|
||||
if (loadJavaTXClass(name)) {
|
||||
var file = findFileForClass(name);
|
||||
var sf = sourceFiles.get(file);
|
||||
if (sf != null) allClasses.addAll(sf.KlassenVektor);
|
||||
} else {
|
||||
var clazz = loadJavaTXClass(name);
|
||||
if (clazz == null) {
|
||||
ClassOrInterface importedClass = ASTFactory.createClass(classLoader.loadClass(name.toString()));
|
||||
allClasses.add(importedClass);
|
||||
} else {
|
||||
allClasses.add(clazz);
|
||||
}
|
||||
return new ArrayList<>(allClasses);
|
||||
return allClasses;
|
||||
}
|
||||
|
||||
public List<ClassOrInterface> getAvailableClasses(SourceFile forSourceFile) throws ClassNotFoundException {
|
||||
public Set<ClassOrInterface> getAvailableClasses(SourceFile forSourceFile) throws ClassNotFoundException {
|
||||
// PL 2018-09-18: List durch Set ersetzt, damit die Klassen nur einmal
|
||||
// hinzugefuegt werden
|
||||
// List<ClassOrInterface> allClasses = new
|
||||
@ -222,7 +236,7 @@ public class JavaTXCompiler {
|
||||
for (JavaClassName name : forSourceFile.getImports()) {
|
||||
allClasses.addAll(getAvailableClasses(name));
|
||||
}
|
||||
return new ArrayList<>(allClasses);
|
||||
return allClasses;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -278,17 +292,21 @@ public class JavaTXCompiler {
|
||||
allClasses.addAll(CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), source.getKey(), this).stream().map(ASTFactory::createClass).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
final ConstraintSet<Pair> cons = getConstraints();
|
||||
final ConstraintSet<Pair> cons = new ConstraintSet<>();
|
||||
for (var f : this.sourceFiles.keySet()) {
|
||||
cons.addAll(getConstraints(f));
|
||||
}
|
||||
|
||||
Set<Set<UnifyPair>> results = new HashSet<>();
|
||||
UnifyResultModel urm = null;
|
||||
// urm.addUnifyResultListener(resultListener);
|
||||
try {
|
||||
logFile = logFile == null ? new FileWriter(new File("log_" + sourceFiles.keySet().iterator().next().getName())) : logFile;
|
||||
IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses, logFile, getClassLoader());
|
||||
IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses, logFile, getClassLoader(), this);
|
||||
System.out.println(finiteClosure);
|
||||
urm = new UnifyResultModel(cons, finiteClosure);
|
||||
urm.addUnifyResultListener(resultListener);
|
||||
ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(cons);
|
||||
ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(this, cons);
|
||||
|
||||
Function<UnifyPair, UnifyPair> distributeInnerVars = x -> {
|
||||
UnifyType lhs, rhs;
|
||||
@ -305,8 +323,8 @@ public class JavaTXCompiler {
|
||||
TypeUnify unify = new TypeUnify();
|
||||
// Set<Set<UnifyPair>> results = new HashSet<>(); Nach vorne gezogen
|
||||
logFile.write("FC:\\" + finiteClosure.toString() + "\n");
|
||||
for (SourceFile sf : this.sourceFiles.values()) {
|
||||
logFile.write(ASTTypePrinter.print(sf));
|
||||
for (SourceFile f : this.sourceFiles.values()) {
|
||||
logFile.write(ASTTypePrinter.print(f));
|
||||
}
|
||||
logFile.flush();
|
||||
|
||||
@ -399,14 +417,12 @@ public class JavaTXCompiler {
|
||||
return urm;
|
||||
}
|
||||
|
||||
public List<ResultSet> typeInference() throws ClassNotFoundException, IOException {
|
||||
List<ClassOrInterface> allClasses = new ArrayList<>();// environment.getAllAvailableClasses();
|
||||
// Alle Importierten Klassen in allen geparsten Sourcefiles kommen ins FC
|
||||
for (Entry<File, SourceFile> source : this.sourceFiles.entrySet()) {
|
||||
SourceFile sf = source.getValue();
|
||||
public List<ResultSet> typeInference(File file) throws ClassNotFoundException, IOException {
|
||||
var sf = sourceFiles.get(file);
|
||||
Set<ClassOrInterface> allClasses = new HashSet<>();// environment.getAllAvailableClasses();
|
||||
allClasses.addAll(getAvailableClasses(sf));
|
||||
allClasses.addAll(sf.getClasses());
|
||||
var newClasses = CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), source.getKey(), this).stream().map(ASTFactory::createClass).collect(Collectors.toList());
|
||||
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())))
|
||||
@ -414,17 +430,16 @@ public class JavaTXCompiler {
|
||||
if (allClasses.stream().noneMatch(old -> old.getClassName().equals(clazz.getClassName())))
|
||||
allClasses.add(clazz);
|
||||
}
|
||||
}
|
||||
|
||||
final ConstraintSet<Pair> cons = getConstraints();
|
||||
final ConstraintSet<Pair> cons = getConstraints(file);
|
||||
Set<Set<UnifyPair>> results = new HashSet<>();
|
||||
try {
|
||||
var logFolder = new File(System.getProperty("user.dir") + "/logFiles/");
|
||||
if (log) logFolder.mkdirs();
|
||||
Writer logFile = log ? new FileWriter(new File(logFolder, "log_" + sourceFiles.keySet().iterator().next().getName())) : new OutputStreamWriter(new NullOutputStream());
|
||||
IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses, logFile, classLoader);
|
||||
IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses.stream().toList(), logFile, classLoader, this);
|
||||
System.out.println(finiteClosure);
|
||||
ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(cons);
|
||||
ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(this, cons);
|
||||
System.out.println("xxx1");
|
||||
Function<UnifyPair, UnifyPair> distributeInnerVars = x -> {
|
||||
UnifyType lhs, rhs;
|
||||
@ -443,10 +458,8 @@ public class JavaTXCompiler {
|
||||
TypeUnify unify = new TypeUnify();
|
||||
// Set<Set<UnifyPair>> results = new HashSet<>(); Nach vorne gezogen
|
||||
logFile.write("FC:\\" + finiteClosure.toString() + "\n");
|
||||
for (SourceFile sf : this.sourceFiles.values()) {
|
||||
logFile.write(ASTTypePrinter.print(sf));
|
||||
System.out.println(ASTTypePrinter.print(sf));
|
||||
}
|
||||
logFile.flush();
|
||||
|
||||
Set<String> methodParaTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().map(y -> y.getParameterList().getFormalparalist().stream().filter(z -> z.getType() instanceof TypePlaceholder).map(z -> ((TypePlaceholder) z.getType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce(new HashSet<String>(), (a, b) -> {
|
||||
@ -648,14 +661,20 @@ public class JavaTXCompiler {
|
||||
|
||||
public final JavaClassRegistry classRegistry = new JavaClassRegistry();
|
||||
|
||||
public record ClassEntry(File classFile, ClassOrInterface cif) {}
|
||||
|
||||
public final Map<JavaClassName, ClassEntry> loadedClasses = new HashMap<>();
|
||||
|
||||
private SourceFile parse(File sourceFile) throws IOException, java.lang.ClassNotFoundException {
|
||||
if (sourceFiles.containsKey(sourceFile)) return sourceFiles.get(sourceFile);
|
||||
SourceFileContext tree = JavaTXParser.parse(sourceFile);
|
||||
environment.addClassesToRegistry(classRegistry, tree, sourceFile, this);
|
||||
SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null), sourceFile.getName());
|
||||
var classes = new ArrayList<ClassOrInterface>();
|
||||
var sf = new SourceFile(generator.pkgName, classes, generator.imports);
|
||||
var sf = new SourceFile("", classes, generator.imports);
|
||||
addSourceFile(sourceFile, sf);
|
||||
generator.convert(classes, tree, environment.packageCrawler);
|
||||
sf.setPackageName(generator.pkgName);
|
||||
sf.imports.addAll(generator.imports);
|
||||
return sf;
|
||||
}
|
||||
@ -665,25 +684,33 @@ public class JavaTXCompiler {
|
||||
* if it doesn't exist it's going to compile it and add it to the source files list
|
||||
* @param name
|
||||
*/
|
||||
public boolean loadJavaTXClass(JavaClassName name) {
|
||||
public ClassOrInterface loadJavaTXClass(JavaClassName name) {
|
||||
var file = findFileForClass(name);
|
||||
if (file != null) {
|
||||
if (classRegistry.contains(name)) return true;
|
||||
if (loadedClasses.containsKey(name)) return loadedClasses.get(name).cif();
|
||||
try {
|
||||
var tree = JavaTXParser.parse(file);
|
||||
classRegistry.addName(name.toString(), 0); // TODO This gets overwritten later, is it bad if we don't know this right away?
|
||||
environment.addClassesToRegistry(classRegistry, tree, file, this);
|
||||
SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null), file.getName());
|
||||
var classes = new ArrayList<ClassOrInterface>();
|
||||
var sf = new SourceFile(generator.pkgName, classes, generator.imports);
|
||||
var sf = new SourceFile("", classes, generator.imports);
|
||||
addSourceFile(file, sf);
|
||||
generator.convert(classes, tree, environment.packageCrawler);
|
||||
return true;
|
||||
sf.setPackageName(generator.pkgName);
|
||||
var classFiles = generateBytecode(file);
|
||||
|
||||
sf.setGenerated();
|
||||
writeClassFile(classFiles, outputPath != null ? outputPath : new File("."), false);
|
||||
var clazz = classLoader.loadClass(name.toString());
|
||||
var classOrInterface = ASTFactory.createClass(clazz);
|
||||
loadedClasses.put(name, new ClassEntry(new File(outputPath, clazz.getName() + ".class"), classOrInterface));
|
||||
return classOrInterface;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
public File findFileForClass(JavaClassName name) {
|
||||
@ -697,25 +724,26 @@ public class JavaTXCompiler {
|
||||
}
|
||||
|
||||
public void generateBytecode() throws ClassNotFoundException, IOException {
|
||||
generateBytecode((File) null);
|
||||
for (var file : sourceFiles.keySet()) {
|
||||
var sf = sourceFiles.get(file);
|
||||
if (sf.isGenerated()) continue;
|
||||
var classes = generateBytecode(file);
|
||||
sf.setGenerated();
|
||||
writeClassFile(classes, outputPath == null ? file.getParentFile() : outputPath, outputPath == null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param path - can be null, then class file output is in the same directory as the parsed source files
|
||||
*/
|
||||
public void generateBytecode(String path) throws ClassNotFoundException, IOException {
|
||||
if (path != null)
|
||||
generateBytecode(new File(path));
|
||||
else
|
||||
generateBytecode();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param path - output-Directory can be null, then class file output is in the same directory as the parsed source files
|
||||
* @return
|
||||
*/
|
||||
public void generateBytecode(File path) throws ClassNotFoundException, IOException {
|
||||
List<ResultSet> typeinferenceResult = this.typeInference();
|
||||
generateBytecode(path, typeinferenceResult);
|
||||
public Map<JavaClassName, byte[]> generateBytecode(File sourceFile) throws ClassNotFoundException, IOException {
|
||||
var sf = sourceFiles.get(sourceFile);
|
||||
if (sf.isGenerated()) return null;
|
||||
List<ResultSet> typeinferenceResult = this.typeInference(sourceFile);
|
||||
var classes = generateBytecode(sf, typeinferenceResult);
|
||||
sf.setGenerated();
|
||||
return classes;
|
||||
}
|
||||
|
||||
private Map<SourceFile, List<GenericsResult>> generatedGenerics = new HashMap<>();
|
||||
@ -733,15 +761,13 @@ public class JavaTXCompiler {
|
||||
for (File f : sourceFiles.keySet()) {
|
||||
HashMap<JavaClassName, byte[]> classFiles = new HashMap<>();
|
||||
SourceFile sf = sourceFiles.get(f);
|
||||
File path;
|
||||
File path = outputPath;
|
||||
if (outputPath == null) {
|
||||
path = f.getParentFile(); // Set path to path of the parsed .jav file
|
||||
} else {
|
||||
path = new File(outputPath, sf.getPkgName().replace(".", "/")); // add package path to root path
|
||||
}
|
||||
|
||||
var generatedClasses = generateBytecode(sf, typeinferenceResult);
|
||||
writeClassFile(generatedClasses, path);
|
||||
writeClassFile(generatedClasses, path, outputPath == null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -749,7 +775,7 @@ public class JavaTXCompiler {
|
||||
var converter = new ASTToTargetAST(this, typeInferenceResult, sf, classLoader);
|
||||
var generatedClasses = new HashMap<JavaClassName, byte[]>();
|
||||
for (var clazz : sf.getClasses()) {
|
||||
var codegen = new Codegen(converter.convert(clazz), this);
|
||||
var codegen = new Codegen(converter.convert(clazz), this, converter);
|
||||
var code = codegen.generate();
|
||||
generatedClasses.put(clazz.getClassName(), code);
|
||||
converter.auxiliaries.forEach((name, source) -> {
|
||||
@ -757,18 +783,19 @@ public class JavaTXCompiler {
|
||||
});
|
||||
}
|
||||
generatedGenerics.put(sf, converter.javaGenerics());
|
||||
converter.generateFunNTypes();
|
||||
return generatedClasses;
|
||||
}
|
||||
|
||||
public synchronized void writeClassFile(Map<JavaClassName, byte[]> classFiles, File path) throws IOException {
|
||||
public synchronized void writeClassFile(Map<JavaClassName, byte[]> classFiles, File path, boolean preserveHierarchy) throws IOException {
|
||||
FileOutputStream output;
|
||||
for (JavaClassName name : classFiles.keySet()) {
|
||||
byte[] bytecode = classFiles.get(name);
|
||||
System.out.println("generating " + name + ".class file ...");
|
||||
// output = new FileOutputStream(new File(System.getProperty("user.dir") +
|
||||
// "/testBytecode/generatedBC/" +name+".class"));
|
||||
File outputFile = new File(path, name.getClassName() + ".class");
|
||||
var subPath = preserveHierarchy ? path : Path.of(path.toString(), name.getPackageName().split("\\.")).toFile();
|
||||
File outputFile = new File(subPath, name.getClassName() + ".class");
|
||||
outputFile.getAbsoluteFile().getParentFile().mkdirs();
|
||||
System.out.println(outputFile);
|
||||
output = new FileOutputStream(outputFile);
|
||||
output.write(bytecode);
|
||||
output.close();
|
||||
|
@ -34,7 +34,7 @@ public class CompilationEnvironment {
|
||||
*
|
||||
* @param sourceFiles die zu kompilierenden Dateien
|
||||
*/
|
||||
public CompilationEnvironment(List<File> sourceFiles) {
|
||||
public CompilationEnvironment(List<File> sourceFiles, DirectoryClassLoader classLoader) {
|
||||
/**
|
||||
* Java 9 bringt einige Änderungen am Classloader So funktioniert der BootClassLoader nicht mehr. hier gibts ein paar Quellen zum nachlesen: http://java9.wtf/class-loading/ https://stackoverflow.com/questions/46494112/classloaders-hierarchy-in-java-9
|
||||
*
|
||||
@ -54,7 +54,7 @@ public class CompilationEnvironment {
|
||||
// librarys = Arrays.asList(loader.getURLs());
|
||||
|
||||
this.sourceFiles = sourceFiles;
|
||||
this.packageCrawler = new PackageCrawler(librarys);
|
||||
this.packageCrawler = new PackageCrawler(classLoader);
|
||||
}
|
||||
|
||||
public void addClassesToRegistry(JavaClassRegistry registry, SourceFileContext tree, File sourceFile, JavaTXCompiler compiler) throws ClassNotFoundException, IOException {
|
||||
@ -77,7 +77,7 @@ public class CompilationEnvironment {
|
||||
// Set classLoader to include default package for this specific source file
|
||||
File dir = sourceFile.getAbsoluteFile().getParentFile();
|
||||
String dirPath = dir.toString() + "/";
|
||||
if (packageName.length() > 0)
|
||||
if (!packageName.isEmpty())
|
||||
dirPath = dirPath.substring(0, dirPath.length() - packageName.length() - 1);
|
||||
String path = dirPath;
|
||||
ArrayList<File> defaultPath = Lists.newArrayList(new File(path));
|
||||
@ -89,7 +89,10 @@ public class CompilationEnvironment {
|
||||
String className = classFile.getName().substring(0, classFile.getName().length() - 6);
|
||||
if (className.matches("Fun\\d+\\$\\$.*"))
|
||||
continue;
|
||||
ret.add(classLoader.loadClass(packageName + className));
|
||||
var name = packageName;
|
||||
if (!packageName.isEmpty()) name += ".";
|
||||
name += className;
|
||||
ret.add(classLoader.loadClass(name));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -101,12 +104,4 @@ public class CompilationEnvironment {
|
||||
return packageName;
|
||||
}
|
||||
|
||||
public List<ClassOrInterface> getAllAvailableClasses() {
|
||||
List<ClassOrInterface> ret = new ArrayList<>();
|
||||
for (Class c : new PackageCrawler(librarys).getAllAvailableClasses()) {
|
||||
ret.add(ASTFactory.createClass(c));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,31 +5,61 @@ import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class DirectoryClassLoader extends URLClassLoader implements IByteArrayClassLoader {
|
||||
public DirectoryClassLoader(File directory, java.lang.ClassLoader parent) {
|
||||
super(generateURLArray(dirToURL(directory)), parent);
|
||||
}
|
||||
// public DirectoryClassLoader(File directory, java.lang.ClassLoader parent) {
|
||||
// super(generateURLArray(dirToURL(directory)), parent);
|
||||
// }
|
||||
|
||||
public DirectoryClassLoader(List<File> directory, java.lang.ClassLoader parent) {
|
||||
super(directory.stream().map(DirectoryClassLoader::dirToURL).collect(Collectors.toList()).toArray(new URL[0]), parent);
|
||||
super(directory.stream().map(DirectoryClassLoader::dirToURL).flatMap(List::stream).collect(Collectors.toList()).toArray(new URL[0]), parent.getParent());
|
||||
}
|
||||
|
||||
private static URL[] generateURLArray(URL url) {
|
||||
return new URL[]{url};
|
||||
}
|
||||
|
||||
private static URL dirToURL(File url){
|
||||
if(!url.isDirectory())throw new RuntimeException(url.toString() + " is not a directory");
|
||||
private static List<URL> dirToURL(File file) {
|
||||
//if(!url.isDirectory())throw new RuntimeException(url.toString() + " is not a directory");
|
||||
|
||||
Path dir;
|
||||
if (file.isDirectory()) {
|
||||
try {
|
||||
return url.toURI().toURL();
|
||||
return List.of(file.toURI().toURL()); // if file is a directory, use it as is
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
return List.of();
|
||||
}
|
||||
}
|
||||
|
||||
dir = file.toPath().getParent(); // if file is not a directory, get its parent directory
|
||||
String pattern = file.toPath().getFileName().toString(); // use the file name as a glob pattern
|
||||
|
||||
List<URL> urls = new ArrayList<>();
|
||||
|
||||
try {
|
||||
urls = Files.walk(dir)
|
||||
.filter(Files::isRegularFile) // only consider files (not directories)
|
||||
.filter(path -> {
|
||||
PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:" + pattern);
|
||||
return matcher.matches(path.getFileName()); // match the file name against the pattern
|
||||
})
|
||||
.map(path -> {
|
||||
try {
|
||||
return path.toUri().toURL();
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}) // convert the path to a URL
|
||||
.toList(); // print the path of each matching file
|
||||
} catch (IOException | RuntimeException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return urls;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -41,4 +71,8 @@ public class DirectoryClassLoader extends URLClassLoader implements IByteArrayCl
|
||||
public Class<?> findClass(String name) throws ClassNotFoundException {
|
||||
return super.findClass(name);
|
||||
}
|
||||
|
||||
public Class<?> _findLoadedClass(String name) throws ClassNotFoundException {
|
||||
return super.findLoadedClass(name);
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,10 @@
|
||||
package de.dhbwstuttgart.environment;
|
||||
|
||||
import java.net.URL;
|
||||
import io.github.classgraph.ClassGraph;
|
||||
import io.github.classgraph.ScanResult;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.reflections.Reflections;
|
||||
import org.reflections.scanners.ResourcesScanner;
|
||||
import org.reflections.scanners.SubTypesScanner;
|
||||
import org.reflections.util.ConfigurationBuilder;
|
||||
import org.reflections.util.FilterBuilder;
|
||||
|
||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||
import org.reflections.vfs.SystemDir;
|
||||
|
||||
/**
|
||||
* Hilft beim Durchsuchen von Packages
|
||||
* Benutzt die Reflections-Library (https://github.com/ronmamo/reflections)
|
||||
@ -19,48 +12,30 @@ import org.reflections.vfs.SystemDir;
|
||||
*/
|
||||
public class PackageCrawler {
|
||||
|
||||
final URL[] urls;
|
||||
public PackageCrawler(List<URL> urlList) {
|
||||
urls = urlList.toArray(new URL[0]);
|
||||
final DirectoryClassLoader classLoader;
|
||||
public PackageCrawler(DirectoryClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
public Set<Class<?>> getClassesInPackage(String packageName) {
|
||||
/*
|
||||
List<DirectoryClassLoader> classLoadersList = new LinkedList<DirectoryClassLoader>();
|
||||
classLoadersList.add(Thread.currentThread().getContextClassLoader());
|
||||
classLoadersList.add(ClasspathHelper.staticClassLoader());
|
||||
classLoadersList.add(Thread.currentThread().getContextClassLoader().getParent());
|
||||
classLoadersList.add(DirectoryClassLoader.getSystemClassLoader());
|
||||
String bootClassPath = System.getProperty("sun.boot.class.path");
|
||||
ArrayList<URL> urlList = new ArrayList<>();
|
||||
for(String path : bootClassPath.split(";")) {
|
||||
var res = new HashSet<Class<?>>();
|
||||
|
||||
try (ScanResult result = new ClassGraph()
|
||||
.enableClassInfo()
|
||||
.enableSystemJarsAndModules()
|
||||
.addClassLoader(classLoader)
|
||||
.acceptPackages(packageName)
|
||||
.scan()) {
|
||||
|
||||
for (var info : result.getAllClasses()) {
|
||||
try {
|
||||
urlList.add(new URL("file:"+path));
|
||||
} catch (MalformedURLException e) {
|
||||
new DebugException("Fehler im Classpath auf diesem System");
|
||||
var clazz = Class.forName(info.getName());
|
||||
res.add(clazz);
|
||||
} catch (ClassNotFoundException ignored) {}
|
||||
}
|
||||
}
|
||||
URL[] urls = urlList.toArray(new URL[0]);
|
||||
classLoadersList.add(new URLClassLoader(urls, DirectoryClassLoader.getSystemClassLoader()));
|
||||
*/
|
||||
Reflections reflections = new Reflections(new ConfigurationBuilder()
|
||||
.setScanners(new SubTypesScanner(false /* don't exclude Object.class */), new ResourcesScanner())
|
||||
.setUrls(urls)
|
||||
.filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix(packageName))));
|
||||
};
|
||||
|
||||
Set<Class<?>> classes = reflections.getSubTypesOf(Object.class);
|
||||
|
||||
return classes;
|
||||
}
|
||||
|
||||
public Set<Class<?>> getAllAvailableClasses(){
|
||||
Reflections reflections = new Reflections(new ConfigurationBuilder()
|
||||
.setScanners(new SubTypesScanner(false /* don't exclude Object.class */), new ResourcesScanner())
|
||||
.setUrls(urls));
|
||||
|
||||
Set<Class<?>> classes = reflections.getSubTypesOf(Object.class);
|
||||
|
||||
return classes;
|
||||
return res;
|
||||
}
|
||||
|
||||
public Map<String, Integer> getClassNames(String packageName){
|
||||
|
@ -1,5 +1,6 @@
|
||||
package de.dhbwstuttgart.parser.SyntaxTreeGenerator;
|
||||
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
import de.dhbwstuttgart.exceptions.DebugException;
|
||||
import de.dhbwstuttgart.parser.NullToken;
|
||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||
@ -25,8 +26,8 @@ public class FCGenerator {
|
||||
*
|
||||
* @param availableClasses - Alle geparsten Klassen
|
||||
*/
|
||||
public static Set<UnifyPair> toUnifyFC(Collection<ClassOrInterface> availableClasses, ClassLoader classLoader) throws ClassNotFoundException {
|
||||
return toFC(availableClasses, classLoader).stream().map(t -> UnifyTypeFactory.convert(t)).collect(Collectors.toSet());
|
||||
public static Set<UnifyPair> toUnifyFC(JavaTXCompiler compiler, Collection<ClassOrInterface> availableClasses, ClassLoader classLoader) throws ClassNotFoundException {
|
||||
return toFC(availableClasses, classLoader).stream().map(t -> UnifyTypeFactory.convert(compiler, t)).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
public static Set<Pair> toFC(Collection<ClassOrInterface> availableClasses, ClassLoader classLoader) throws ClassNotFoundException {
|
||||
@ -157,7 +158,8 @@ public class FCGenerator {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tauscht die GTVs in einem Typ gegen die entsprechenden Typen in der übergebenen Map aus.
|
||||
* Tauscht die GTVs in einem Typ gegen die entsprechenden Typen in der übergebenen Map aus auf der direkten Argumentebene.
|
||||
* Hier sind keine Wildcards zulässig
|
||||
*/
|
||||
private static class TypeExchanger implements TypeVisitor<RefTypeOrTPHOrWildcardOrGeneric>{
|
||||
|
||||
@ -171,7 +173,7 @@ public class FCGenerator {
|
||||
public RefTypeOrTPHOrWildcardOrGeneric visit(RefType refType) {
|
||||
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
|
||||
for(RefTypeOrTPHOrWildcardOrGeneric param : refType.getParaList()){
|
||||
params.add(param.acceptTV(this));
|
||||
params.add(param.acceptTV(new TypeExchangerInner(gtvs)));
|
||||
}
|
||||
RefTypeOrTPHOrWildcardOrGeneric ret = new RefType(refType.getName(), params, new NullToken());
|
||||
return ret;
|
||||
@ -200,4 +202,51 @@ public class FCGenerator {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tauscht die GTVs in einem Typ gegen die entsprechenden Typen in der übergebenen Map aus auf den Argumenten der Argumente.
|
||||
* Hier sind Wildcards zulässig
|
||||
*/
|
||||
private static class TypeExchangerInner implements TypeVisitor<RefTypeOrTPHOrWildcardOrGeneric>{
|
||||
|
||||
private final HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs;
|
||||
|
||||
TypeExchangerInner(HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs){
|
||||
this.gtvs = gtvs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RefTypeOrTPHOrWildcardOrGeneric visit(RefType refType) {
|
||||
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
|
||||
for(RefTypeOrTPHOrWildcardOrGeneric param : refType.getParaList()){
|
||||
params.add(param.acceptTV(this));
|
||||
}
|
||||
RefTypeOrTPHOrWildcardOrGeneric ret = new RefType(refType.getName(), params, new NullToken());
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RefTypeOrTPHOrWildcardOrGeneric visit(SuperWildcardType superWildcardType) {
|
||||
return superWildcardType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RefTypeOrTPHOrWildcardOrGeneric visit(TypePlaceholder typePlaceholder) {
|
||||
throw new DebugException("Dieser Fall darf nicht auftreten");
|
||||
}
|
||||
|
||||
@Override
|
||||
public RefTypeOrTPHOrWildcardOrGeneric visit(ExtendsWildcardType extendsWildcardType) {
|
||||
return extendsWildcardType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RefTypeOrTPHOrWildcardOrGeneric visit(GenericRefType genericRefType) {
|
||||
if(! gtvs.containsKey(genericRefType.getParsedName()))
|
||||
throw new DebugException("Dieser Fall darf nicht auftreten");
|
||||
return gtvs.get(genericRefType.getParsedName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -279,7 +279,8 @@ public class StatementGenerator {
|
||||
|
||||
if (!Objects.isNull(creator.classCreatorRest())) {
|
||||
ArgumentList args = convertArguments(creator.classCreatorRest().arguments().expressionList());
|
||||
ArrayList<RefTypeOrTPHOrWildcardOrGeneric> argTypes = args.getArguments().stream().map(x -> TypePlaceholder.fresh(creator.getStart())).collect(Collectors.toCollection(ArrayList::new));
|
||||
ArrayList<TypePlaceholder> argTypes = args.getArguments().stream().map(x -> TypePlaceholder.fresh(creator.getStart())).collect(Collectors.toCollection(ArrayList::new));
|
||||
argTypes.add(TypePlaceholder.fresh(creator.getStart())); // return type
|
||||
Statement ret = new NewClass(newclass, args, null, argTypes, creator.getStart());
|
||||
ret.setStatement();
|
||||
return ret;
|
||||
@ -310,7 +311,7 @@ public class StatementGenerator {
|
||||
IdentifierContext identifier = innercreator.identifier();
|
||||
RefType newclass = (RefType) TypeGenerator.convertTypeName(identifier.getText(), genericArgs, identifier.getStart(), reg, generics);
|
||||
ArgumentList args = convertArguments(innercreator.classCreatorRest().arguments().expressionList());
|
||||
ArrayList<RefTypeOrTPHOrWildcardOrGeneric> argTypes = args.getArguments().stream().map(x -> TypePlaceholder.fresh(innercreator.getStart())).collect(Collectors.toCollection(ArrayList::new));
|
||||
ArrayList<TypePlaceholder> argTypes = args.getArguments().stream().map(x -> TypePlaceholder.fresh(innercreator.getStart())).collect(Collectors.toCollection(ArrayList::new));
|
||||
Statement ret = new NewClass(newclass, args, null, argTypes, innercreator.getStart());
|
||||
ret.setStatement();
|
||||
return ret;
|
||||
@ -596,8 +597,12 @@ public class StatementGenerator {
|
||||
}
|
||||
|
||||
private Statement convert(Java17Parser.ContinuestmtContext stmt) {
|
||||
// TODO
|
||||
throw new NotImplementedException();
|
||||
Token offset = stmt.getStart();
|
||||
if (!Objects.isNull(stmt.identifier())) {
|
||||
return new Continue(localVars.get(stmt.identifier().getText()), offset);
|
||||
} else {
|
||||
return new Continue(TypePlaceholder.fresh(offset), offset);
|
||||
}
|
||||
}
|
||||
|
||||
private Statement convert(Java17Parser.SemistmtContext stmt) {
|
||||
@ -692,6 +697,7 @@ public class StatementGenerator {
|
||||
if (!Objects.isNull(expr.methodCall())) {
|
||||
return convert(expr.methodCall(), expr.expression(), offset);
|
||||
} else if (!Objects.isNull(expr.identifier())) {
|
||||
// FIXME This is not the right way of handling any of this
|
||||
return generateLocalOrFieldVarOrClassName(expr.getText(), offset);
|
||||
} else {
|
||||
// Für alle anderen Optionen, wie Feldzugriff, Aufrufe von super oder explizite
|
||||
@ -711,7 +717,7 @@ public class StatementGenerator {
|
||||
}
|
||||
|
||||
ArgumentList argumentList = convertArguments(expr.expressionList());
|
||||
ArrayList<RefTypeOrTPHOrWildcardOrGeneric> signature = argumentList.getArguments().stream().map(x -> (RefTypeOrTPHOrWildcardOrGeneric) TypePlaceholder.fresh(offset)).collect(Collectors.toCollection(ArrayList::new));
|
||||
ArrayList<TypePlaceholder> signature = argumentList.getArguments().stream().map(x -> TypePlaceholder.fresh(offset)).collect(Collectors.toCollection(ArrayList::new));
|
||||
signature.add(TypePlaceholder.fresh(offset)); // return type
|
||||
|
||||
MethodCall ret;
|
||||
@ -736,7 +742,7 @@ public class StatementGenerator {
|
||||
name = expr.SUPER().getText();
|
||||
}
|
||||
ArgumentList argumentList = convertArguments(expr.expressionList());
|
||||
ArrayList<RefTypeOrTPHOrWildcardOrGeneric> signature = argumentList.getArguments().stream().map(x -> (RefTypeOrTPHOrWildcardOrGeneric) TypePlaceholder.fresh(offset)).collect(Collectors.toCollection(ArrayList::new));
|
||||
ArrayList<TypePlaceholder> signature = argumentList.getArguments().stream().map(x -> TypePlaceholder.fresh(offset)).collect(Collectors.toCollection(ArrayList::new));
|
||||
signature.add(TypePlaceholder.fresh(offset)); // return type
|
||||
MethodCall ret = new MethodCall(TypePlaceholder.fresh(offset), getReceiver(receiver), name, argumentList, TypePlaceholder.fresh(offset), signature, offset);
|
||||
ret.setStatement();
|
||||
@ -774,6 +780,7 @@ public class StatementGenerator {
|
||||
* @return
|
||||
*/
|
||||
private Expression generateLocalOrFieldVarOrClassName(String expression, Token offset) {
|
||||
// FIXME Why does this take a String argument???
|
||||
String[] parts = expression.split("\\.");
|
||||
if (parts.length < 2) {
|
||||
// Check for localVar:
|
||||
@ -803,6 +810,7 @@ public class StatementGenerator {
|
||||
// Check for Classname:
|
||||
if (reg.contains(whole)) {
|
||||
receiver = generateStaticClassName(whole, offset);
|
||||
break;
|
||||
}
|
||||
whole += ".";
|
||||
}
|
||||
@ -831,7 +839,13 @@ public class StatementGenerator {
|
||||
}
|
||||
|
||||
private Expression convert(Java17Parser.ConditionalassignexpressionContext expression) {
|
||||
throw new NotImplementedException();
|
||||
return new Ternary(TypePlaceholder.fresh(
|
||||
expression.getStart()),
|
||||
convert(expression.expression(0)),
|
||||
convert(expression.expression(1)),
|
||||
convert(expression.expression(2)),
|
||||
expression.getStart()
|
||||
);
|
||||
}
|
||||
|
||||
private Expression convert(Java17Parser.OrexpressionContext expression) {
|
||||
@ -884,15 +898,15 @@ public class StatementGenerator {
|
||||
}
|
||||
|
||||
private Expression convert(Java17Parser.BitwiseorexpressionContext expression) {
|
||||
throw new NotImplementedException();
|
||||
return new BinaryExpr(BinaryExpr.Operator.OR, TypePlaceholder.fresh(expression.getStart()), convert(expression.expression(0)), convert(expression.expression(1)), expression.getStart());
|
||||
}
|
||||
|
||||
private Expression convert(Java17Parser.BitwisexorexpressionContext expression) {
|
||||
throw new NotImplementedException();
|
||||
return new BinaryExpr(BinaryExpr.Operator.XOR, TypePlaceholder.fresh(expression.getStart()), convert(expression.expression(0)), convert(expression.expression(1)), expression.getStart());
|
||||
}
|
||||
|
||||
private Expression convert(Java17Parser.BitwiseandexpressionContext expression) {
|
||||
throw new NotImplementedException();
|
||||
return new BinaryExpr(BinaryExpr.Operator.AND, TypePlaceholder.fresh(expression.getStart()), convert(expression.expression(0)), convert(expression.expression(1)), expression.getStart());
|
||||
}
|
||||
|
||||
private Expression convert(Java17Parser.EqualityexpressionContext expression) {
|
||||
@ -957,6 +971,8 @@ public class StatementGenerator {
|
||||
return BinaryExpr.Operator.EQUAL;
|
||||
} else if (operator.equals("!=")) {
|
||||
return BinaryExpr.Operator.NOTEQUAL;
|
||||
} else if (operator.equals("%")) {
|
||||
return BinaryExpr.Operator.MOD;
|
||||
} else {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
@ -995,6 +1011,9 @@ public class StatementGenerator {
|
||||
ret = new UnaryExpr(UnaryExpr.Operation.PREDECREMENT, expr, TypePlaceholder.fresh(op), op);
|
||||
ret.setStatement();
|
||||
return ret;
|
||||
} else if (op.getText().equals("!")) {
|
||||
ret = new UnaryExpr(UnaryExpr.Operation.NOT, expr, TypePlaceholder.fresh(op), op);
|
||||
return ret;
|
||||
} else {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
@ -1028,7 +1047,7 @@ public class StatementGenerator {
|
||||
case PrimaryThisContext primthis:
|
||||
return new This(primthis.getStart());
|
||||
case PrimarySuperContext primsuper:
|
||||
throw new NotImplementedException();
|
||||
return new Super(primsuper.getStart());
|
||||
case PrimaryLiteralContext primliteral:
|
||||
return convert(primliteral.literal());
|
||||
case PrimaryIdentifierContext primidentifier:
|
||||
@ -1043,10 +1062,17 @@ public class StatementGenerator {
|
||||
private Expression convert(Java17Parser.LiteralContext literal) {
|
||||
switch (literal) {
|
||||
case IntLiteralContext intliteral:
|
||||
Number value = Integer.parseInt(intliteral.getText());
|
||||
Number value;
|
||||
if (intliteral.getText().endsWith("l") || intliteral.getText().endsWith("L"))
|
||||
value = Long.parseLong(intliteral.getText().substring(0, intliteral.getText().length() - 1));
|
||||
else value = Integer.parseInt(intliteral.getText());
|
||||
return new Literal(TypePlaceholder.fresh(literal.getStart()), value, intliteral.getStart());
|
||||
case FltLiteralContext floatliteral:
|
||||
value = Double.parseDouble(floatliteral.getText());
|
||||
if (floatliteral.getText().endsWith("f") || floatliteral.getText().endsWith("F"))
|
||||
value = Float.parseFloat(floatliteral.getText().substring(0, floatliteral.getText().length() - 1));
|
||||
else if (floatliteral.getText().endsWith("d") || floatliteral.getText().endsWith("D"))
|
||||
value = Double.parseDouble(floatliteral.getText().substring(0, floatliteral.getText().length() - 1));
|
||||
else value = Double.parseDouble(floatliteral.getText());
|
||||
return new Literal(TypePlaceholder.fresh(literal.getStart()), value, floatliteral.getStart());
|
||||
case CharLiteralContext charliteral:
|
||||
RefType type = new RefType(reg.getName("java.lang.Character"), charliteral.getStart());
|
||||
|
@ -34,6 +34,11 @@ public class SyntacticSugar {
|
||||
public void visit(ReturnVoid aReturn) {
|
||||
hasReturn = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(LambdaExpression le) {
|
||||
//PL 2024-04-09 Do nothing, as in a LambdaExpression a return could be
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasReturn(Block block) {
|
||||
|
@ -71,10 +71,6 @@ import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||
import de.dhbwstuttgart.syntaxtree.type.Void;
|
||||
import de.dhbwstuttgart.typeinference.constraints.GenericsResolver;
|
||||
import javassist.compiler.SyntaxError;
|
||||
|
||||
import javax.swing.text.html.Option;
|
||||
|
||||
public class SyntaxTreeGenerator {
|
||||
private JavaClassRegistry reg;
|
||||
@ -258,7 +254,10 @@ public class SyntaxTreeGenerator {
|
||||
List<RefType> implementedInterfaces = new ArrayList<>();
|
||||
List<Pattern> constructorParameters = new ArrayList<>();
|
||||
List<Statement> constructorStatements = new ArrayList<>();
|
||||
for (RecordComponentContext component : recordDeclaration.recordHeader().recordComponentList().recordComponent()) {
|
||||
|
||||
List<Java17Parser.RecordComponentContext> components = recordDeclaration.recordHeader().recordComponentList() != null ?
|
||||
recordDeclaration.recordHeader().recordComponentList().recordComponent(): List.of();
|
||||
for (RecordComponentContext component : components) {
|
||||
int fieldmodifiers = allmodifiers.get("private") + allmodifiers.get("final");
|
||||
String fieldname = component.identifier().getText();
|
||||
Token fieldoffset = component.getStart();
|
||||
@ -333,7 +332,7 @@ public class SyntaxTreeGenerator {
|
||||
|
||||
private ClassOrInterface convertInterface(Java17Parser.InterfaceDeclarationContext ctx, int modifiers) {
|
||||
this.superClass = new RefType(new JavaClassName("java.lang.Object"), new NullToken());
|
||||
String className = this.pkgName.length() > 0 ? this.pkgName + "." : "" + ctx.identifier().getText();
|
||||
String className = (this.pkgName.length() > 0 ? this.pkgName + "." : "") + ctx.identifier().getText();
|
||||
JavaClassName name = reg.getName(className); // Holt den Package Namen mit dazu
|
||||
if (!name.toString().equals(className)) { // Kommt die Klasse schon in einem anderen Package vor?
|
||||
throw new TypeinferenceException("Name " + className + " bereits vorhanden in " + reg.getName(className).toString(), ctx.getStart());
|
||||
@ -452,8 +451,8 @@ public class SyntaxTreeGenerator {
|
||||
protected static Block prepareBlock(Block constructorBlock, RefType superClass) {
|
||||
List<Statement> statements = constructorBlock.getStatements();
|
||||
if (statements.isEmpty() || !(statements.get(0) instanceof SuperCall || statements.get(0) instanceof ThisCall)) {
|
||||
var signature = new ArrayList<RefTypeOrTPHOrWildcardOrGeneric>();
|
||||
signature.add(new Void(new NullToken()));
|
||||
var signature = new ArrayList<TypePlaceholder>();
|
||||
signature.add(TypePlaceholder.fresh(new NullToken()));
|
||||
statements.add(0, new SuperCall(superClass, signature, constructorBlock.getOffset()));
|
||||
}
|
||||
/* statements.addAll(fieldInitializations); geloescht PL 2018-11-24 */
|
||||
|
@ -68,6 +68,8 @@ public class TypeGenerator {
|
||||
return new RefType(ASTFactory.createClass(Integer.class).getClassName(), typeContext.getStart());
|
||||
case "double":
|
||||
return new RefType(ASTFactory.createClass(Double.class).getClassName(), typeContext.getStart());
|
||||
case "float":
|
||||
return new RefType(ASTFactory.createClass(Float.class).getClassName(), typeContext.getStart());
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
@ -140,7 +140,8 @@ public class GatherNames {
|
||||
if (importDeclCtx.MUL() == null) {
|
||||
var name = importDeclCtx.qualifiedName().getText();
|
||||
var className = new JavaClassName(name);
|
||||
if (compiler.loadJavaTXClass(className)) {
|
||||
var clazz = compiler.loadJavaTXClass(className);
|
||||
if (clazz != null) {
|
||||
ret.put(name, compiler.classRegistry.getNumberOfGenerics(name));
|
||||
} else {
|
||||
Class<?> cl = compiler.getClassLoader().loadClass(name);
|
||||
|
@ -236,6 +236,11 @@ public abstract class AbstractASTWalker implements ASTVisitor {
|
||||
aBreak.accept(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Continue aContinue) {
|
||||
aContinue.accept(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(StaticClassName staticClassName) {
|
||||
|
||||
@ -332,4 +337,11 @@ public abstract class AbstractASTWalker implements ASTVisitor {
|
||||
public void visit(GuardedPattern aGuardedPattern) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Ternary ternary) {
|
||||
ternary.cond.accept(this);
|
||||
ternary.iftrue.accept(this);
|
||||
ternary.iffalse.accept(this);
|
||||
}
|
||||
}
|
||||
|
@ -9,10 +9,7 @@ import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Stellt jede Art von Klasse dar. Auch abstrakte Klassen und Interfaces
|
||||
@ -128,7 +125,6 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
|
||||
public List<Method> getMethods() {
|
||||
return this.methods;
|
||||
}
|
||||
|
||||
/*
|
||||
* public RefType getType() { return generateTypeOfClass(this.getClassName(), this.getGenerics(), this.getOffset()); }
|
||||
*/
|
||||
@ -189,4 +185,15 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
|
||||
return this.name.toString() + this.genericClassParameters.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof ClassOrInterface other)) return false;
|
||||
return Objects.equals(name, other.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package de.dhbwstuttgart.syntaxtree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Objects;
|
||||
|
||||
import de.dhbwstuttgart.parser.NullToken;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||
@ -32,6 +33,7 @@ public class Method extends SyntaxTreeNode implements IItemWithOffset, TypeScope
|
||||
private GenericDeclarationList generics;
|
||||
private final RefTypeOrTPHOrWildcardOrGeneric returnType;
|
||||
public final Boolean isInherited;
|
||||
public final Boolean isImplemented;
|
||||
|
||||
/*
|
||||
* its Constraints
|
||||
@ -49,10 +51,11 @@ public class Method extends SyntaxTreeNode implements IItemWithOffset, TypeScope
|
||||
this.block = block;
|
||||
this.generics = gtvDeclarations;
|
||||
this.isInherited = false;
|
||||
this.isImplemented = false;
|
||||
}
|
||||
|
||||
public Method(int modifier, String name, RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList parameterList, Block block,
|
||||
GenericDeclarationList gtvDeclarations, Token offset, Boolean isInherited) {
|
||||
GenericDeclarationList gtvDeclarations, Token offset, Boolean isInherited, Boolean isOverridden) {
|
||||
super(offset);
|
||||
this.name = name;
|
||||
this.modifier = modifier;
|
||||
@ -61,6 +64,7 @@ public class Method extends SyntaxTreeNode implements IItemWithOffset, TypeScope
|
||||
this.block = block;
|
||||
this.generics = gtvDeclarations;
|
||||
this.isInherited = isInherited;
|
||||
this.isImplemented = isOverridden;
|
||||
}
|
||||
|
||||
public ParameterList getParameterList() {
|
||||
@ -93,4 +97,23 @@ public class Method extends SyntaxTreeNode implements IItemWithOffset, TypeScope
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Method method = (Method) o;
|
||||
return Objects.equals(name, method.name) && Objects.equals(parameterlist, method.parameterlist) && Objects.equals(returnType, method.returnType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name, parameterlist, returnType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,8 @@ public class SourceFile extends SyntaxTreeNode {
|
||||
public final List<ClassOrInterface> KlassenVektor;
|
||||
public final Set<JavaClassName> imports;
|
||||
|
||||
private boolean isGenerated;
|
||||
|
||||
public List<ClassOrInterface> availableClasses = new ArrayList<>();
|
||||
|
||||
/**
|
||||
@ -38,6 +40,18 @@ public class SourceFile extends SyntaxTreeNode {
|
||||
this.imports = new HashSet<>(sf.imports);
|
||||
}
|
||||
|
||||
public void setPackageName(String packageName) {
|
||||
this.pkgName = packageName;
|
||||
}
|
||||
|
||||
public void setGenerated() {
|
||||
this.isGenerated = true;
|
||||
}
|
||||
|
||||
public boolean isGenerated() {
|
||||
return this.isGenerated;
|
||||
}
|
||||
|
||||
public String getPkgName() {
|
||||
return this.pkgName;
|
||||
}
|
||||
|
@ -53,6 +53,8 @@ public interface StatementVisitor {
|
||||
|
||||
void visit(Break aBreak);
|
||||
|
||||
void visit(Continue aContinue);
|
||||
|
||||
void visit(Yield aYield);
|
||||
|
||||
void visit(StaticClassName staticClassName);
|
||||
@ -80,4 +82,6 @@ public interface StatementVisitor {
|
||||
void visit(Literal literal);
|
||||
|
||||
void visit(Throw aThrow);
|
||||
|
||||
void visit(Ternary ternary);
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ public class ASTFactory {
|
||||
private static final HashMap<java.lang.Class, ClassOrInterface> cache = new HashMap<>();
|
||||
|
||||
public static ClassOrInterface createClass(java.lang.Class jreClass) {
|
||||
System.out.println(jreClass);
|
||||
if (cache.containsKey(jreClass))
|
||||
return cache.get(jreClass);
|
||||
|
||||
@ -105,11 +106,46 @@ public class ASTFactory {
|
||||
allInheritedMethods.removeAll(allDeclaredMethods);
|
||||
for (java.lang.reflect.Method method : allDeclaredMethods) {
|
||||
var signature = methodSignatures.get(new Pair<>(method.getName(), org.objectweb.asm.Type.getMethodDescriptor(method)));
|
||||
methoden.add(createMethod(method, signature, jreClass, false));
|
||||
if (jreClass.getSuperclass()==null) {
|
||||
methoden.add(createMethod(method, signature, jreClass, false, false));
|
||||
}
|
||||
else {
|
||||
Boolean isImplemented = false;
|
||||
isImplemented = Arrays.stream(jreClass.getInterfaces()).
|
||||
reduce(false,
|
||||
(x,y) -> {
|
||||
try {
|
||||
y.getDeclaredMethod(method.getName(), method.getParameterTypes());
|
||||
return true;
|
||||
}
|
||||
catch (java.lang.NoSuchMethodException e) {
|
||||
return false;
|
||||
}},
|
||||
(x,y) -> (x || y)
|
||||
);
|
||||
|
||||
if (isImplemented) {
|
||||
methoden.add(createMethod(method, signature, jreClass, false, true));
|
||||
}
|
||||
else {
|
||||
if (Modifier.isAbstract(jreClass.getSuperclass().getModifiers())) {
|
||||
try {
|
||||
jreClass.getSuperclass().getDeclaredMethod(method.getName(), method.getParameterTypes());
|
||||
methoden.add(createMethod(method, signature, jreClass, false, true));
|
||||
}
|
||||
catch (java.lang.NoSuchMethodException e) {
|
||||
methoden.add(createMethod(method, signature, jreClass, false, false));
|
||||
}
|
||||
}
|
||||
else {
|
||||
methoden.add(createMethod(method, signature, jreClass, false, false));
|
||||
}
|
||||
|
||||
}
|
||||
}}
|
||||
for (java.lang.reflect.Method method : allInheritedMethods) {
|
||||
var signature = methodSignatures.get(new Pair<>(method.getName(), org.objectweb.asm.Type.getMethodDescriptor(method)));
|
||||
methoden.add(createMethod(method, signature, jreClass, true));
|
||||
methoden.add(createMethod(method, signature, jreClass, true, false));
|
||||
}
|
||||
List<Field> felder = new ArrayList<>();
|
||||
for (java.lang.reflect.Field field : jreClass.getDeclaredFields()) {
|
||||
@ -138,6 +174,7 @@ public class ASTFactory {
|
||||
superClass = (RefType) createType(java.lang.Object.class);
|
||||
}
|
||||
List<RefType> implementedInterfaces = new ArrayList<>();
|
||||
System.out.println(jreClass);
|
||||
for (Type jreInterface : jreClass.getGenericInterfaces()) {
|
||||
implementedInterfaces.add((RefType) createType(jreInterface));
|
||||
}
|
||||
@ -192,7 +229,7 @@ public class ASTFactory {
|
||||
return Optional.of(new de.dhbwstuttgart.syntaxtree.Constructor(modifier, name, returnType, parameterList, block, gtvDeclarations, offset /* , new ArrayList<>() geloescht PL 2018-11-24 */));
|
||||
}
|
||||
|
||||
public static Method createMethod(java.lang.reflect.Method jreMethod, String signature, java.lang.Class inClass, Boolean isInherited) {
|
||||
public static Method createMethod(java.lang.reflect.Method jreMethod, String signature, java.lang.Class inClass, Boolean isInherited, Boolean isImplemented) {
|
||||
String name = jreMethod.getName();
|
||||
RefTypeOrTPHOrWildcardOrGeneric returnType;
|
||||
Type jreRetType;
|
||||
@ -218,7 +255,7 @@ public class ASTFactory {
|
||||
GenericDeclarationList gtvDeclarations = createGenerics(jreMethod.getTypeParameters(), inClass, jreMethod.getName(), signature);
|
||||
Token offset = new NullToken();
|
||||
|
||||
return new Method(jreMethod.getModifiers(), name, returnType, parameterList, block, gtvDeclarations, offset, isInherited);
|
||||
return new Method(jreMethod.getModifiers(), name, returnType, parameterList, block, gtvDeclarations, offset, isInherited, isImplemented);
|
||||
}
|
||||
|
||||
public static GenericDeclarationList createGenerics(TypeVariable[] typeParameters, Class context, String methodName, String signature) {
|
||||
@ -368,6 +405,8 @@ public class ASTFactory {
|
||||
return new RefType(new JavaClassName("java.lang.Character"), new ArrayList<>(), new NullToken(), true);
|
||||
} else if (type.getTypeName().equals("short")) {
|
||||
return new RefType(new JavaClassName("java.lang.Short"), new ArrayList<>(), new NullToken(), true);
|
||||
} else if (type.getTypeName().equals("float")) {
|
||||
return new RefType(new JavaClassName("java.lang.Float"), new ArrayList<>(), new NullToken(), true);
|
||||
} else if (type.getTypeName().equals("double")) {
|
||||
return new RefType(new JavaClassName("java.lang.Double"), new ArrayList<>(), new NullToken(), true);
|
||||
} else if (type.getTypeName().equals("long")) {
|
||||
|
@ -1,17 +1,21 @@
|
||||
package de.dhbwstuttgart.syntaxtree.factory;
|
||||
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||
import de.dhbwstuttgart.parser.NullToken;
|
||||
import de.dhbwstuttgart.parser.SourceLoc;
|
||||
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.FCGenerator;
|
||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
|
||||
import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
|
||||
import de.dhbwstuttgart.syntaxtree.type.*;
|
||||
import de.dhbwstuttgart.syntaxtree.type.Void;
|
||||
import de.dhbwstuttgart.syntaxtree.type.WildcardType;
|
||||
@ -29,7 +33,7 @@ public class UnifyTypeFactory {
|
||||
|
||||
private static ArrayList<PlaceholderType> PLACEHOLDERS = new ArrayList<>();
|
||||
|
||||
public static FiniteClosure generateFC(List<ClassOrInterface> fromClasses, Writer logFile, ClassLoader classLoader) throws ClassNotFoundException {
|
||||
public static FiniteClosure generateFC(List<ClassOrInterface> fromClasses, Writer logFile, ClassLoader classLoader, JavaTXCompiler compiler) throws ClassNotFoundException {
|
||||
/*
|
||||
Die transitive Hülle muss funktionieren.
|
||||
Man darf schreiben List<A> extends AL<A>
|
||||
@ -40,7 +44,7 @@ public class UnifyTypeFactory {
|
||||
Generell dürfen sie immer die gleichen Namen haben.
|
||||
TODO: die transitive Hülle bilden
|
||||
*/
|
||||
return new FiniteClosure(FCGenerator.toUnifyFC(fromClasses, classLoader), logFile);
|
||||
return new FiniteClosure(FCGenerator.toUnifyFC(compiler, fromClasses, classLoader), logFile, compiler);
|
||||
}
|
||||
|
||||
public static UnifyPair generateSmallerPair(UnifyType tl, UnifyType tr, SourceLoc location){
|
||||
@ -63,23 +67,23 @@ public class UnifyTypeFactory {
|
||||
* Convert from
|
||||
* ASTType -> UnifyType
|
||||
*/
|
||||
public static UnifyType convert(RefTypeOrTPHOrWildcardOrGeneric t, Boolean innerType){
|
||||
public static UnifyType convert(JavaTXCompiler compiler, RefTypeOrTPHOrWildcardOrGeneric t, Boolean innerType){
|
||||
if (t instanceof GenericRefType){
|
||||
return UnifyTypeFactory.convert((GenericRefType)t, innerType);
|
||||
return UnifyTypeFactory.convert(compiler, (GenericRefType)t, innerType);
|
||||
} else if (t instanceof TypePlaceholder){
|
||||
return UnifyTypeFactory.convert((TypePlaceholder)t, innerType);
|
||||
return UnifyTypeFactory.convert(compiler, (TypePlaceholder)t, innerType);
|
||||
} else if (t instanceof ExtendsWildcardType){
|
||||
return UnifyTypeFactory.convert((ExtendsWildcardType)t, innerType);
|
||||
return UnifyTypeFactory.convert(compiler, (ExtendsWildcardType)t, innerType);
|
||||
} else if (t instanceof SuperWildcardType) {
|
||||
return UnifyTypeFactory.convert((SuperWildcardType)t, innerType);
|
||||
return UnifyTypeFactory.convert(compiler, (SuperWildcardType) t, innerType);
|
||||
} else if (t instanceof RefType){
|
||||
return UnifyTypeFactory.convert((RefType)t, innerType);
|
||||
return UnifyTypeFactory.convert(compiler, (RefType)t, innerType);
|
||||
}
|
||||
//Es wurde versucht ein Typ umzuwandeln, welcher noch nicht von der Factory abgedeckt ist
|
||||
throw new NotImplementedException("Der Typ "+t+" kann nicht umgewandelt werden");
|
||||
}
|
||||
|
||||
public static UnifyType convert(RefType t, Boolean innerType){
|
||||
public static UnifyType convert(JavaTXCompiler compiler, RefType t, Boolean innerType){
|
||||
//Check if it is a FunN Type:
|
||||
Pattern p = Pattern.compile("Fun(\\d+)[$][$]");
|
||||
Matcher m = p.matcher(t.getName().toString());
|
||||
@ -87,35 +91,41 @@ public class UnifyTypeFactory {
|
||||
if(b){
|
||||
Integer N = Integer.valueOf(m.group(1));
|
||||
if((N + 1) == t.getParaList().size()){
|
||||
return convertFunN(t.getParaList(), false);
|
||||
return convertFunN(compiler, t.getParaList(), false);
|
||||
}
|
||||
}
|
||||
UnifyType ret;
|
||||
if(t.getParaList() != null && t.getParaList().size() > 0){
|
||||
List<UnifyType> params = new ArrayList<>();
|
||||
if (t.getParaList() != null) {
|
||||
for (RefTypeOrTPHOrWildcardOrGeneric pT : t.getParaList()) {
|
||||
params.add(UnifyTypeFactory.convert(pT, true));
|
||||
params.add(UnifyTypeFactory.convert(compiler, pT, true));
|
||||
}
|
||||
ret = new ReferenceType(t.getName().toString(),new TypeParams(params));
|
||||
}else{
|
||||
ret = new ReferenceType(t.getName().toString(), false);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static UnifyType convertFunN(List<RefTypeOrTPHOrWildcardOrGeneric> paraList, Boolean innerType){
|
||||
var clazz = compiler.getClass(t.getName());
|
||||
if (clazz != null && clazz.isInterface() && clazz.isFunctionalInterface()) {
|
||||
var method = clazz.getMethods().stream().filter(x -> Modifier.isAbstract(x.modifier)).findFirst().orElseThrow();
|
||||
var methodParams = method.getParameterList().getFormalparalist().stream().map(x -> convert(compiler, x.getType(), true)).toList();
|
||||
var generics = StreamSupport.stream(clazz.getGenerics().spliterator(), false).map(GenericTypeVar::getName).toList();
|
||||
return new FunInterfaceType(t.getName().toString(), new TypeParams(params), methodParams, convert(compiler, method.getReturnType(), true), generics);
|
||||
}
|
||||
|
||||
return new ReferenceType(t.getName().toString(),new TypeParams(params));
|
||||
}
|
||||
|
||||
public static UnifyType convertFunN(JavaTXCompiler compiler, List<RefTypeOrTPHOrWildcardOrGeneric> paraList, Boolean innerType){
|
||||
UnifyType ret;
|
||||
List<UnifyType> params = new ArrayList<>();
|
||||
if(paraList != null && paraList.size() > 0){
|
||||
for(RefTypeOrTPHOrWildcardOrGeneric pT : paraList){
|
||||
params.add(UnifyTypeFactory.convert(pT, false));
|
||||
params.add(UnifyTypeFactory.convert(compiler, pT, false));
|
||||
}
|
||||
}
|
||||
ret = FunNType.getFunNType(new TypeParams(params));
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static UnifyType convert(TypePlaceholder tph, Boolean innerType){
|
||||
public static UnifyType convert(JavaTXCompiler compiler, TypePlaceholder tph, Boolean innerType){
|
||||
if (tph.getName().equals("AFR")) {
|
||||
System.out.println("XXX"+innerType);
|
||||
}
|
||||
@ -135,21 +145,21 @@ public class UnifyTypeFactory {
|
||||
}
|
||||
}
|
||||
|
||||
public static UnifyType convert(GenericRefType t, Boolean innerType){
|
||||
public static UnifyType convert(JavaTXCompiler compiler, GenericRefType t, Boolean innerType){
|
||||
return new ReferenceType(t.getParsedName(), true);
|
||||
}
|
||||
|
||||
public static UnifyType convert(WildcardType t, Boolean innerType){
|
||||
public static UnifyType convert(JavaTXCompiler compiler, WildcardType t, Boolean innerType){
|
||||
if(t.isExtends())
|
||||
return new ExtendsType(UnifyTypeFactory.convert(t.getInnerType(), false));
|
||||
return new ExtendsType(UnifyTypeFactory.convert(compiler, t.getInnerType(), false));
|
||||
else if(t.isSuper())
|
||||
return new SuperType(UnifyTypeFactory.convert(t.getInnerType(), false));
|
||||
return new SuperType(UnifyTypeFactory.convert(compiler, t.getInnerType(), false));
|
||||
else throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
||||
public static ConstraintSet<UnifyPair> convert(ConstraintSet<Pair> constraints) {
|
||||
return constraints.map(UnifyTypeFactory::convert);
|
||||
public static ConstraintSet<UnifyPair> convert(JavaTXCompiler compiler, ConstraintSet<Pair> constraints) {
|
||||
return constraints.map(c -> UnifyTypeFactory.convert(compiler, c));
|
||||
}
|
||||
|
||||
//NEVER USED
|
||||
@ -160,23 +170,23 @@ public class UnifyTypeFactory {
|
||||
// return unifyPairConstraint;
|
||||
//}
|
||||
|
||||
public static UnifyPair convert(Pair p) {
|
||||
public static UnifyPair convert(JavaTXCompiler compiler, Pair p) {
|
||||
UnifyPair ret = null;
|
||||
if(p.GetOperator().equals(PairOperator.SMALLERDOT)) {
|
||||
ret = generateSmallerDotPair(UnifyTypeFactory.convert(p.TA1, false)
|
||||
, UnifyTypeFactory.convert(p.TA2, false), p.getLocation());
|
||||
ret = generateSmallerDotPair(UnifyTypeFactory.convert(compiler, p.TA1, false)
|
||||
, UnifyTypeFactory.convert(compiler, p.TA2, false), p.getLocation());
|
||||
//return ret;
|
||||
}else if(p.GetOperator().equals(PairOperator.SMALLERNEQDOT)) {
|
||||
ret = generateSmallNotEqualDotPair(UnifyTypeFactory.convert(p.TA1, false)
|
||||
, UnifyTypeFactory.convert(p.TA2, false), p.getLocation());
|
||||
ret = generateSmallNotEqualDotPair(UnifyTypeFactory.convert(compiler, p.TA1, false)
|
||||
, UnifyTypeFactory.convert(compiler, p.TA2, false), p.getLocation());
|
||||
//return ret;
|
||||
}else if(p.GetOperator().equals(PairOperator.EQUALSDOT)) {
|
||||
ret = generateEqualDotPair(UnifyTypeFactory.convert(p.TA1, false)
|
||||
, UnifyTypeFactory.convert(p.TA2, false), p.getLocation());
|
||||
ret = generateEqualDotPair(UnifyTypeFactory.convert(compiler, p.TA1, false)
|
||||
, UnifyTypeFactory.convert(compiler, p.TA2, false), p.getLocation());
|
||||
//return ret;
|
||||
}else if(p.GetOperator().equals(PairOperator.SMALLER)){
|
||||
ret = generateSmallerPair(UnifyTypeFactory.convert(p.TA1, false),
|
||||
UnifyTypeFactory.convert(p.TA2, false), p.getLocation());
|
||||
ret = generateSmallerPair(UnifyTypeFactory.convert(compiler, p.TA1, false),
|
||||
UnifyTypeFactory.convert(compiler, p.TA2, false), p.getLocation());
|
||||
}else throw new NotImplementedException();
|
||||
UnifyType lhs, rhs;
|
||||
if (((lhs = ret.getLhsType()) instanceof PlaceholderType)
|
||||
|
@ -17,6 +17,7 @@ public class BinaryExpr extends Expression {
|
||||
MOD, // Modulo Operator %
|
||||
AND, // &
|
||||
OR, // |
|
||||
XOR, // ^
|
||||
DIV, // /
|
||||
LESSTHAN, // <
|
||||
BIGGERTHAN, // >
|
||||
|
@ -0,0 +1,18 @@
|
||||
package de.dhbwstuttgart.syntaxtree.statement;
|
||||
|
||||
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
|
||||
public class Continue extends Statement {
|
||||
|
||||
public Continue(RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
|
||||
super(type, offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(StatementVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
}
|
@ -27,10 +27,10 @@ public class MethodCall extends Statement
|
||||
public RefTypeOrTPHOrWildcardOrGeneric receiverType;
|
||||
|
||||
//sind Tphs, repraesentieren im Resultset die Signatur der aufgerufenen Methoden, letztes Element ist der Returntyp
|
||||
public final ArrayList<RefTypeOrTPHOrWildcardOrGeneric> signature;
|
||||
public final ArrayList<TypePlaceholder> signature;
|
||||
|
||||
public MethodCall(RefTypeOrTPHOrWildcardOrGeneric retType, Receiver receiver, String methodName, ArgumentList argumentList,
|
||||
RefTypeOrTPHOrWildcardOrGeneric receiverType, ArrayList<RefTypeOrTPHOrWildcardOrGeneric> signature, Token offset){
|
||||
RefTypeOrTPHOrWildcardOrGeneric receiverType, ArrayList<TypePlaceholder> signature, Token offset){
|
||||
super(retType,offset);
|
||||
this.arglist = argumentList;
|
||||
this.name = methodName;
|
||||
@ -40,7 +40,7 @@ public class MethodCall extends Statement
|
||||
if (signature == null) throw new NullPointerException();
|
||||
}
|
||||
|
||||
public List<RefTypeOrTPHOrWildcardOrGeneric> signatureArguments() {
|
||||
public List<TypePlaceholder> signatureArguments() {
|
||||
return signature.subList(0, signature.size() - 1);
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ import de.dhbwstuttgart.syntaxtree.Method;
|
||||
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||
import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption;
|
||||
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
|
||||
import de.dhbwstuttgart.typeinference.constraints.Constraint;
|
||||
@ -30,9 +31,9 @@ public class NewClass extends MethodCall
|
||||
* @param start
|
||||
*/
|
||||
public NewClass(RefType newClass, ArgumentList args, RefTypeOrTPHOrWildcardOrGeneric receiverType,
|
||||
ArrayList<RefTypeOrTPHOrWildcardOrGeneric> argTypes, Token start) {
|
||||
ArrayList<TypePlaceholder> signature, Token start) {
|
||||
super(newClass, new ExpressionReceiver(new EmptyStmt(start)), newClass.getName().toString(),
|
||||
args, receiverType, argTypes, start);
|
||||
args, receiverType, signature, start);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -3,6 +3,7 @@ package de.dhbwstuttgart.syntaxtree.statement;
|
||||
import de.dhbwstuttgart.parser.NullToken;
|
||||
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||
import de.dhbwstuttgart.syntaxtree.type.Void;
|
||||
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
|
||||
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
||||
@ -10,8 +11,12 @@ import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||
|
||||
public class Super extends Expression
|
||||
{
|
||||
public class Super extends Expression {
|
||||
|
||||
public Super(Token offset) {
|
||||
super(TypePlaceholder.fresh(offset), offset);
|
||||
}
|
||||
|
||||
public Super(RefTypeOrTPHOrWildcardOrGeneric type, Token offset)
|
||||
{
|
||||
super(type, offset);
|
||||
|
@ -4,6 +4,7 @@ import de.dhbwstuttgart.parser.NullToken;
|
||||
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||
import de.dhbwstuttgart.syntaxtree.type.Void;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
|
||||
@ -16,12 +17,12 @@ import java.util.List;
|
||||
public class SuperCall extends MethodCall
|
||||
{
|
||||
public SuperCall(RefTypeOrTPHOrWildcardOrGeneric receiverType,
|
||||
ArrayList<RefTypeOrTPHOrWildcardOrGeneric> argTypes, Token offset){
|
||||
ArrayList<TypePlaceholder> argTypes, Token offset){
|
||||
this(new ArgumentList(new ArrayList<Expression>(), offset), receiverType, argTypes, offset);
|
||||
}
|
||||
|
||||
public SuperCall(ArgumentList argumentList, RefTypeOrTPHOrWildcardOrGeneric receiverType,
|
||||
ArrayList<RefTypeOrTPHOrWildcardOrGeneric> argTypes, Token offset){
|
||||
ArrayList<TypePlaceholder> argTypes, Token offset){
|
||||
super(new Void(offset), new ExpressionReceiver(new Super(receiverType, offset)), "<init>", argumentList, receiverType, argTypes, offset);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,24 @@
|
||||
package de.dhbwstuttgart.syntaxtree.statement;
|
||||
|
||||
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
|
||||
public class Ternary extends Expression {
|
||||
|
||||
public final Expression cond;
|
||||
public final Expression iftrue;
|
||||
public final Expression iffalse;
|
||||
|
||||
public Ternary(RefTypeOrTPHOrWildcardOrGeneric type, Expression cond, Expression iftrue, Expression iffalse, Token offset) {
|
||||
super(type, offset);
|
||||
this.cond = cond;
|
||||
this.iftrue = iftrue;
|
||||
this.iffalse = iffalse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(StatementVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
@ -8,8 +8,7 @@ import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||
|
||||
public class This extends Expression
|
||||
{
|
||||
public This(Token offset)
|
||||
{
|
||||
public This(Token offset) {
|
||||
super(TypePlaceholder.fresh(offset), offset);
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ package de.dhbwstuttgart.syntaxtree.statement;
|
||||
import de.dhbwstuttgart.syntaxtree.Constructor;
|
||||
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||
import de.dhbwstuttgart.syntaxtree.type.Void;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
|
||||
@ -11,7 +12,7 @@ import java.util.ArrayList;
|
||||
|
||||
public class ThisCall extends MethodCall
|
||||
{
|
||||
public ThisCall(ArgumentList argumentList, RefTypeOrTPHOrWildcardOrGeneric receiverType, ArrayList<RefTypeOrTPHOrWildcardOrGeneric> argTypes, Token offset) {
|
||||
public ThisCall(ArgumentList argumentList, RefTypeOrTPHOrWildcardOrGeneric receiverType, ArrayList<TypePlaceholder> argTypes, Token offset) {
|
||||
super(new Void(offset), new ExpressionReceiver(new This(offset)), "<init>", argumentList, receiverType, argTypes, offset);
|
||||
}
|
||||
|
||||
|
@ -333,6 +333,11 @@ public class OutputGenerator implements ASTVisitor {
|
||||
out.append("break");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Continue aContinue) {
|
||||
out.append("continue");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(StaticClassName staticClassName) {
|
||||
|
||||
@ -380,6 +385,7 @@ public class OutputGenerator implements ASTVisitor {
|
||||
out.append("super(");
|
||||
superCall.arglist.accept(this);
|
||||
out.append(")");
|
||||
out.append(" Signature: " + superCall.signature);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -387,6 +393,7 @@ public class OutputGenerator implements ASTVisitor {
|
||||
out.append("this(");
|
||||
thisCall.arglist.accept(this);
|
||||
out.append(")");
|
||||
out.append(" Signature: " + thisCall.signature);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -427,6 +434,18 @@ public class OutputGenerator implements ASTVisitor {
|
||||
// TODO implement
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Ternary ternary) {
|
||||
out.append("(");
|
||||
ternary.cond.accept(this);
|
||||
out.append(" ? ");
|
||||
ternary.iftrue.accept(this);
|
||||
out.append(" : ");
|
||||
ternary.iffalse.accept(this);
|
||||
out.append(")::");
|
||||
ternary.getType().accept(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Switch switchStmt) {
|
||||
out.append("switch(");
|
||||
|
@ -1,11 +1,12 @@
|
||||
package de.dhbwstuttgart.target.generate;
|
||||
|
||||
import de.dhbwstuttgart.bytecode.CodeGenException;
|
||||
import de.dhbwstuttgart.bytecode.FunNGenerator;
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
import de.dhbwstuttgart.environment.ByteArrayClassLoader;
|
||||
import de.dhbwstuttgart.environment.IByteArrayClassLoader;
|
||||
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||
import de.dhbwstuttgart.parser.NullToken;
|
||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||
import de.dhbwstuttgart.syntaxtree.*;
|
||||
import de.dhbwstuttgart.syntaxtree.Record;
|
||||
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
|
||||
@ -16,8 +17,6 @@ import de.dhbwstuttgart.target.tree.expression.*;
|
||||
import de.dhbwstuttgart.target.tree.type.*;
|
||||
import de.dhbwstuttgart.typeinference.result.*;
|
||||
|
||||
import javax.sql.rowset.RowSetWarning;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
@ -27,16 +26,19 @@ import java.util.stream.Stream;
|
||||
*/
|
||||
public class ASTToTargetAST {
|
||||
|
||||
record SignaturePair(TypePlaceholder signature, RefTypeOrTPHOrWildcardOrGeneric parameter) {};
|
||||
record SignaturePairTarget(TargetType signature, TargetType parameter) {}
|
||||
|
||||
public static RefType OBJECT = ASTFactory.createObjectType(); // TODO It would be better if I could call this directly but the hashcode seems to change
|
||||
|
||||
protected List<Generics> all;
|
||||
protected Generics generics;
|
||||
public Generics generics;
|
||||
final Map<ClassOrInterface, Set<GenericTypeVar>> userDefinedGenerics = new HashMap<>();
|
||||
final Map<Method, Set<SignaturePair>> tphsInMethods = new HashMap<>();
|
||||
private Method currentMethod;
|
||||
|
||||
public final JavaTXCompiler compiler;
|
||||
|
||||
protected ClassOrInterface currentClass; // TODO This is only needed because of SuperCall, maybe there's
|
||||
|
||||
public List<GenericsResult> txGenerics() {
|
||||
return all.stream().map(generics -> new GenericsResult(generics.txGenerics)).toList();
|
||||
}
|
||||
@ -51,11 +53,11 @@ public class ASTToTargetAST {
|
||||
return converter.result;
|
||||
}
|
||||
|
||||
record Generics(JavaGenerics javaGenerics, TxGenerics txGenerics) {
|
||||
public record Generics(JavaGenerics javaGenerics, TxGenerics txGenerics) {
|
||||
}
|
||||
|
||||
|
||||
protected IByteArrayClassLoader classLoader;
|
||||
public IByteArrayClassLoader classLoader;
|
||||
protected SourceFile sourceFile;
|
||||
|
||||
public ASTToTargetAST(List<ResultSet> resultSets) {
|
||||
@ -77,15 +79,26 @@ public class ASTToTargetAST {
|
||||
this.generics = all.get(0);
|
||||
}
|
||||
|
||||
public void addSignaturePair(TypePlaceholder signature, RefTypeOrTPHOrWildcardOrGeneric parameter) {
|
||||
var set = tphsInMethods.getOrDefault(currentMethod, new HashSet<>());
|
||||
set.add(new SignaturePair(signature, parameter));
|
||||
tphsInMethods.put(currentMethod, set);
|
||||
}
|
||||
|
||||
Optional<Method> findMethod(ClassOrInterface owner, String name, List<TargetType> argumentList) {
|
||||
Optional<Method> method = Optional.empty();
|
||||
while (method.isEmpty() && !owner.getClassName().toString().equals("java.lang.Object")) {
|
||||
while (method.isEmpty()) {
|
||||
method = owner.getMethods().stream().filter(m -> m.name.equals(name) && parameterEquals(m.getParameterList(), argumentList)).findFirst();
|
||||
if (owner.getClassName().toString().equals("java.lang.Object")) break;
|
||||
owner = compiler.getClass(owner.getSuperClass().getName());
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
Optional<Constructor> findConstructor(ClassOrInterface owner, List<TargetType> argumentList) {
|
||||
return owner.getConstructors().stream().filter(c -> parameterEquals(c.getParameterList(), argumentList)).findFirst();
|
||||
}
|
||||
|
||||
boolean parameterEquals(ParameterList parameterList, List<TargetType> arguments) {
|
||||
var pars = parameterList.getFormalparalist();
|
||||
if (pars.size() != arguments.size())
|
||||
@ -125,8 +138,41 @@ public class ASTToTargetAST {
|
||||
return ret;
|
||||
}
|
||||
|
||||
public List<List<TargetMethod>> groupOverloads(ClassOrInterface input, List<Method> methods) {
|
||||
var res = new ArrayList<List<TargetMethod>>();
|
||||
for (var method : methods) {
|
||||
// Convert all methods
|
||||
var methodsWithTphs = convert(input, method);
|
||||
// Then check for methods with the same signature
|
||||
var mapOfSignatures = new HashMap<TargetMethod.Signature, List<MethodWithTphs>>();
|
||||
for (var m : methodsWithTphs) {
|
||||
var methodsWithSameSignature = mapOfSignatures.getOrDefault(m.method.signature(), new ArrayList<>());
|
||||
methodsWithSameSignature.add(m);
|
||||
mapOfSignatures.put(m.method.signature(), methodsWithSameSignature);
|
||||
}
|
||||
|
||||
var resMethods = new HashSet<TargetMethod>();
|
||||
for (var methodsWithSignature : mapOfSignatures.values()) {
|
||||
outer: for (var m1 : methodsWithSignature) {
|
||||
for (var m2 : methodsWithSignature) {
|
||||
for (var i = 0; i < m1.args.size(); i++) {
|
||||
var arg1 = m1.args.get(i);
|
||||
var arg2 = m2.args.get(i);
|
||||
if (arg1.parameter.equals(arg2.parameter)) {
|
||||
if (isSupertype(arg1.signature, arg2.signature) &&
|
||||
!arg1.signature.equals(arg2.signature)) continue outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
resMethods.add(m1.method);
|
||||
}
|
||||
}
|
||||
res.add(resMethods.stream().toList());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public TargetStructure convert(ClassOrInterface input) {
|
||||
currentClass = input;
|
||||
Set<TargetGeneric> javaGenerics = new HashSet<>();
|
||||
Set<TargetGeneric> txGenerics = new HashSet<>();
|
||||
|
||||
@ -154,13 +200,13 @@ public class ASTToTargetAST {
|
||||
TargetBlock finalFieldInitializer = fieldInitializer;
|
||||
|
||||
var superInterfaces = input.getSuperInterfaces().stream().map(clazz -> convert(clazz, generics.javaGenerics)).toList();
|
||||
var constructors = input.getConstructors().stream().map(constructor -> this.convert(constructor, finalFieldInitializer)).flatMap(List::stream).toList();
|
||||
var constructors = input.getConstructors().stream().map(constructor -> this.convert(input, constructor, finalFieldInitializer)).flatMap(List::stream).toList();
|
||||
var fields = input.getFieldDecl().stream().map(this::convert).toList();
|
||||
var methods = groupOverloads(input.getMethods()).stream().map(this::convert).flatMap(List::stream).toList();
|
||||
var methods = groupOverloads(input, input.getMethods()).stream().flatMap(List::stream).toList();
|
||||
|
||||
TargetMethod staticConstructor = null;
|
||||
if (input.getStaticInitializer().isPresent())
|
||||
staticConstructor = this.convert(input.getStaticInitializer().get()).get(0);
|
||||
staticConstructor = this.convert(input, input.getStaticInitializer().get()).stream().findFirst().orElseThrow().method;
|
||||
|
||||
if (input instanceof Record)
|
||||
return new TargetRecord(input.getModifiers(), input.getClassName(), javaGenerics, txGenerics, superInterfaces, constructors, staticConstructor, fields, methods);
|
||||
@ -169,7 +215,7 @@ public class ASTToTargetAST {
|
||||
else return new TargetClass(input.getModifiers(), input.getClassName(), convert(input.getSuperClass(), generics.javaGenerics), javaGenerics, txGenerics, superInterfaces, constructors, staticConstructor, fields, methods);
|
||||
}
|
||||
|
||||
private List<MethodParameter> convert(ParameterList input, GenerateGenerics generics) {
|
||||
public List<MethodParameter> convert(ParameterList input, GenerateGenerics generics) {
|
||||
return input.getFormalparalist().stream().map(param ->
|
||||
new MethodParameter((TargetPattern) convert(param))
|
||||
).toList();
|
||||
@ -179,10 +225,10 @@ public class ASTToTargetAST {
|
||||
return generics.stream().anyMatch(g -> g.name().equals(type.getParsedName()));
|
||||
}
|
||||
|
||||
private Set<TargetGeneric> collectMethodGenerics(GenerateGenerics generateGenerics, Set<GenerateGenerics.Pair> generics, Method input) {
|
||||
private Set<TargetGeneric> collectMethodGenerics(ClassOrInterface clazz, GenerateGenerics generateGenerics, Set<GenerateGenerics.Pair> generics, Method input) {
|
||||
var convertedGenerics = new HashSet<>(convert(generics, generateGenerics));
|
||||
outer: for (GenericTypeVar typeVar : input.getGenerics()) {
|
||||
for (var classGeneric : currentClass.getGenerics()) {
|
||||
for (var classGeneric : clazz.getGenerics()) {
|
||||
if (classGeneric.equals(typeVar)) {
|
||||
continue outer;
|
||||
}
|
||||
@ -197,10 +243,11 @@ public class ASTToTargetAST {
|
||||
return convertedGenerics;
|
||||
}
|
||||
|
||||
private List<TargetConstructor> convert(Constructor input, TargetBlock fieldInitializer) {
|
||||
private List<TargetConstructor> convert(ClassOrInterface currentClass, Constructor input, TargetBlock fieldInitializer) {
|
||||
generics = all.get(0);
|
||||
List<TargetConstructor> result = new ArrayList<>();
|
||||
Set<List<MethodParameter>> parameterSet = new HashSet<>();
|
||||
this.currentMethod = input;
|
||||
|
||||
for (var s : all) {
|
||||
generics = s;
|
||||
@ -209,8 +256,8 @@ public class ASTToTargetAST {
|
||||
List<MethodParameter> params = convert(input.getParameterList(), this.generics.javaGenerics);
|
||||
if (parameterSet.stream().noneMatch(p -> p.equals(params))) {
|
||||
List<MethodParameter> txParams = convert(input.getParameterList(), this.generics.txGenerics);
|
||||
var javaMethodGenerics = collectMethodGenerics(generics.javaGenerics(), javaGenerics, input);
|
||||
var txMethodGenerics = collectMethodGenerics(generics.txGenerics(), txGenerics, input);
|
||||
var javaMethodGenerics = collectMethodGenerics(currentClass, generics.javaGenerics(), javaGenerics, input);
|
||||
var txMethodGenerics = collectMethodGenerics(currentClass, generics.txGenerics(), txGenerics, input);
|
||||
|
||||
result.add(new TargetConstructor(input.modifier, javaMethodGenerics, txMethodGenerics, params, txParams, convert(input.block), fieldInitializer));
|
||||
parameterSet.add(params);
|
||||
@ -220,56 +267,6 @@ public class ASTToTargetAST {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This only considers type patterns, all other methods aren't grouped together
|
||||
* @param a
|
||||
* @param b
|
||||
* @return
|
||||
*/
|
||||
private boolean signatureEquals(Method a, Method b) {
|
||||
if (!a.name.equals(b.name)) return false;
|
||||
var para = a.getParameterList().getFormalparalist();
|
||||
var parb = b.getParameterList().getFormalparalist();
|
||||
if (para.size() != parb.size()) return false;
|
||||
|
||||
for (var i = 0; i < para.size(); i++) {
|
||||
var pa = para.get(i);
|
||||
var pb = parb.get(i);
|
||||
|
||||
if (pa instanceof RecordPattern rpa) {
|
||||
if (pb instanceof RecordPattern rpb) {
|
||||
if (rpa.getType().equals(rpb.getType())) continue;
|
||||
}
|
||||
return false;
|
||||
} else if (pa.getType().equals(pb.getType())) {
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO Nested patterns
|
||||
private List<List<Method>> groupOverloads(List<Method> input) {
|
||||
var done = new HashSet<Method>();
|
||||
var res = new ArrayList<List<Method>>();
|
||||
for (var method : input) {
|
||||
if (done.contains(method)) continue;
|
||||
var overloads = new ArrayList<Method>();
|
||||
overloads.add(method);
|
||||
done.add(method);
|
||||
for (var method2 : input) {
|
||||
if (!done.contains(method2) && signatureEquals(method, method2)) {
|
||||
done.add(method2);
|
||||
overloads.add(method2);
|
||||
}
|
||||
}
|
||||
res.add(overloads);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private String encodeName(String name, ParameterList params) {
|
||||
var res = new StringBuilder();
|
||||
res.append(name);
|
||||
@ -285,11 +282,11 @@ public class ASTToTargetAST {
|
||||
return res.toString();
|
||||
}
|
||||
|
||||
private List<TargetMethod> convert(List<Method> overloadedMethods) {
|
||||
private List<TargetMethod> convert(ClassOrInterface clazz, List<Method> overloadedMethods) {
|
||||
if (overloadedMethods.size() == 1) {
|
||||
return convert(overloadedMethods.get(0));
|
||||
return convert(clazz, overloadedMethods.getFirst()).stream().map(m -> m.method()).toList();
|
||||
}
|
||||
var res = new ArrayList<Method>();
|
||||
var methods = new ArrayList<Method>();
|
||||
for (var method : overloadedMethods) {
|
||||
var newMethod = new Method(
|
||||
method.modifier,
|
||||
@ -301,7 +298,7 @@ public class ASTToTargetAST {
|
||||
method.getGenerics(),
|
||||
method.getOffset()
|
||||
);
|
||||
res.add(newMethod);
|
||||
methods.add(newMethod);
|
||||
}
|
||||
|
||||
// TODO Record overloading
|
||||
@ -324,7 +321,16 @@ public class ASTToTargetAST {
|
||||
var entryPoint = new Method(template.modifier, template.name, template.getReturnType(), params, block, template.getGenerics(), new NullToken());
|
||||
|
||||
res.add(entryPoint); // TODO*/
|
||||
return res.stream().map(this::convert).flatMap(List::stream).toList();
|
||||
var res = new ArrayList<TargetMethod>();
|
||||
for (var method : methods) {
|
||||
var overloads = convert(clazz, method);
|
||||
for (var m : overloads) {
|
||||
var overload = m.method;
|
||||
if (res.contains(overload)) throw new CodeGenException("Duplicate method found: " + overload.name() + " with signature " + overload.signature().getSignature());
|
||||
res.add(overload);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private Expression makeRecordSwitch(RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList params, List<Method> overloadedMethods) {
|
||||
@ -348,31 +354,75 @@ public class ASTToTargetAST {
|
||||
return swtch;
|
||||
}
|
||||
|
||||
private List<TargetMethod> convert(Method method) {
|
||||
generics = all.get(0);
|
||||
List<TargetMethod> result = new ArrayList<>();
|
||||
Set<List<MethodParameter>> parameterSet = new HashSet<>();
|
||||
private Optional<Method> findSuperMethodToOverride(ClassOrInterface currentClass, String name, List<MethodParameter> params) {
|
||||
var superClass = compiler.getClass(currentClass.getSuperClass().getName());
|
||||
var methodStream = superClass.getMethods().stream();
|
||||
for (var superInterface : currentClass.getSuperInterfaces()) {
|
||||
methodStream = Stream.concat(methodStream, compiler.getClass(superInterface.getName()).getMethods().stream());
|
||||
}
|
||||
|
||||
return methodStream.filter(m -> {
|
||||
if (!m.name.equals(name)) return false;
|
||||
var sParams = m.getParameterList();
|
||||
if (sParams.getFormalparalist().size() != params.size()) return false;
|
||||
for (var i = 0; i < params.size(); i++) {
|
||||
var a = TargetType.toPrimitive(params.get(i).pattern().type());
|
||||
var b = convert(sParams.getFormalparalist().get(i).getType());
|
||||
if (!Objects.equals(a, b)) return false;
|
||||
}
|
||||
return true;
|
||||
}).findFirst();
|
||||
}
|
||||
|
||||
record MethodWithTphs(TargetMethod method, List<SignaturePairTarget> args) {}
|
||||
|
||||
private List<MethodWithTphs> convert(ClassOrInterface currentClass, Method method) {
|
||||
generics = all.getFirst();
|
||||
List<MethodWithTphs> result = new ArrayList<>();
|
||||
this.currentMethod = method;
|
||||
|
||||
for (var s : all) {
|
||||
generics = s;
|
||||
var javaGenerics = this.generics.javaGenerics.generics(currentClass, method);
|
||||
var txGenerics = this.generics.txGenerics.generics(currentClass, method);
|
||||
List<MethodParameter> params = convert(method.getParameterList(), this.generics.javaGenerics);
|
||||
if (parameterSet.stream().noneMatch(p -> p.equals(params))) {
|
||||
var returnType = convert(method.getReturnType(), this.generics.javaGenerics);
|
||||
var superMethod = findSuperMethodToOverride(currentClass, method.getName(), params);
|
||||
if (superMethod.isPresent()) {
|
||||
// If we find a super method to override, use its parameters and return types
|
||||
var newReturnType = convert(superMethod.get().getReturnType(), this.generics.javaGenerics);
|
||||
if (newReturnType instanceof TargetPrimitiveType && TargetType.toPrimitive(returnType).equals(newReturnType)) {
|
||||
returnType = newReturnType;
|
||||
params = convert(superMethod.get().getParameterList(), method.getParameterList(), this.generics.javaGenerics);
|
||||
}
|
||||
}
|
||||
|
||||
List<MethodParameter> txParams = convert(method.getParameterList(), this.generics.txGenerics);
|
||||
|
||||
var javaMethodGenerics = collectMethodGenerics(generics.javaGenerics(), javaGenerics, method);
|
||||
var txMethodGenerics = collectMethodGenerics(generics.txGenerics(), txGenerics, method);
|
||||
var javaMethodGenerics = collectMethodGenerics(currentClass, generics.javaGenerics(), javaGenerics, method);
|
||||
var txMethodGenerics = collectMethodGenerics(currentClass, generics.txGenerics(), txGenerics, method);
|
||||
|
||||
var javaSignature = new TargetMethod.Signature(javaMethodGenerics, params, convert(method.getReturnType(), this.generics.javaGenerics));
|
||||
var javaSignature = new TargetMethod.Signature(javaMethodGenerics, params, returnType);
|
||||
var txSignature = new TargetMethod.Signature(txMethodGenerics, txParams, convert(method.getReturnType(), this.generics.txGenerics));
|
||||
result.add(new TargetMethod(method.modifier, method.name, convert(method.block), javaSignature, txSignature));
|
||||
parameterSet.add(params);
|
||||
}
|
||||
var newMethod = new TargetMethod(method.modifier, method.name, convert(method.block), javaSignature, txSignature);
|
||||
|
||||
var concreteParams = tphsInMethods.getOrDefault(method, new HashSet<>()).stream().map(sig -> new SignaturePairTarget(convert(sig.signature), convert(sig.parameter))).toList();
|
||||
|
||||
result.add(new MethodWithTphs(newMethod, concreteParams));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<MethodParameter> convert(ParameterList superList, ParameterList paraList, JavaGenerics generics) {
|
||||
var list = new ArrayList<MethodParameter>();
|
||||
for (var i = 0; i < paraList.getFormalparalist().size(); i++) {
|
||||
var param = paraList.getParameterAt(i);
|
||||
list.add(new MethodParameter((TargetPattern) convert(param)).withType(convert(superList.getParameterAt(i).getType(), generics)));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
protected TargetSwitch.Case convert(SwitchBlock block) {
|
||||
return new TargetSwitch.Case(block.getLabels().stream().map(this::convert).toList(), convert((Block) block), block.isExpression);
|
||||
}
|
||||
@ -404,7 +454,7 @@ public class ASTToTargetAST {
|
||||
|
||||
public Map<String, byte[]> auxiliaries = new HashMap<>();
|
||||
|
||||
protected TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input) {
|
||||
public TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input) {
|
||||
return convert(input, generics.javaGenerics);
|
||||
}
|
||||
|
||||
@ -430,10 +480,59 @@ public class ASTToTargetAST {
|
||||
}
|
||||
var filteredParams = new ArrayList<TargetType>();
|
||||
for (var i = 0; i < newParams.size(); i++) {
|
||||
if (gep.parameters.get(i) != null)
|
||||
if (i < gep.inParams.size() && gep.inParams.get(i) != null)
|
||||
filteredParams.add(newParams.get(i));
|
||||
}
|
||||
return TargetFunNType.fromParams(params, filteredParams);
|
||||
return TargetFunNType.fromParams(params, filteredParams, gep.getReturnType() != null ? 1 : 0);
|
||||
}
|
||||
|
||||
private boolean isSubtype(TargetType test, TargetType other) {
|
||||
var testClass = compiler.getClass(new JavaClassName(test.name()));
|
||||
var otherClass = compiler.getClass(new JavaClassName(other.name()));
|
||||
if (testClass == null) return false;
|
||||
while (testClass != null) {
|
||||
if (testClass.equals(otherClass)) return true;
|
||||
if (testClass.getClassName().equals(new JavaClassName("java.lang.Object"))) break;
|
||||
testClass = compiler.getClass(testClass.getSuperClass().getName());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isSupertype(TargetType test, TargetType other) {
|
||||
return isSubtype(other, test);
|
||||
}
|
||||
|
||||
private boolean isSubtype(FunNGenerator.GenericParameters test, FunNGenerator.GenericParameters other) {
|
||||
if (test.getArguments().size() != other.getArguments().size()) return false;
|
||||
if (!isSubtype(test.getReturnType(), other.getReturnType())) return false;
|
||||
for (int i = 0; i < test.getArguments().size(); i++) {
|
||||
var arg1 = test.getArguments().get(i);
|
||||
var arg2 = other.getArguments().get(i);
|
||||
if (!isSupertype(arg1, arg2)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void generateFunNTypes() {
|
||||
for (var entry : usedFunN.entrySet()) {
|
||||
var gep = entry.getValue();
|
||||
var superInterfaces = usedFunN.values().stream()
|
||||
.filter(g -> !g.equals(gep))
|
||||
.filter(genericParameters -> isSubtype(gep, genericParameters))
|
||||
.map(FunNGenerator::getSpecializedClassName)
|
||||
.toList();
|
||||
|
||||
var code = FunNGenerator.generateSpecializedBytecode(gep, superInterfaces);
|
||||
|
||||
try {
|
||||
classLoader.findClass(entry.getKey());
|
||||
} catch (ClassNotFoundException e) {
|
||||
try {
|
||||
classLoader.loadClass(code);
|
||||
} catch (LinkageError ignored) {}
|
||||
}
|
||||
auxiliaries.put(entry.getKey(), code);
|
||||
}
|
||||
}
|
||||
|
||||
protected TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, GenerateGenerics generics) {
|
||||
@ -448,17 +547,16 @@ public class ASTToTargetAST {
|
||||
}
|
||||
|
||||
var params = refType.getParaList().stream().map(type -> {
|
||||
var res = convert(type, generics);
|
||||
if (res == null) res = new TargetRefType("java.lang.Void");
|
||||
return res;
|
||||
return convert(type, generics);
|
||||
}).toList();
|
||||
|
||||
if (name.matches("Fun\\d+\\$\\$")) { // TODO This seems like a bad idea
|
||||
var className = FunNGenerator.getSpecializedClassName(FunNGenerator.getArguments(params), FunNGenerator.getReturnType(params));
|
||||
var returnType = FunNGenerator.getReturnType(params);
|
||||
var className = FunNGenerator.getSpecializedClassName(FunNGenerator.getArguments(params), returnType);
|
||||
if (!usedFunNSuperTypes.contains(params.size())) {
|
||||
usedFunNSuperTypes.add(params.size());
|
||||
var code = FunNGenerator.generateSuperBytecode(params.size() - 1);
|
||||
var superClassName = FunNGenerator.getSuperClassName(params.size() - 1);
|
||||
var code = FunNGenerator.generateSuperBytecode(params.size() - 1, returnType != null ? 1 : 0);
|
||||
var superClassName = FunNGenerator.getSuperClassName(params.size() - 1, returnType != null ? 1 : 0);
|
||||
try {
|
||||
classLoader.findClass(superClassName);
|
||||
} catch (ClassNotFoundException e) {
|
||||
@ -470,17 +568,8 @@ public class ASTToTargetAST {
|
||||
}
|
||||
FunNGenerator.GenericParameters gep = null;
|
||||
if (!usedFunN.containsKey(className)) {
|
||||
gep = new FunNGenerator.GenericParameters();
|
||||
var code = FunNGenerator.generateSpecializedBytecode(FunNGenerator.getArguments(params), FunNGenerator.getReturnType(params), gep);
|
||||
try {
|
||||
classLoader.findClass(className);
|
||||
} catch (ClassNotFoundException e) {
|
||||
try {
|
||||
classLoader.loadClass(code);
|
||||
} catch (LinkageError ignored) {}
|
||||
}
|
||||
gep = new FunNGenerator.GenericParameters(params, returnType != null ? 1 : 0);
|
||||
usedFunN.put(className, gep);
|
||||
auxiliaries.put(className, code);
|
||||
} else {
|
||||
gep = usedFunN.get(className);
|
||||
}
|
||||
|
@ -652,14 +652,12 @@ public abstract class GenerateGenerics {
|
||||
}
|
||||
|
||||
void normalize(Set<Pair> result, Set<Pair> classGenerics, Set<TPH> usedTphs) {
|
||||
outer:
|
||||
for (var tph : usedTphs) {
|
||||
for (var p1 : new HashSet<>(result)) {
|
||||
if (p1 instanceof PairLT ptph && ptph.left.equals(ptph.right))
|
||||
if (p1 instanceof PairLT ptph && ptph.left.resolve().equals(ptph.right.resolve()))
|
||||
result.remove(p1); // TODO This is a bit strange
|
||||
if (p1.left.equals(tph)) continue outer;
|
||||
}
|
||||
|
||||
for (var tph : usedTphs) {
|
||||
if (classGenerics == null || classGenerics.stream().noneMatch((pair) -> pair.left.equals(tph)))
|
||||
addToPairs(result, new PairEQ(tph, ASTToTargetAST.OBJECT));
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package de.dhbwstuttgart.target.generate;
|
||||
|
||||
import de.dhbwstuttgart.exceptions.DebugException;
|
||||
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||
import de.dhbwstuttgart.parser.NullToken;
|
||||
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
|
||||
@ -9,6 +10,8 @@ import de.dhbwstuttgart.syntaxtree.factory.PrimitiveMethodsGenerator;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.*;
|
||||
import de.dhbwstuttgart.syntaxtree.type.*;
|
||||
import de.dhbwstuttgart.target.tree.MethodParameter;
|
||||
import de.dhbwstuttgart.target.tree.TargetGeneric;
|
||||
import de.dhbwstuttgart.target.tree.TargetMethod;
|
||||
import de.dhbwstuttgart.target.tree.expression.*;
|
||||
import de.dhbwstuttgart.target.tree.type.*;
|
||||
|
||||
@ -81,7 +84,9 @@ public class StatementToTargetExpression implements ASTVisitor {
|
||||
} // Don't look at lambda expressions
|
||||
});
|
||||
|
||||
result = new TargetLambdaExpression(converter.convert(lambdaExpression.getType()), captures, parameters, converter.convert(lambdaExpression.getReturnType()), converter.convert(lambdaExpression.methodBody));
|
||||
TargetMethod.Signature signature = new TargetMethod.Signature(Set.of(), parameters, converter.convert(lambdaExpression.getReturnType()));;
|
||||
var tpe = converter.convert(lambdaExpression.getType());
|
||||
result = new TargetLambdaExpression(tpe, captures, signature, converter.convert(lambdaExpression.methodBody));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -103,8 +108,9 @@ public class StatementToTargetExpression implements ASTVisitor {
|
||||
case SUB -> new TargetBinaryOp.Sub(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
|
||||
case MUL -> new TargetBinaryOp.Mul(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
|
||||
case MOD -> new TargetBinaryOp.Rem(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
|
||||
case AND -> new TargetBinaryOp.And(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
|
||||
case OR -> new TargetBinaryOp.Or(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
|
||||
case AND -> new TargetBinaryOp.BAnd(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
|
||||
case OR -> new TargetBinaryOp.BOr(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
|
||||
case XOR -> new TargetBinaryOp.XOr(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
|
||||
case DIV -> new TargetBinaryOp.Div(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
|
||||
case LESSTHAN -> new TargetBinaryOp.Less(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
|
||||
case BIGGERTHAN -> new TargetBinaryOp.Greater(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
|
||||
@ -199,14 +205,23 @@ public class StatementToTargetExpression implements ASTVisitor {
|
||||
Method foundMethod = null;
|
||||
var isStatic = false;
|
||||
var isInterface = true;
|
||||
var isPrivate = false;
|
||||
var signature = methodCall.signatureArguments().stream().map(converter::convert).toList();
|
||||
|
||||
var receiverClass = converter.currentClass;
|
||||
// Add used TPHs to containing method
|
||||
for (var i = 0; i < methodCall.signatureArguments().size(); i++) {
|
||||
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) {
|
||||
var thisMethod = converter.findMethod(converter.currentClass, methodCall.name, signature);
|
||||
foundMethod = thisMethod.orElseGet(() -> findMethod(converter.currentClass.getSuperClass().getName(), methodCall.name, signature).orElseThrow());
|
||||
if (receiverClass == null) throw new DebugException("Class " + receiverName + " does not exist!");
|
||||
var thisMethod = converter.findMethod(receiverClass, methodCall.name, signature);
|
||||
ClassOrInterface finalReceiverClass = receiverClass;
|
||||
foundMethod = thisMethod.orElseGet(() -> findMethod(finalReceiverClass.getSuperClass().getName(), methodCall.name, signature).orElseThrow());
|
||||
} else if (!isFunNType) {
|
||||
receiverClass = converter.compiler.getClass(receiverName);
|
||||
if (receiverClass == null) throw new DebugException("Class " + receiverName + " does not exist!");
|
||||
foundMethod = findMethod(receiverName, methodCall.name, signature).orElseThrow();
|
||||
}
|
||||
|
||||
@ -214,15 +229,20 @@ public class StatementToTargetExpression implements ASTVisitor {
|
||||
returnType = converter.convert(foundMethod.getReturnType());
|
||||
argList = foundMethod.getParameterList().getFormalparalist().stream().map(e -> converter.convert(e.getType())).toList();
|
||||
isStatic = Modifier.isStatic(foundMethod.modifier);
|
||||
isPrivate = Modifier.isPrivate(foundMethod.modifier);
|
||||
isInterface = receiverClass.isInterface();
|
||||
}
|
||||
|
||||
result = new TargetMethodCall(converter.convert(methodCall.getType()), returnType, argList, converter.convert(methodCall.receiver), methodCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), receiverType, methodCall.name, isStatic, isInterface);
|
||||
System.out.println(argList);
|
||||
result = new TargetMethodCall(converter.convert(methodCall.getType()), returnType, argList, converter.convert(methodCall.receiver), methodCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), receiverType, methodCall.name, isStatic, isInterface, isPrivate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NewClass newClass) {
|
||||
result = new TargetNew(new TargetRefType(newClass.name), newClass.getArgumentList().getArguments().stream().map(converter::convert).toList());
|
||||
var receiverName = new JavaClassName(newClass.name);
|
||||
var ctor = converter.findConstructor(converter.compiler.getClass(receiverName), newClass.signatureArguments().stream().map(converter::convert).toList());
|
||||
var signature = ctor.orElseThrow().getParameterList().getFormalparalist().stream().map(e -> converter.convert(e.getType())).toList();
|
||||
result = new TargetNew(new TargetRefType(newClass.name), signature, newClass.getArgumentList().getArguments().stream().map(converter::convert).toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -246,6 +266,11 @@ public class StatementToTargetExpression implements ASTVisitor {
|
||||
result = new TargetBreak();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Continue aContinue) {
|
||||
result = new TargetContinue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(StaticClassName staticClassName) {
|
||||
result = new TargetClassName(converter.convert(staticClassName.getType()));
|
||||
@ -268,7 +293,7 @@ public class StatementToTargetExpression implements ASTVisitor {
|
||||
|
||||
@Override
|
||||
public void visit(DoStmt whileStmt) {
|
||||
throw new NotImplementedException();
|
||||
result = new TargetDo(converter.convert(whileStmt.expr), converter.convert(whileStmt.loopBlock));
|
||||
}
|
||||
|
||||
// TODO These two might not be necessary
|
||||
@ -284,20 +309,31 @@ public class StatementToTargetExpression implements ASTVisitor {
|
||||
|
||||
@Override
|
||||
public void visit(SuperCall superCall) {
|
||||
var aSuper = converter.convert(converter.currentClass.getSuperClass());
|
||||
var aSuper = converter.convert(superCall.receiver.getType());
|
||||
var type = converter.convert(superCall.getType());
|
||||
var parameters = superCall.arglist.getArguments().stream().map(par -> converter.convert(par.getType())).toList();
|
||||
var receiverName = new JavaClassName(converter.convert(superCall.receiver.getType()).name());
|
||||
var clazz = converter.compiler.getClass(receiverName);
|
||||
var signature = superCall.signatureArguments().stream().map(converter::convert).toList();
|
||||
var method = converter.findConstructor(clazz, signature);
|
||||
var params = superCall.getArgumentList().getArguments().stream().map(converter::convert).toList();
|
||||
|
||||
result = new TargetMethodCall(type, type, parameters, new TargetSuper(aSuper), superCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), aSuper, superCall.name, false, false);
|
||||
List<TargetType> argList;
|
||||
if (method.isPresent()) {
|
||||
argList = method.get().getParameterList().getFormalparalist().stream().map(e -> converter.convert(e.getType())).toList();
|
||||
} else {
|
||||
argList = params.stream().map(TargetExpression::type).toList();
|
||||
}
|
||||
|
||||
result = new TargetMethodCall(type, null, argList, new TargetSuper(aSuper), params, aSuper, superCall.name, false, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ThisCall thisCall) {
|
||||
var aThis = converter.convert(new RefType(converter.currentClass.getClassName(), new NullToken()));
|
||||
var aThis = converter.convert(thisCall.receiver.getType());
|
||||
var type = converter.convert(thisCall.getType());
|
||||
var parameters = thisCall.arglist.getArguments().stream().map(par -> converter.convert(par.getType())).toList();
|
||||
|
||||
result = new TargetMethodCall(type, type, parameters, new TargetThis(aThis), thisCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), aThis, thisCall.name, false, false);
|
||||
result = new TargetMethodCall(type, type, parameters, new TargetThis(aThis), thisCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), aThis, thisCall.name, false, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -345,6 +381,11 @@ public class StatementToTargetExpression implements ASTVisitor {
|
||||
result = new TargetThrow(converter.convert(aThrow.expr));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Ternary ternary) {
|
||||
result = new TargetTernary(converter.convert(ternary.getType()), converter.convert(ternary.cond), converter.convert(ternary.iftrue), converter.convert(ternary.iffalse));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Switch switchStmt) {
|
||||
var cases = switchStmt.getBlocks().stream().filter(s -> !s.isDefault()).map(converter::convert).toList();
|
||||
|
@ -124,6 +124,11 @@ public abstract class TracingStatementVisitor implements StatementVisitor {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Continue aContinue) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(StaticClassName staticClassName) {
|
||||
|
||||
@ -203,4 +208,11 @@ public abstract class TracingStatementVisitor implements StatementVisitor {
|
||||
public void visit(Yield aYield) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Ternary ternary) {
|
||||
ternary.cond.accept(this);
|
||||
ternary.iftrue.accept(this);
|
||||
ternary.iffalse.accept(this);
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,24 @@
|
||||
package de.dhbwstuttgart.target.tree;
|
||||
|
||||
import de.dhbwstuttgart.target.tree.expression.TargetBlock;
|
||||
import de.dhbwstuttgart.target.tree.expression.TargetPattern;
|
||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
public record TargetMethod(int access, String name, TargetBlock block, Signature signature, Signature txSignature) {
|
||||
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() {
|
||||
return TargetMethod.getSignature(generics, parameters, returnType);
|
||||
}
|
||||
|
||||
public String getDescriptor() {
|
||||
return TargetMethod.getDescriptor(returnType, parameters.stream().map(MethodParameter::pattern).map(TargetPattern::type).toArray(TargetType[]::new));
|
||||
}
|
||||
}
|
||||
|
||||
public static String getDescriptor(TargetType returnType, TargetType... parameters) {
|
||||
String ret = "(";
|
||||
@ -55,5 +65,16 @@ public record TargetMethod(int access, String name, TargetBlock block, Signature
|
||||
public boolean isStatic() {
|
||||
return (access & Opcodes.ACC_STATIC) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof TargetMethod otherMethod)) return false;
|
||||
return otherMethod.signature.equals(this.signature) && otherMethod.name.equals(this.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name, signature);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,4 @@
|
||||
package de.dhbwstuttgart.target.tree.expression;
|
||||
|
||||
public record TargetDo(TargetExpression cond, TargetExpression body) implements TargetExpression {
|
||||
}
|
@ -3,7 +3,7 @@ package de.dhbwstuttgart.target.tree.expression;
|
||||
import de.dhbwstuttgart.target.tree.type.*;
|
||||
|
||||
public sealed interface TargetExpression
|
||||
permits TargetBinaryOp, TargetBlock, TargetBreak, TargetCast, TargetClassName, TargetContinue, TargetFieldVar, TargetFor, TargetForEach, TargetIf, TargetInstanceOf, TargetLambdaExpression, TargetLiteral, TargetLocalVar, TargetPattern, TargetReturn, TargetStatementExpression, TargetSuper, TargetSwitch, TargetTernary, TargetThis, TargetThrow, TargetUnaryOp, TargetVarDecl, TargetWhile, TargetYield {
|
||||
permits TargetBinaryOp, TargetBlock, TargetBreak, TargetCast, TargetClassName, TargetContinue, TargetDo, TargetFieldVar, TargetFor, TargetForEach, TargetIf, TargetInstanceOf, TargetLambdaExpression, TargetLiteral, TargetLocalVar, TargetPattern, TargetReturn, TargetStatementExpression, TargetSuper, TargetSwitch, TargetTernary, TargetThis, TargetThrow, TargetUnaryOp, TargetVarDecl, TargetWhile, TargetYield {
|
||||
|
||||
default TargetType type() {
|
||||
return null;
|
||||
|
@ -7,4 +7,9 @@ public record TargetGuard(TargetPattern inner, TargetExpression expression) impl
|
||||
public TargetGuard withType(TargetType type) {
|
||||
return new TargetGuard(inner.withType(type), expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TargetType type() {
|
||||
return inner.type();
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,10 @@ package de.dhbwstuttgart.target.tree.expression;
|
||||
|
||||
import de.dhbwstuttgart.target.tree.MethodParameter;
|
||||
import de.dhbwstuttgart.target.tree.TargetField;
|
||||
import de.dhbwstuttgart.target.tree.TargetMethod;
|
||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record TargetLambdaExpression(TargetType type, List<MethodParameter> captures, List<MethodParameter> params, TargetType returnType, TargetBlock block) implements TargetExpression {
|
||||
public record TargetLambdaExpression(TargetType type, List<MethodParameter> captures, TargetMethod.Signature signature, TargetBlock block) implements TargetExpression {
|
||||
}
|
||||
|
@ -1,15 +1,13 @@
|
||||
package de.dhbwstuttgart.target.tree.expression;
|
||||
|
||||
import de.dhbwstuttgart.target.tree.MethodParameter;
|
||||
import de.dhbwstuttgart.target.tree.TargetMethod;
|
||||
import de.dhbwstuttgart.target.tree.type.TargetRefType;
|
||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record TargetMethodCall(TargetType type, TargetType returnType, List<TargetType> parameterTypes, TargetExpression expr, List<TargetExpression> args, TargetType owner, String name, boolean isStatic, boolean isInterface) implements TargetStatementExpression {
|
||||
public TargetMethodCall(TargetType type, TargetExpression expr, List<TargetExpression> args, TargetType owner, String name, boolean isStatic, boolean isInterface) {
|
||||
this(type, type, args.stream().map(TargetExpression::type).toList(), expr, args, owner, name, isStatic, isInterface);
|
||||
public record TargetMethodCall(TargetType type, TargetType returnType, List<TargetType> parameterTypes, TargetExpression expr, List<TargetExpression> args, TargetType owner, String name, boolean isStatic, boolean isInterface, boolean isPrivate) implements TargetStatementExpression {
|
||||
public TargetMethodCall(TargetType type, TargetExpression expr, List<TargetExpression> args, TargetType owner, String name, boolean isStatic, boolean isInterface, boolean isPrivate) {
|
||||
this(type, type, args.stream().map(TargetExpression::type).toList(), expr, args, owner, name, isStatic, isInterface, isPrivate);
|
||||
}
|
||||
|
||||
|
||||
|
@ -5,8 +5,8 @@ import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record TargetNew(TargetType type, List<TargetExpression> params) implements TargetStatementExpression {
|
||||
public record TargetNew(TargetType type, List<TargetType> signature, List<TargetExpression> params) implements TargetStatementExpression {
|
||||
public String getDescriptor() {
|
||||
return TargetMethod.getDescriptor(null, params.stream().map(TargetExpression::type).toArray(TargetType[]::new));
|
||||
return TargetMethod.getDescriptor(null, signature.toArray(TargetType[]::new));
|
||||
}
|
||||
}
|
||||
|
@ -8,4 +8,6 @@ public sealed interface TargetPattern extends TargetExpression permits TargetCom
|
||||
}
|
||||
|
||||
TargetPattern withType(TargetType type);
|
||||
|
||||
TargetType type();
|
||||
}
|
||||
|
@ -2,5 +2,5 @@ package de.dhbwstuttgart.target.tree.expression;
|
||||
|
||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||
|
||||
public record TargetTernary(TargetType type, TargetExpression cond, TargetExpression ifTrue, TargetExpression ifFalse) implements TargetExpression {
|
||||
public record TargetTernary(TargetType type, TargetExpression cond, TargetExpression iftrue, TargetExpression iffalse) implements TargetExpression {
|
||||
}
|
||||
|
@ -1,6 +1,4 @@
|
||||
package de.dhbwstuttgart.target.tree.expression;
|
||||
|
||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||
|
||||
public record TargetWhile(TargetExpression cond, TargetExpression body) implements TargetExpression {
|
||||
}
|
||||
|
@ -4,15 +4,29 @@ import de.dhbwstuttgart.bytecode.FunNGenerator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record TargetFunNType(String name, List<TargetType> params) implements TargetSpecializedType {
|
||||
public record TargetFunNType(String name, List<TargetType> funNParams, List<TargetType> params, int returnArguments) implements TargetSpecializedType {
|
||||
|
||||
public static TargetFunNType fromParams(List<TargetType> params) {
|
||||
return fromParams(params, params);
|
||||
public static TargetFunNType fromParams(List<TargetType> params, int returnArguments) {
|
||||
return fromParams(params, params, returnArguments);
|
||||
}
|
||||
|
||||
public static TargetFunNType fromParams(List<TargetType> params, List<TargetType> realParams) {
|
||||
public static TargetFunNType fromParams(List<TargetType> params, List<TargetType> realParams, int returnArguments) {
|
||||
var name = FunNGenerator.getSpecializedClassName(FunNGenerator.getArguments(params), FunNGenerator.getReturnType(params));
|
||||
return new TargetFunNType(name, realParams);
|
||||
return new TargetFunNType(name, params, realParams, returnArguments);
|
||||
}
|
||||
|
||||
public String toMethodDescriptor() {
|
||||
var res = "(";
|
||||
for (var i = 0; i < funNParams.size() - 1; i++) {
|
||||
res += "Ljava/lang/Object;";
|
||||
}
|
||||
res += ")";
|
||||
if (returnArguments > 0) {
|
||||
res += "Ljava/lang/Object;";
|
||||
} else {
|
||||
res += "V";
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -53,19 +53,17 @@ public sealed interface TargetType
|
||||
};
|
||||
}
|
||||
|
||||
static TargetType toTargetType(Class<?> clazz) {
|
||||
if (clazz.isPrimitive()) {
|
||||
if (clazz.equals(boolean.class)) return boolean_;
|
||||
if (clazz.equals(char.class)) return char_;
|
||||
if (clazz.equals(byte.class)) return byte_;
|
||||
if (clazz.equals(short.class)) return short_;
|
||||
if (clazz.equals(int.class)) return int_;
|
||||
if (clazz.equals(long.class)) return long_;
|
||||
if (clazz.equals(float.class)) return float_;
|
||||
if (clazz.equals(double.class)) return double_;
|
||||
}
|
||||
if (clazz.equals(void.class)) return null;
|
||||
return new TargetRefType(clazz.getName());
|
||||
static TargetType toWrapper(TargetType f) {
|
||||
if (f.equals(boolean_)) return Boolean;
|
||||
if (f.equals(char_)) return Char;
|
||||
if (f.equals(byte_)) return Byte;
|
||||
if (f.equals(short_)) return Short;
|
||||
if (f.equals(int_)) return Integer;
|
||||
if (f.equals(long_)) return Long;
|
||||
if (f.equals(float_)) return Float;
|
||||
if (f.equals(double_)) return Double;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
String toSignature();
|
||||
|
@ -10,6 +10,7 @@ import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||
import de.dhbwstuttgart.syntaxtree.type.Void;
|
||||
import de.dhbwstuttgart.typeinference.constraints.GenericsResolver;
|
||||
import de.dhbwstuttgart.typeinference.typeAlgo.TYPEStmt;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -19,14 +20,16 @@ public class MethodAssumption extends Assumption{
|
||||
private RefTypeOrTPHOrWildcardOrGeneric retType;
|
||||
List<? extends RefTypeOrTPHOrWildcardOrGeneric> params;
|
||||
private final Boolean isInherited;
|
||||
private final Boolean isOverridden;
|
||||
|
||||
public MethodAssumption(ClassOrInterface receiver, RefTypeOrTPHOrWildcardOrGeneric retType,
|
||||
List<? extends RefTypeOrTPHOrWildcardOrGeneric> params, TypeScope scope, Boolean isInherited){
|
||||
List<? extends RefTypeOrTPHOrWildcardOrGeneric> params, TypeScope scope, Boolean isInherited, Boolean isOverridden){
|
||||
super(scope);
|
||||
this.receiver = receiver;
|
||||
this.retType = retType;
|
||||
this.params = params;
|
||||
this.isInherited = isInherited;
|
||||
this.isOverridden = isOverridden;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -67,23 +70,14 @@ public class MethodAssumption extends Assumption{
|
||||
* @return
|
||||
*/
|
||||
public RefTypeOrTPHOrWildcardOrGeneric getReceiverType(GenericsResolver resolver) {
|
||||
if (receiver == null) return null;
|
||||
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
|
||||
for(GenericTypeVar gtv : receiver.getGenerics()){
|
||||
//Die Generics werden alle zu TPHs umgewandelt.
|
||||
params.add(resolver.resolve(new GenericRefType(gtv.getName(), new NullToken())));
|
||||
}
|
||||
RefTypeOrTPHOrWildcardOrGeneric receiverType;
|
||||
if(receiver instanceof FunNClass){
|
||||
receiverType = new RefType(new JavaClassName(receiver.getClassName().toString()+"$$"), params, new NullToken()); // new FunN(params);
|
||||
}else{
|
||||
receiverType = new RefType(receiver.getClassName(), params, new NullToken());
|
||||
}
|
||||
|
||||
return receiverType;
|
||||
return TYPEStmt.getReceiverType(receiver, resolver);
|
||||
}
|
||||
|
||||
public Boolean isInherited() {
|
||||
return isInherited;
|
||||
}
|
||||
|
||||
public Boolean isOverridden() {
|
||||
return isOverridden;
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package de.dhbwstuttgart.typeinference.assumptions;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Iterators;
|
||||
import de.dhbwstuttgart.bytecode.CodeGenException;
|
||||
import de.dhbwstuttgart.exceptions.DebugException;
|
||||
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
|
||||
import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
|
||||
import de.dhbwstuttgart.syntaxtree.Method;
|
||||
@ -30,6 +32,14 @@ public class TypeInferenceBlockInformation extends TypeInferenceInformation {
|
||||
public ClassOrInterface getCurrentClass() {
|
||||
return currentClass;
|
||||
}
|
||||
|
||||
public ClassOrInterface getSuperClass() {
|
||||
for (var clazz : getAvailableClasses()) {
|
||||
if (clazz.getClassName().equals(currentClass.getSuperClass().getName()))
|
||||
return clazz;
|
||||
}
|
||||
throw new DebugException("Class has no superclass!");
|
||||
}
|
||||
public TypeScope getCurrentTypeScope() {
|
||||
return methodContext;
|
||||
}
|
||||
|
@ -8,7 +8,8 @@ import java.util.Set;
|
||||
|
||||
public class Constraint<A> extends HashSet<A> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private Boolean isInherited = false;//wird nur für die Method-Constraints benoetigt
|
||||
private Boolean isInherited = false;//wird beides nur für die Method-Constraints benoetigt
|
||||
private Boolean isImplemented = false;
|
||||
|
||||
/*
|
||||
* wird verwendet um bei der Codegenerierung die richtige Methoden - Signatur
|
||||
@ -22,12 +23,14 @@ public class Constraint<A> extends HashSet<A> {
|
||||
super();
|
||||
}
|
||||
|
||||
public Constraint(Boolean isInherited) {
|
||||
public Constraint(Boolean isInherited, Boolean isImplemented) {
|
||||
this.isInherited = isInherited;
|
||||
this.isImplemented = isImplemented;
|
||||
}
|
||||
|
||||
public Constraint(Boolean isInherited, Constraint<A> extendConstraint, Set<A> methodSignatureConstraint) {
|
||||
public Constraint(Boolean isInherited, Boolean isImplemented, Constraint<A> extendConstraint, Set<A> methodSignatureConstraint) {
|
||||
this.isInherited = isInherited;
|
||||
this.isImplemented = isImplemented;
|
||||
this.extendConstraint = extendConstraint;
|
||||
this.methodSignatureConstraint = methodSignatureConstraint;
|
||||
}
|
||||
@ -40,6 +43,10 @@ public class Constraint<A> extends HashSet<A> {
|
||||
return isInherited;
|
||||
}
|
||||
|
||||
public Boolean isImplemented() {
|
||||
return isImplemented;
|
||||
}
|
||||
|
||||
public Constraint<A> getExtendConstraint() {
|
||||
return extendConstraint;
|
||||
}
|
||||
@ -57,7 +64,8 @@ public class Constraint<A> extends HashSet<A> {
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return super.toString() + "\nisInherited = " + isInherited
|
||||
return super.toString() + "\nisInherited = " + isInherited + " isOveridden = " + isImplemented
|
||||
+ methodSignatureConstraint
|
||||
//" + extendsContraint: " + (extendConstraint != null ? extendConstraint.toStringBase() : "null" )
|
||||
+ "\n" ;
|
||||
}
|
||||
|
@ -71,12 +71,13 @@ public class ConstraintSet<A> {
|
||||
|
||||
for(Set<Constraint<A>> oderConstraint : oderConstraints){
|
||||
newOder.add(
|
||||
oderConstraint.parallelStream().map((Constraint<A> as) -> {
|
||||
oderConstraint.stream().map((Constraint<A> as) -> {
|
||||
|
||||
Constraint<B> newConst = as.stream()
|
||||
.map(o)
|
||||
.collect(Collectors.toCollection((
|
||||
() -> new Constraint<B> (as.isInherited(),
|
||||
as.isImplemented(),
|
||||
(as.getExtendConstraint() != null)
|
||||
? as.getExtendConstraint().stream().map(o).collect(Collectors.toCollection(Constraint::new))
|
||||
: null,
|
||||
|
@ -15,19 +15,17 @@ import java.util.*;
|
||||
|
||||
public class TYPE {
|
||||
|
||||
private final Collection<SourceFile> sfs;
|
||||
private final SourceFile sf;
|
||||
private final Set<ClassOrInterface> allAvailableClasses;
|
||||
|
||||
public TYPE(Collection<SourceFile> sourceFiles, Set<ClassOrInterface> allAvailableClasses){
|
||||
sfs = sourceFiles;
|
||||
public TYPE(SourceFile sf, Set<ClassOrInterface> allAvailableClasses){
|
||||
this.sf = sf;
|
||||
this.allAvailableClasses = allAvailableClasses;
|
||||
}
|
||||
|
||||
public ConstraintSet getConstraints() {
|
||||
ConstraintSet ret = new ConstraintSet();
|
||||
for(SourceFile sf : sfs)
|
||||
for (ClassOrInterface cl : sf.KlassenVektor) {
|
||||
System.out.println(sf.availableClasses);
|
||||
var allClasses = new HashSet<ClassOrInterface>();
|
||||
allClasses.addAll(allAvailableClasses);
|
||||
allClasses.addAll(sf.availableClasses);
|
||||
|
@ -1,6 +1,7 @@
|
||||
//PL 2018-12-19: Merge chekcen
|
||||
package de.dhbwstuttgart.typeinference.typeAlgo;
|
||||
|
||||
import java.sql.Ref;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -245,6 +246,9 @@ public class TYPEStmt implements StatementVisitor {
|
||||
constraintsSet.addUndConstraint(new Pair(unaryExpr.expr.getType(), number, PairOperator.SMALLERNEQDOT, loc(unaryExpr.getOffset())));
|
||||
// The type of the postfix increment expression is the type of the variable
|
||||
constraintsSet.addUndConstraint(new Pair(unaryExpr.expr.getType(), unaryExpr.getType(), PairOperator.EQUALSDOT, loc(unaryExpr.getOffset())));
|
||||
} 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(), new RefType(ASTFactory.createClass(java.lang.Boolean.class).getClassName(), new NullToken()), PairOperator.EQUALSDOT, loc(unaryExpr.getOffset())));
|
||||
} else {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
@ -256,7 +260,15 @@ public class TYPEStmt implements StatementVisitor {
|
||||
public void visit(BinaryExpr binary) {
|
||||
binary.lexpr.accept(this);
|
||||
binary.rexpr.accept(this);
|
||||
if (binary.operation.equals(BinaryExpr.Operator.DIV) || binary.operation.equals(BinaryExpr.Operator.MUL) || binary.operation.equals(BinaryExpr.Operator.MOD) || binary.operation.equals(BinaryExpr.Operator.ADD) || binary.operation.equals(BinaryExpr.Operator.SUB)) {
|
||||
if (binary.operation.equals(BinaryExpr.Operator.DIV)
|
||||
|| binary.operation.equals(BinaryExpr.Operator.MUL)
|
||||
|| binary.operation.equals(BinaryExpr.Operator.MOD)
|
||||
|| binary.operation.equals(BinaryExpr.Operator.ADD)
|
||||
|| binary.operation.equals(BinaryExpr.Operator.SUB)
|
||||
|| binary.operation.equals(BinaryExpr.Operator.OR)
|
||||
|| binary.operation.equals(BinaryExpr.Operator.AND)
|
||||
|| binary.operation.equals(BinaryExpr.Operator.XOR)) {
|
||||
|
||||
Set<Constraint<Pair>> numericAdditionOrStringConcatenation = new HashSet<>();
|
||||
|
||||
// TODO PL 2018-11-06
|
||||
@ -476,6 +488,16 @@ public class TYPEStmt implements StatementVisitor {
|
||||
aThrow.expr.accept(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Ternary ternary) {
|
||||
ternary.cond.accept(this);
|
||||
ternary.iftrue.accept(this);
|
||||
ternary.iffalse.accept(this);
|
||||
constraintsSet.addUndConstraint(new Pair(ternary.cond.getType(), bool, PairOperator.EQUALSDOT));
|
||||
constraintsSet.addUndConstraint(new Pair(ternary.iftrue.getType(), ternary.getType(), PairOperator.SMALLERDOT));
|
||||
constraintsSet.addUndConstraint(new Pair(ternary.iffalse.getType(), ternary.getType(), PairOperator.SMALLERDOT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Return returnExpr) {
|
||||
returnExpr.retexpr.accept(this);
|
||||
@ -492,6 +514,11 @@ public class TYPEStmt implements StatementVisitor {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Continue aContinue) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(StaticClassName staticClassName) {
|
||||
// Hier entstehen keine Constraints
|
||||
@ -499,7 +526,13 @@ public class TYPEStmt implements StatementVisitor {
|
||||
|
||||
@Override
|
||||
public void visit(Super aSuper) {
|
||||
throw new NotImplementedException();
|
||||
var superClass = info.getSuperClass();
|
||||
var params = new ArrayList<RefTypeOrTPHOrWildcardOrGeneric>();
|
||||
for (var gtv : superClass.getGenerics()) {
|
||||
params.add(new GenericRefType(gtv.getName(), aSuper.getOffset()));
|
||||
}
|
||||
var superType = new RefType(superClass.getClassName(), params, aSuper.getOffset());
|
||||
constraintsSet.addUndConstraint(new Pair(aSuper.getType(), superType, PairOperator.EQUALSDOT, loc(aSuper.getOffset())));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -541,7 +574,10 @@ public class TYPEStmt implements StatementVisitor {
|
||||
|
||||
@Override
|
||||
public void visit(DoStmt whileStmt) {
|
||||
throw new NotImplementedException();
|
||||
RefType booleanType = new RefType(ASTFactory.createClass(java.lang.Boolean.class).getClassName(), new NullToken());
|
||||
whileStmt.expr.accept(this);
|
||||
constraintsSet.addUndConstraint(new Pair(whileStmt.expr.getType(), booleanType, PairOperator.EQUALSDOT, loc(whileStmt.expr.getOffset())));
|
||||
whileStmt.loopBlock.accept(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -559,20 +595,17 @@ public class TYPEStmt implements StatementVisitor {
|
||||
@Override
|
||||
public void visit(SuperCall superCall) {
|
||||
Set<Constraint<Pair>> methodConstraints = new HashSet<>();
|
||||
for (var clazz : info.getAvailableClasses()) {
|
||||
if (clazz.getClassName().equals(info.getCurrentClass().getSuperClass().getName())) {
|
||||
var clazz = info.getSuperClass();
|
||||
for (var ctor : clazz.getConstructors()) {
|
||||
var params = convertParams(ctor.getParameterList(), info);
|
||||
if (params.size() != superCall.arglist.getArguments().size()) continue;
|
||||
var assumption = new MethodAssumption(null, new Void(new NullToken()), params, createTypeScope(clazz, ctor), ctor.isInherited);
|
||||
var assumption = new MethodAssumption(null, new Void(new NullToken()), params, createTypeScope(clazz, ctor), ctor.isInherited, false);
|
||||
|
||||
GenericsResolver resolver = getResolverInstance();
|
||||
Set<Constraint<Pair>> oneMethodConstraints = generateConstraint(superCall, assumption, info, resolver);
|
||||
methodConstraints.addAll(oneMethodConstraints);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
constraintsSet.addUndConstraint(new Pair(superCall.receiver.getType(), getReceiverType(info.getSuperClass(), getResolverInstance()), PairOperator.EQUALSDOT));
|
||||
constraintsSet.addOderConstraint(methodConstraints);
|
||||
}
|
||||
|
||||
@ -582,23 +615,41 @@ public class TYPEStmt implements StatementVisitor {
|
||||
for (var ctor : info.getCurrentClass().getConstructors()) {
|
||||
var params = convertParams(ctor.getParameterList(), info);
|
||||
if (params.size() != thisCall.arglist.getArguments().size()) continue;
|
||||
var assumption = new MethodAssumption(null, new Void(new NullToken()), params, createTypeScope(info.getCurrentClass(), ctor), ctor.isInherited);
|
||||
var assumption = new MethodAssumption(null, new Void(new NullToken()), params, createTypeScope(info.getCurrentClass(), ctor), ctor.isInherited, false);
|
||||
|
||||
GenericsResolver resolver = getResolverInstance();
|
||||
Set<Constraint<Pair>> oneMethodConstraints = generateConstraint(thisCall, assumption, info, resolver);
|
||||
methodConstraints.addAll(oneMethodConstraints);
|
||||
}
|
||||
constraintsSet.addUndConstraint(new Pair(thisCall.receiver.getType(), getReceiverType(info.getCurrentClass(), getResolverInstance()), PairOperator.EQUALSDOT));
|
||||
constraintsSet.addOderConstraint(methodConstraints);
|
||||
}
|
||||
|
||||
public static RefTypeOrTPHOrWildcardOrGeneric getReceiverType(ClassOrInterface receiver, GenericsResolver resolver) {
|
||||
if (receiver == null) return null;
|
||||
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
|
||||
for(GenericTypeVar gtv : receiver.getGenerics()){
|
||||
//Die Generics werden alle zu TPHs umgewandelt.
|
||||
params.add(resolver.resolve(new GenericRefType(gtv.getName(), new NullToken())));
|
||||
}
|
||||
RefTypeOrTPHOrWildcardOrGeneric receiverType;
|
||||
if(receiver instanceof FunNClass){
|
||||
receiverType = new RefType(new JavaClassName(receiver.getClassName().toString()+"$$"), params, new NullToken()); // new FunN(params);
|
||||
}else{
|
||||
receiverType = new RefType(receiver.getClassName(), params, new NullToken());
|
||||
}
|
||||
|
||||
return receiverType;
|
||||
}
|
||||
|
||||
/*
|
||||
* METHOD CALL Section:
|
||||
*/
|
||||
|
||||
protected Set<Constraint<Pair>> generateConstraint(MethodCall forMethod, MethodAssumption assumption, TypeInferenceBlockInformation info, GenericsResolver resolver) {
|
||||
Constraint<Pair> methodConstraint, extendsMethodConstraint;
|
||||
methodConstraint = new Constraint<>(assumption.isInherited());
|
||||
extendsMethodConstraint = new Constraint<>(assumption.isInherited());// PL 2023-01-24: Ersetzt die Dopplung in visit(MethodCall)
|
||||
methodConstraint = new Constraint<>(assumption.isInherited(), assumption.isOverridden());
|
||||
extendsMethodConstraint = new Constraint<>(assumption.isInherited(), assumption.isOverridden());// PL 2023-01-24: Ersetzt die Dopplung in visit(MethodCall)
|
||||
|
||||
ClassOrInterface receiverCl = assumption.getReceiver();
|
||||
/*
|
||||
@ -640,7 +691,8 @@ public class TYPEStmt implements StatementVisitor {
|
||||
|
||||
Set<Pair> methodSignatureConstraint = generatemethodSignatureConstraint(forMethod, assumption, info, resolver);
|
||||
|
||||
System.out.println("methodSignatureConstraint; " + methodSignatureConstraint);
|
||||
//System.out.println("methodSignatureConstraint: " + methodSignatureConstraint);
|
||||
//System.out.println("methodConstraint: " + methodConstraint);
|
||||
|
||||
methodConstraint.setmethodSignatureConstraint(methodSignatureConstraint);
|
||||
extendsMethodConstraint.setmethodSignatureConstraint(methodSignatureConstraint);
|
||||
@ -648,6 +700,7 @@ public class TYPEStmt implements StatementVisitor {
|
||||
Set<Constraint<Pair>> ret = new HashSet<>();
|
||||
ret.add(methodConstraint);
|
||||
ret.add(extendsMethodConstraint);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -671,7 +724,6 @@ public class TYPEStmt implements StatementVisitor {
|
||||
Set<Pair> ret = new HashSet<>();
|
||||
|
||||
for (int i = 0; i < foMethod.arglist.getArguments().size(); i++) {
|
||||
|
||||
// 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));
|
||||
|
||||
@ -702,14 +754,14 @@ public class TYPEStmt implements StatementVisitor {
|
||||
public RefTypeOrTPHOrWildcardOrGeneric getReturnType() {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}, false));
|
||||
}, false, false));
|
||||
}
|
||||
for (ClassOrInterface cl : info.getAvailableClasses()) {
|
||||
for (Method m : cl.getMethods()) {
|
||||
if (m.getName().equals(name) && m.getParameterList().getFormalparalist().size() == numArgs) {
|
||||
RefTypeOrTPHOrWildcardOrGeneric retType = m.getReturnType();// info.checkGTV(m.getReturnType());
|
||||
|
||||
ret.add(new MethodAssumption(cl, retType, convertParams(m.getParameterList(), info), createTypeScope(cl, m), m.isInherited));
|
||||
ret.add(new MethodAssumption(cl, retType, convertParams(m.getParameterList(), info), createTypeScope(cl, m), m.isInherited, m.isImplemented));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -740,7 +792,8 @@ public class TYPEStmt implements StatementVisitor {
|
||||
if (cl.getClassName().equals(ofType.getName())) {
|
||||
for (Method m : cl.getConstructors()) {
|
||||
if (m.getParameterList().getFormalparalist().size() == argList.getArguments().size()) {
|
||||
ret.add(new MethodAssumption(cl, cl.generateTypeOfThisClass(), convertParams(m.getParameterList(), info), createTypeScope(cl, m), m.isInherited));
|
||||
var params = convertParams(m.getParameterList(), info);
|
||||
ret.add(new MethodAssumption(cl, cl.generateTypeOfThisClass(), params, createTypeScope(cl, m), m.isInherited, m.isImplemented));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -755,6 +808,12 @@ public class TYPEStmt implements StatementVisitor {
|
||||
methodConstraint.add(new Pair(assumption.getReturnType(resolver), forConstructor.getType(), PairOperator.SMALLERDOT, loc(forConstructor.getOffset())));
|
||||
// WELCHEN SINN MACHT DIESER CONSTRAINT???
|
||||
methodConstraint.addAll(generateParameterConstraints(forConstructor, assumption, info, resolver));
|
||||
|
||||
Set<Pair> methodSignatureConstraint = generatemethodSignatureConstraint(forConstructor, assumption, info, resolver);
|
||||
methodConstraint.setmethodSignatureConstraint(methodSignatureConstraint);
|
||||
|
||||
methodConstraint.addAll(methodSignatureConstraint);
|
||||
|
||||
return methodConstraint;
|
||||
}
|
||||
|
||||
|
@ -79,9 +79,10 @@ public class Match implements IMatch {
|
||||
// SUBST - Rule
|
||||
if(lhsType instanceof PlaceholderType) {
|
||||
mgu.add((PlaceholderType) lhsType, rhsType);
|
||||
termsList = termsList.stream().map(mgu::applyleft).collect(Collectors.toCollection(ArrayList::new));
|
||||
idx = idx+1 == termsList.size() ? 0 : idx+1;
|
||||
continue;
|
||||
//PL 2024-04-08 falsch da es sich nicht um Unifikation handelt
|
||||
//termsList = termsList.stream().map(mgu::applyleft).collect(Collectors.toCollection(ArrayList::new));
|
||||
//continue;
|
||||
}
|
||||
|
||||
idx++;
|
||||
|
@ -12,21 +12,14 @@ import java.util.Stack;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
import de.dhbwstuttgart.exceptions.DebugException;
|
||||
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
|
||||
import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
|
||||
import de.dhbwstuttgart.typeinference.unify.interfaces.IRuleSet;
|
||||
import de.dhbwstuttgart.typeinference.unify.model.ExtendsType;
|
||||
import de.dhbwstuttgart.typeinference.unify.model.FunNType;
|
||||
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
|
||||
import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
|
||||
import de.dhbwstuttgart.typeinference.unify.model.ReferenceType;
|
||||
import de.dhbwstuttgart.typeinference.unify.model.SuperType;
|
||||
import de.dhbwstuttgart.typeinference.unify.model.TypeParams;
|
||||
import de.dhbwstuttgart.typeinference.unify.model.Unifier;
|
||||
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
|
||||
import de.dhbwstuttgart.typeinference.unify.model.UnifyType;
|
||||
import de.dhbwstuttgart.typeinference.unify.model.WildcardType;
|
||||
import de.dhbwstuttgart.typeinference.unify.model.*;
|
||||
import de.dhbwstuttgart.typeinference.constraints.Constraint;
|
||||
import de.dhbwstuttgart.typeinference.unify.distributeVariance;
|
||||
|
||||
@ -709,9 +702,10 @@ public class RuleSet implements IRuleSet{
|
||||
x -> uni.apply(pair,x)).collect(Collectors.toCollection((b.getExtendConstraint() != null)
|
||||
? () -> new Constraint<UnifyPair>(
|
||||
b.isInherited(),
|
||||
b.isImplemented(),
|
||||
b.getExtendConstraint().stream().map(x -> uni.apply(pair,x)).collect(Collectors.toCollection(Constraint::new)),
|
||||
b.getmethodSignatureConstraint().stream().map(x -> uni.apply(pair,x)).collect(Collectors.toCollection(HashSet::new)))
|
||||
: () -> new Constraint<UnifyPair>(b.isInherited())
|
||||
: () -> new Constraint<UnifyPair>(b.isInherited(), b.isImplemented())
|
||||
));
|
||||
oderConstraints.replaceAll(oc -> oc.stream().map(applyUni).collect(Collectors.toCollection(HashSet::new)));
|
||||
/*
|
||||
@ -892,37 +886,41 @@ public class RuleSet implements IRuleSet{
|
||||
|
||||
//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();
|
||||
|
||||
// The generic Version of typeFI (FI<a1, a2, a3, ... >)
|
||||
UnifyType typeDgen = opt.get();
|
||||
|
||||
// Actually greater+ because the types are ensured to have different names
|
||||
Set<UnifyType> smaller = fc.getChildren(typeDgen);
|
||||
opt = smaller.stream().filter(x -> x.getName().equals(pair.getLhsType().getName())).findAny();
|
||||
|
||||
if(!opt.isPresent())
|
||||
if (!(typeFI instanceof ReferenceType refType) || !(refType instanceof FunInterfaceType intf))
|
||||
return Optional.empty();
|
||||
|
||||
TypeParams typeDParams = typeFI.getTypeParams();
|
||||
TypeParams typeDgenParams = typeDgen.getTypeParams();
|
||||
|
||||
Unifier unif = Unifier.identity();
|
||||
for(int i = 0; i < typeDParams.size(); i++) {
|
||||
if (typeDgenParams.get(i) instanceof PlaceholderType)
|
||||
unif.add((PlaceholderType) typeDgenParams.get(i), typeDParams.get(i));
|
||||
else System.out.println("ERROR");
|
||||
}
|
||||
|
||||
UnifyType newRhsType = opt.get();
|
||||
var fiArgs = intf.getFunctionalInterfaceTypeArguments(refType);
|
||||
var retType = fiArgs.getFirst();
|
||||
var lhsArgs = intf.getFunctionalInterfaceTypeArguments(lhsType);
|
||||
var lhsRet = lhsArgs.getFirst();
|
||||
|
||||
Set<UnifyPair> result = new HashSet<>();
|
||||
result.add(new UnifyPair(lhsType, unif.apply(newRhsType), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair()));
|
||||
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);
|
||||
}
|
||||
|
@ -253,13 +253,14 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
|
||||
one = true;
|
||||
Set<UnifyPair> neweq = new HashSet<>(eq);
|
||||
/* 1-elementige Oder-Constraints werden in und-Constraints umgewandelt */
|
||||
Set<UnifyPair> methodSignatureConstraint = new HashSet<>();
|
||||
oderConstraintsField.stream()
|
||||
.filter(x -> x.size()==1)
|
||||
.map(y -> y.stream().findFirst().get()).forEach(x -> neweq.addAll(x));
|
||||
.map(y -> y.stream().findFirst().get()).forEach(x -> { neweq.addAll(x); methodSignatureConstraint.addAll(x.getmethodSignatureConstraint());} );
|
||||
ArrayList<Set<Constraint<UnifyPair>>> remainingOderconstraints = oderConstraintsField.stream()
|
||||
.filter(x -> x.size()>1)
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
Set<Set<UnifyPair>> res = unify(neweq, remainingOderconstraints, fc, parallel, rekTiefeField, new HashSet<>());
|
||||
Set<Set<UnifyPair>> res = unify(neweq, remainingOderconstraints, fc, parallel, rekTiefeField, methodSignatureConstraint);
|
||||
noOfThread--;
|
||||
try {
|
||||
logFile.close();
|
||||
@ -594,15 +595,17 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
|
||||
/* methodconstraintsets werden zum Ergebnis hinzugefuegt
|
||||
* Anfang
|
||||
*/
|
||||
//System.out.println("methodSignatureConstraint Return: " + methodSignatureConstraint);
|
||||
//System.out.println("methodSignatureConstraint Return: " + methodSignatureConstraint + "\n");
|
||||
eqPrimePrimeSet.forEach(x -> x.addAll(methodSignatureConstraint));
|
||||
|
||||
//Substitutionen in methodcontraintsets werdne ausgeführt
|
||||
/* PL auskommentiert 2024-05-02
|
||||
eqPrimePrimeSet = eqPrimePrimeSet.stream().map(
|
||||
x -> { Optional<Set<UnifyPair>> help = rules.subst(x);
|
||||
return help.isPresent() ?
|
||||
help.get():
|
||||
x; }).collect(Collectors.toSet());
|
||||
*/
|
||||
/*
|
||||
* Ende
|
||||
*/
|
||||
@ -813,6 +816,7 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
|
||||
writeLog("nextSetasList: " + nextSetasList.toString());
|
||||
if (variance == 1) {
|
||||
a = oup.max(nextSetasList.iterator());
|
||||
writeLog("Max: a in " + variance + " "+ a);
|
||||
nextSetasList.remove(a);
|
||||
if (oderConstraint) {
|
||||
nextSetasListOderConstraints.add(((Constraint<UnifyPair>)a).getExtendConstraint());
|
||||
@ -885,7 +889,11 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
|
||||
|
||||
if (oderConstraint) {//Methodconstraints werden abgespeichert für die Bytecodegenerierung von Methodenaufrufen
|
||||
methodSignatureConstraint.addAll(((Constraint<UnifyPair>)a).getmethodSignatureConstraint());
|
||||
//System.out.println("ERSTELLUNG: " +methodSignatureConstraint);
|
||||
writeLog("ERSTELLUNG methodSignatureConstraint: " + methodSignatureConstraint);
|
||||
//System.out.println("ERSTELLUNG methodSignatureConstraint: " +noOfThread+" "+methodSignatureConstraint);
|
||||
//System.out.println("a: " +a);
|
||||
//System.out.println("eq: " +eq);
|
||||
//System.out.println();
|
||||
}
|
||||
|
||||
i++;
|
||||
@ -1134,14 +1142,22 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
|
||||
writeLog("a in " + variance + " "+ a);
|
||||
writeLog("nextSetasListRest: " + nextSetasListRest.toString());
|
||||
}
|
||||
|
||||
//Fuer parallele Berechnung der Oder-Contraints wird methodSignature kopiert
|
||||
//und jeweils die methodSignature von a bzw. nSaL wieder gelöscht, wenn es keine Lösung ist.
|
||||
Set<UnifyPair> methodSignatureConstraintForParallel = new HashSet<>(methodSignatureConstraint);
|
||||
Set<UnifyPair> nSaL = a;
|
||||
|
||||
while (!nextSetasListRest.isEmpty()) {
|
||||
Set<UnifyPair> nSaL = nextSetasListRest.remove(0);
|
||||
methodSignatureConstraintForParallel.removeAll(((Constraint<UnifyPair>)nSaL).getmethodSignatureConstraint());
|
||||
nSaL = nextSetasListRest.remove(0);
|
||||
nextSetasList.remove(nSaL); //PL einkommentiert 20-02-03
|
||||
methodSignatureConstraintForParallel.addAll(((Constraint<UnifyPair>)nSaL).getmethodSignatureConstraint());
|
||||
Set<UnifyPair> newEq = new HashSet<>(eq);
|
||||
Set<Set<UnifyPair>> newElems = new HashSet<>(elems);
|
||||
List<Set<Constraint<UnifyPair>>> newOderConstraints = new ArrayList<>(oderConstraints);
|
||||
newElems.add(nSaL);
|
||||
TypeUnify2Task fork = new TypeUnify2Task(newElems, newEq, newOderConstraints, nSaL, fc, parallel, logFile, log, rekTiefe, urm, usedTasks, methodSignatureConstraint);
|
||||
TypeUnify2Task fork = new TypeUnify2Task(newElems, newEq, newOderConstraints, nSaL, fc, parallel, logFile, log, rekTiefe, urm, usedTasks, new HashSet<>(methodSignatureConstraintForParallel));
|
||||
forks.add(fork);
|
||||
synchronized(usedTasks) {
|
||||
if (this.myIsCancelled()) {
|
||||
@ -1338,12 +1354,15 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
|
||||
while(aParDefIt.hasNext()) {
|
||||
Set<UnifyPair> a_new = aParDefIt.next();
|
||||
List<Set<UnifyPair>> smallerSetasList = oup.smallerThan(a_new, nextSetasList);
|
||||
writeLog("smallerSetasList: " + smallerSetasList);
|
||||
List<Set<UnifyPair>> notInherited = smallerSetasList.stream()
|
||||
.filter(x -> !((Constraint<UnifyPair>)x).isInherited())
|
||||
.filter(x -> !((Constraint<UnifyPair>)x).isInherited() && !((Constraint<UnifyPair>)x).isImplemented())
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
writeLog("notInherited: " + notInherited+"\n");
|
||||
List<Set<UnifyPair>> notErased = new ArrayList<>();
|
||||
notInherited.stream().forEach(x -> { notErased.addAll(oup.smallerEqThan(x, smallerSetasList)); });
|
||||
List<Set<UnifyPair>> erased = new ArrayList<>(smallerSetasList);
|
||||
writeLog("notErased: " + notErased+"\n");
|
||||
erased.removeAll(notErased);
|
||||
nextSetasList.removeAll(erased);
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package de.dhbwstuttgart.typeinference.unify.interfaces;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -3,6 +3,8 @@ package de.dhbwstuttgart.typeinference.unify.model;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.sql.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
@ -20,7 +22,12 @@ import com.google.common.collect.Ordering;
|
||||
|
||||
//PL 18-02-05/18-04-05 Unifier durch Matcher ersetzt
|
||||
//muss greater noch ersetzt werden ja erledigt 18--04-05
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
import de.dhbwstuttgart.parser.SourceLoc;
|
||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||
import de.dhbwstuttgart.typeinference.unify.MartelliMontanariUnify;
|
||||
|
||||
import de.dhbwstuttgart.typeinference.unify.Match;
|
||||
@ -29,6 +36,7 @@ import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
|
||||
import de.dhbwstuttgart.typeinference.unify.interfaces.IUnify;
|
||||
import de.dhbwstuttgart.util.Pair;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
import org.apache.commons.io.output.NullWriter;
|
||||
|
||||
/**
|
||||
* The finite closure for the type unification
|
||||
@ -37,6 +45,8 @@ import org.antlr.v4.runtime.Token;
|
||||
public class FiniteClosure //extends Ordering<UnifyType> //entfernt PL 2018-12-11
|
||||
implements IFiniteClosure {
|
||||
|
||||
final JavaTXCompiler compiler;
|
||||
|
||||
Writer logFile;
|
||||
static Boolean log = false;
|
||||
public void setLogTrue() {
|
||||
@ -71,7 +81,8 @@ implements IFiniteClosure {
|
||||
/**
|
||||
* Creates a new instance using the inheritance tree defined in the pairs.
|
||||
*/
|
||||
public FiniteClosure(Set<UnifyPair> pairs, Writer logFile) {
|
||||
public FiniteClosure(Set<UnifyPair> pairs, Writer logFile, JavaTXCompiler compiler) {
|
||||
this.compiler = compiler;
|
||||
this.logFile = logFile;
|
||||
this.pairs = new HashSet<>(pairs);
|
||||
inheritanceGraph = new HashMap<UnifyType, Node<UnifyType>>();
|
||||
@ -130,6 +141,10 @@ implements IFiniteClosure {
|
||||
}
|
||||
}
|
||||
|
||||
public FiniteClosure(Set<UnifyPair> constraints, Writer writer) {
|
||||
this(constraints, writer, null);
|
||||
}
|
||||
|
||||
void testSmaller() {
|
||||
UnifyType tq1, tq2, tq3;
|
||||
tq1 = new ExtendsType(PlaceholderType.freshPlaceholder());
|
||||
@ -684,7 +699,7 @@ implements IFiniteClosure {
|
||||
*/
|
||||
|
||||
public int compare (UnifyType left, UnifyType right, PairOperator pairop) {
|
||||
//try {logFile.write("left: "+ left + " right: " + right + " pairop: " + pairop);} catch (IOException ie) {}
|
||||
try {logFile.write("left: "+ left + " right: " + right + " pairop: " + pairop +"\n");} catch (IOException ie) {}
|
||||
if (left.getName().equals("Matrix") || right.getName().equals("Matrix"))
|
||||
System.out.println("");
|
||||
/*
|
||||
@ -741,15 +756,15 @@ implements IFiniteClosure {
|
||||
HashSet<UnifyPair> hs = new HashSet<>();
|
||||
hs.add(up);
|
||||
Set<UnifyPair> smallerRes = unifyTask.applyTypeUnificationRules(hs, this);
|
||||
/*
|
||||
//if (left.getName().equals("Matrix") || right.getName().equals("Matrix"))
|
||||
|
||||
//if (left.getName().equals("Vector") || right.getName().equals("AbstractList"))
|
||||
{try {
|
||||
logFile.write("\nsmallerRes: " + smallerRes);//"smallerHash: " + greaterHash.toString());
|
||||
logFile.flush();
|
||||
}
|
||||
catch (IOException e) {
|
||||
System.err.println("no LogFile");}}
|
||||
*/
|
||||
|
||||
//Gleichungen der Form a <./=. Theta oder Theta <./=. a oder a <./=. b sind ok.
|
||||
Predicate<UnifyPair> delFun = x -> !((x.getLhsType() instanceof PlaceholderType ||
|
||||
x.getRhsType() instanceof PlaceholderType)
|
||||
@ -757,6 +772,12 @@ implements IFiniteClosure {
|
||||
((WildcardType)x.getLhsType()).getWildcardedType().equals(x.getRhsType()))
|
||||
);
|
||||
long smallerLen = smallerRes.stream().filter(delFun).count();
|
||||
try {
|
||||
logFile.write("\nsmallerLen: " + smallerLen +"\n");
|
||||
logFile.flush();
|
||||
}
|
||||
catch (IOException e) {
|
||||
System.err.println("no LogFile");}
|
||||
if (smallerLen == 0) return -1;
|
||||
else {
|
||||
up = new UnifyPair(right, left, pairop);
|
||||
@ -764,15 +785,15 @@ implements IFiniteClosure {
|
||||
hs = new HashSet<>();
|
||||
hs.add(up);
|
||||
Set<UnifyPair> greaterRes = unifyTask.applyTypeUnificationRules(hs, this);
|
||||
/*
|
||||
//if (left.getName().equals("Matrix") || right.getName().equals("Matrix"))
|
||||
|
||||
//if (left.getName().equals("Vector") || right.getName().equals("AbstractList"))
|
||||
{try {
|
||||
logFile.write("\ngreaterRes: " + greaterRes);//"smallerHash: " + greaterHash.toString());
|
||||
logFile.flush();
|
||||
}
|
||||
catch (IOException e) {
|
||||
System.err.println("no LogFile");}}
|
||||
*/
|
||||
|
||||
//Gleichungen der Form a <./=. Theta oder Theta <./=. a oder a <./=. b sind ok.
|
||||
long greaterLen = greaterRes.stream().filter(delFun).count();
|
||||
if (greaterLen == 0) return 1;
|
||||
|
@ -0,0 +1,49 @@
|
||||
package de.dhbwstuttgart.typeinference.unify.model;
|
||||
|
||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class FunInterfaceType extends ReferenceType {
|
||||
final List<UnifyType> intfArgTypes;
|
||||
final UnifyType intfReturnType;
|
||||
final List<String> generics;
|
||||
|
||||
public FunInterfaceType(String name, TypeParams params, List<UnifyType> intfArgTypes, UnifyType intfReturnType, List<String> generics) {
|
||||
super(name, params);
|
||||
this.intfArgTypes = intfArgTypes;
|
||||
this.intfReturnType = intfReturnType;
|
||||
this.generics = generics;
|
||||
}
|
||||
|
||||
public List<UnifyType> getFunctionalInterfaceTypeArguments(UnifyType t) {
|
||||
if (t instanceof FunNType) {
|
||||
var ret = new ArrayList<UnifyType>();
|
||||
if (t.getTypeParams().size() > 0) {
|
||||
ret.add(t.getTypeParams().get(t.getTypeParams().size() - 1));
|
||||
ret.addAll(Arrays.asList(t.getTypeParams().get()).subList(0, t.getTypeParams().size() - 1));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
var args = new ArrayList<UnifyType>();
|
||||
args.add(intfReturnType);
|
||||
args.addAll(intfArgTypes);
|
||||
|
||||
// TODO There might be a better way of dealing with this
|
||||
var i = 0;
|
||||
for (var generic : generics) {
|
||||
for (var j = 0; j < args.size(); j++) {
|
||||
if (args.get(j).getName().equals(generic))
|
||||
args.set(j, t.getTypeParams().get(i));
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user