1
0

Compare commits

...

66 Commits

Author SHA1 Message Date
9c2c6a3ea9 Alter OL Test 2024-07-01 12:36:22 +02:00
a7ad4fa984 Add OrCOnsTest 2024-06-28 11:32:32 +02:00
fcda301b1e Hack in ASP-Constraint generation for WLP2024 paper Prototype Test 2024-06-10 09:02:26 +02:00
2aa3997f17 Readme 2024-06-07 14:54:27 +02:00
7e37497740 Start ASP Gen after Constraint Generateion 2024-06-07 14:53:47 +02:00
3d2b935c60 Merge branch 'targetBytecode' of https://gitea.hb.dhbw-stuttgart.de/JavaTX/JavaCompilerCore into targetBytecode 2024-05-14 22:53:08 +02:00
db01b0c8dd new file: resources/AllgemeinTest/Box.jav 2024-05-14 22:50:20 +02:00
662756ac18 Merge branch 'targetBytecode' of https://gitea.hb.dhbw-stuttgart.de/JavaTX/JavaCompilerCore into targetBytecode 2024-05-10 16:51:10 +02:00
b0bf41968e Bug325 2024-05-10 16:50:06 +02:00
2221b559ca Implementierungen von Interfaces eingefuegt und Overriding ersetzt durch implementierung
modified:   ../src/main/java/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java

Overriding ersetzt durch implementierung (Umbennennung)
	modified:   ../resources/bytecode/javFiles/Matrix.jav
	modified:   ../src/main/java/de/dhbwstuttgart/syntaxtree/Method.java
	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/constraints/Constraint.java
	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/constraints/ConstraintSet.java
	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java
	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java
	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java
2024-05-10 14:16:23 +02:00
021b7ec9fe Fehler vom vorigen korriert Commit
modified:   ../resources/bytecode/javFiles/Matrix.jav
	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/constraints/Constraint.java
	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/constraints/ConstraintSet.java
	modified:   ../src/test/java/TestComplete.java
2024-05-08 09:07:22 +02:00
154d4823e4 isOverridden eingefuegt.
Problem beim Konvertioeren
	modified:   ../src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java
	modified:   ../src/main/java/de/dhbwstuttgart/syntaxtree/Method.java
	modified:   ../src/main/java/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java
	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java
	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/constraints/Constraint.java
	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/constraints/ConstraintSet.java
	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java
	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java
	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java
	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java
2024-05-08 00:14:21 +02:00
71dfe5d9e1 Bei diesem und vorigen Commit wurde der Bug

geloest.

1. src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java
in der Methode copute wurden die methodSignatureConstraints der bereits zu Beginn
aufegloesten einer Oder Constraints in die Methodconstraints der Unifikation geschrieben
2. Elementtyp der linken Seiten der methodSignatureConstraints wurden von RefTypeOrTPHOrWildcardOrGeneric auf TypePlaceholder geaendert, weil dort nur TypePlaceholder geaendert.
3. src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java
in der Methode prepareBlock wurde der Typ des Rückgabewerts des supercalls von Void auf eine
Freshtpevar gesetzt.
4. src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java
in der unify2-Methode wurde am Ende der Aufruf der Substitution nach Hinzufuegen der
Methodconstraints auskommentiert -> hat zu nicht geloesten Constraints gefuehrt.

	modified:   src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java
	modified:   src/test/java/TestComplete.java
2024-05-02 16:33:37 +02:00
58110c474a mathStrucInteger.jav funktioniert gerade nicht
modified:   resources/bytecode/javFiles/Matrix.jav
	modified:   src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java
	modified:   src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java
	modified:   src/main/java/de/dhbwstuttgart/syntaxtree/statement/MethodCall.java
	modified:   src/main/java/de/dhbwstuttgart/syntaxtree/statement/NewClass.java
	modified:   src/main/java/de/dhbwstuttgart/syntaxtree/statement/SuperCall.java
	modified:   src/main/java/de/dhbwstuttgart/syntaxtree/statement/ThisCall.java
	modified:   src/main/java/de/dhbwstuttgart/typeinference/constraints/Constraint.java
	modified:   src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java
	modified:   src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java
	modified:   src/main/java/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java
2024-05-02 00:13:45 +02:00
df2ec4b1ba Fix , convert captures to correct types 2024-04-30 16:55:40 +02:00
2c66a1d6e6 add class file 2024-04-29 10:27:23 +02:00
c76ee355d8 Add bug for 2024-04-29 10:25:01 +02:00
a5c314c5c5 Fix 2024-04-28 19:25:20 +02:00
cba35a4bec Don't load source files twice 2024-04-27 23:08:15 +02:00
b774281cbb Add Ternary, fix 2024-04-22 12:17:53 +02:00
9358130468 Fix package weirdness? See 2024-04-18 11:51:08 +02:00
708aa64283 Fix current directory not being added to path 2024-04-18 10:31:12 +02:00
c21e5202d6 Fix 2024-04-18 10:20:35 +02:00
b3bd5cde10 Fix tests 2024-04-15 16:44:34 +02:00
df78937ef3 Fix test case a bit 2024-04-15 16:18:25 +02:00
7fb4824f8d Add modulo, fix 2024-04-12 15:40:22 +02:00
e0d71a6003 fix console 2024-04-12 14:17:15 +02:00
49803385cf Fix optional parameters 2024-04-12 13:58:11 +02:00
39d02f792c Deal with multiple source files properly, don't throw all the constraints together 2024-04-12 10:48:13 +02:00
4fc78f494c More poking around 2024-04-10 10:22:34 +02:00
b752219d8c Throw exception if class doesn't exist 2024-04-10 10:03:59 +02:00
ec890356e4 Don't trim stack trace because some tests randomly fail and we need to know why 2024-04-10 09:58:01 +02:00
d405b0c3a2 Merge branch 'targetBytecode' of ssh://gitea.hb.dhbw-stuttgart.de:2222/JavaTX/JavaCompilerCore into targetBytecode 2024-04-10 09:42:47 +02:00
6c8657b7a8 Work on 2024-04-10 09:42:31 +02:00
bcce4cee19 modified: src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntacticSugar.java
Im Visitor ReturnFinder wuder nicht beruecksichtigt, dass auch in einem Lambda-Ausdruck ein Reurn stehen kann, welchen die umgebenden Block nicht beendet.
2024-04-09 18:25:26 +02:00
e6cd4038e2 Fix bytecode error when calling interface functions 2024-04-09 15:52:44 +02:00
e50f941b79 Merge branch 'targetBytecode' of ssh://gitea.hb.dhbw-stuttgart.de:2222/JavaTX/JavaCompilerCore into targetBytecode 2024-04-09 14:59:16 +02:00
cb7d0e22cc Fix 2024-04-09 14:58:43 +02:00
0d5be89310 modified: ../src/main/java/de/dhbwstuttgart/typeinference/unify/Match.java
modified:   ../src/test/java/TestComplete.java
2024-04-09 01:50:42 +02:00
0b7f07108f Fix 2024-04-08 14:25:41 +02:00
6b0816c1c4 Add test for 2024-04-08 14:02:57 +02:00
f66b9099f3 Fix 2024-04-08 13:51:49 +02:00
da74898f9d Fix 2024-04-08 13:18:27 +02:00
46a7f61234 Fix 2024-04-08 11:52:52 +02:00
e59accf7ee Fix 2024-04-08 11:40:46 +02:00
4b110244f2 new file: ../../AllgemeinTest/List.jav 2024-04-07 17:31:05 +02:00
e37040f367 Bug 307 gefixt
Changes to be committed:
	modified:   src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java
	modified:   src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java
	modified:   src/test/java/TestComplete.java
2024-04-03 00:11:01 +02:00
6850a8fa21 Decouple unify from the rest of the code 2024-03-28 10:35:34 +01:00
877e5ed38a Reversing alone would disturb the parameters () 2024-03-27 14:52:15 +01:00
82b4450857 Fix 298 for real this time? 2024-03-27 14:39:43 +01:00
b70e435120 Work on issue 2024-03-27 12:21:57 +01:00
3b14cd609f Revert "Get rid of mutable state, hopefully fix "
This reverts commit bc61fc2e1d.
2024-03-27 09:57:21 +01:00
8fdfbf875b Fix maybe? 2024-03-26 17:31:48 +01:00
bc61fc2e1d Get rid of mutable state, hopefully fix 2024-03-26 16:54:24 +01:00
62f2e05f35 Add test case for 2024-03-26 11:04:03 +01:00
606ce8b82d Implement AND/OR/XOR, fix 2024-03-26 10:54:32 +01:00
c84befae51 Add Negation operator (fixes ) 2024-03-25 17:05:20 +01:00
7f3c1686ec Fix 2024-03-25 15:10:47 +01:00
43da2ffbdc Fix 2024-03-25 14:49:18 +01:00
9472b5c86f Types are weird in this one 2024-03-25 13:51:56 +01:00
7cb0e9dbb7 Taking the super methods parameters should only happen for the types, fix 2024-03-25 13:43:30 +01:00
e07521d9b6 Fix 2024-03-25 12:14:03 +01:00
c2ee12397f Work on issue 2024-03-22 14:54:23 +01:00
e6321ff8bc Fix gtvs being strange, 2024-03-21 17:40:42 +01:00
786e0a7a23 Fix and also call private methods correctly 2024-03-21 11:49:16 +01:00
1c63321b30 Fix 2024-03-20 14:37:15 +01:00
90 changed files with 1562 additions and 463 deletions
README.mdpom.xml
resources
src

9
README.md Normal file

@ -0,0 +1,9 @@
Prototype
run with:
mvn test -Dtest="TestComplete#matrixTest"
mvn test -Dtest="typeinference.JavaTXCompilerTest#importTest"
then the output is in: /tmp/output

@ -53,9 +53,8 @@ http://maven.apache.org/maven-v4_0_0.xsd">
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<compilerArgs>--enable-preview</compilerArgs>
<source>21</source>
<target>21</target>
<source>22</source>
<target>22</target>
</configuration>
</plugin>
<plugin>
@ -66,7 +65,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>

@ -0,0 +1,10 @@
class Box<A> {
A a;
Box(A a) {
this.a = a;
}
}

@ -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);
}
*/
}

@ -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;
}
}

@ -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";
}
}

@ -0,0 +1,4 @@
import java.util.HashSet;
public class Bug301<A> extends HashSet<A> {
}

@ -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>());
}
}

@ -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);
}
}

@ -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);
}
}

@ -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;
}
}

@ -0,0 +1,9 @@
import java.lang.Integer;
import java.lang.String;
public class Bug310 {
Integer i = 3;
public toString() {
return i.toString();
}
}

@ -0,0 +1,10 @@
import java.lang.String;
public class Bug311 {
Bug311A i = new Bug311A();
public toString() {
return i.toString();
}
}
class Bug311A {}

@ -0,0 +1,8 @@
public class Bug312 {
Bug312A i = new Bug312A();
public main() {
if (i == null) {}
}
}
class Bug312A {}

@ -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());
}
}

@ -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();
}
}

@ -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);
}
}

@ -0,0 +1,8 @@
import java.lang.Integer;
import Bug328B;
public class Bug328 extends Bug328B {
public Bug328() {
super(1);
}
}

Binary file not shown.

@ -0,0 +1,3 @@
public class Bug328B {
public Bug328B(int a) {}
}

@ -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;
}
}

@ -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() {
Runnable lam = () -> {
String test = "";
String b = "b";
test = b;
System.out.println(test);};
//lam.run();
import java.lang.Boolean;
import java.lang.Integer;
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;
}
}

@ -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;
}
}

Binary file not shown.

@ -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); }

@ -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";
}
}

@ -0,0 +1,3 @@
package pkg.sub;
public interface Interface {}

@ -6,6 +6,8 @@ import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
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 +16,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,8 +29,9 @@ public class Codegen {
private int lambdaCounter = 0;
private final HashMap<TargetLambdaExpression, TargetMethod> lambdas = new HashMap<>();
private final JavaTXCompiler compiler;
private final ASTToTargetAST converter;
public Codegen(TargetStructure clazz, JavaTXCompiler compiler) {
public Codegen(TargetStructure clazz, JavaTXCompiler compiler, ASTToTargetAST converter) {
this.clazz = clazz;
this.className = clazz.qualifiedName().getClassName();
this.cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS) {
@ -37,6 +41,7 @@ public class Codegen {
}
};
this.compiler = compiler;
this.converter = converter;
}
private record LocalVar(int index, String name, TargetType type) {
@ -281,9 +286,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 +726,49 @@ public class Codegen {
private void generateLambdaExpression(State state, TargetLambdaExpression lambda) {
var mv = state.mv;
String methodName = "apply";
TargetMethod.Signature signature = null;
if (!(state.contextType instanceof TargetFunNType ctx)) {
var intf = compiler.getClass(new JavaClassName(state.contextType.name()));
if (intf != null) {
var method = intf.getMethods().stream().filter(m -> Modifier.isAbstract(m.modifier)).findFirst().orElseThrow();
methodName = method.getName();
var methodParams = new ArrayList<MethodParameter>();
for (var i = 0; i < lambda.signature().parameters().size(); i++) {
var param = lambda.signature().parameters().get(i);
var tpe = converter.convert(method.getParameterList().getParameterAt(i).getType());
methodParams.add(param.withType(tpe));
}
var retType = converter.convert(method.getReturnType());
signature = new TargetMethod.Signature(Set.of(), methodParams, retType);
}
}
if (signature == null) {
signature = new TargetMethod.Signature(Set.of(), lambda.signature().parameters().stream().map(par -> par.withType(TargetType.Object)).toList(), TargetType.Object);
}
signature = new TargetMethod.Signature(
signature.generics(),
signature.parameters().stream().map(par ->
par.withType(par.pattern().type() instanceof TargetGenericType ? TargetType.Object : par.pattern().type())
).toList(),
signature.returnType() instanceof TargetGenericType ? TargetType.Object : signature.returnType()
);
var parameters = new ArrayList<>(lambda.captures());
parameters.addAll(signature.parameters());
var implSignature = new TargetMethod.Signature(Set.of(), parameters, lambda.signature().returnType());
// Normalize
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,17 +776,7 @@ 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()));
@ -752,17 +784,15 @@ public class Codegen {
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();
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))));
mv.visitInvokeDynamicInsn(methodName, descriptor, bootstrap, Type.getType(signature.getSignature()), handle, Type.getType(signature.getDescriptor()));
}
private void generate(State state, TargetExpression expr) {
@ -873,6 +903,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;
}
@ -962,13 +994,34 @@ public class Codegen {
}
case TargetReturn ret: {
if (ret.expression() != null && state.returnType != null) {
var ctype = state.contextType;
state.contextType = state.returnType;
generate(state, ret.expression());
state.contextType = ctype;
boxPrimitive(state, ret.expression().type());
convertTo(state, ret.expression().type(), state.returnType);
mv.visitInsn(ARETURN);
if (state.returnType instanceof TargetPrimitiveType) {
var ctype = state.contextType;
state.contextType = state.returnType;
generate(state, ret.expression());
state.contextType = ctype;
unboxPrimitive(state, state.returnType);
if (state.returnType.equals(TargetType.boolean_)
|| state.returnType.equals(TargetType.char_)
|| state.returnType.equals(TargetType.int_)
|| state.returnType.equals(TargetType.short_)
|| state.returnType.equals(TargetType.byte_))
mv.visitInsn(IRETURN);
else if (state.returnType.equals(TargetType.long_))
mv.visitInsn(LRETURN);
else if (state.returnType.equals(TargetType.float_))
mv.visitInsn(FRETURN);
else if (state.returnType.equals(TargetType.double_))
mv.visitInsn(DRETURN);
} else {
var ctype = state.contextType;
state.contextType = state.returnType;
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,8 +1061,10 @@ 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);
@ -1024,7 +1079,12 @@ public class Codegen {
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 +1111,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);
}

@ -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;
@ -72,18 +66,19 @@ public class JavaTXCompiler {
Boolean resultmodel = true;
public final Map<File, SourceFile> sourceFiles = new HashMap<>();
Boolean log = false; //gibt an ob ein Log-File nach System.getProperty("user.dir")+""/logFiles/"" geschrieben werden soll?
Boolean log = true; //gibt an ob ein Log-File nach System.getProperty("user.dir")+""/logFiles/"" geschrieben werden soll?
public volatile UnifyTaskModel usedTasks = new UnifyTaskModel();
private final DirectoryClassLoader classLoader;
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());
if (outputPath != null) path.add(outputPath);
classLoader = new DirectoryClassLoader(path, ClassLoader.getSystemClassLoader());
environment = new CompilationEnvironment(sources);
classPath = contextPath;
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()) {
var importedClasses = new ArrayList<ClassOrInterface>();
for (JavaClassName name : source.getValue().getImports()) {
importedClasses.addAll(getAvailableClasses(name));
}
for (Class c : CompilationEnvironment.loadDefaultPackageClasses(source.getValue().getPkgName(), source.getKey(), this)) {
ClassOrInterface importedClass = ASTFactory.createClass(c);
importedClasses.add(importedClass);
}
source.getValue().availableClasses.addAll(importedClasses);
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 : sf.getImports()) {
importedClasses.addAll(getAvailableClasses(name));
}
for (File f : this.sourceFiles.keySet()) {
SourceFile sf = sourceFiles.get(f);
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.
for (Class c : CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), sourceFile, this)) {
ClassOrInterface importedClass = ASTFactory.createClass(c);
importedClasses.add(importedClass);
}
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();
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));
}
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, 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,32 +417,29 @@ 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();
allClasses.addAll(getAvailableClasses(sf));
allClasses.addAll(sf.getClasses());
var newClasses = CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), source.getKey(), this).stream().map(ASTFactory::createClass).collect(Collectors.toList());
for (var clazz : newClasses) {
// Don't load classes that get recompiled
if (sf.getClasses().stream().anyMatch(nf -> nf.getClassName().equals(clazz.getClassName())))
continue;
if (allClasses.stream().noneMatch(old -> old.getClassName().equals(clazz.getClassName())))
allClasses.add(clazz);
}
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(), file, this).stream().map(ASTFactory::createClass).collect(Collectors.toSet());
for (var clazz : newClasses) {
// Don't load classes that get recompiled
if (sf.getClasses().stream().anyMatch(nf -> nf.getClassName().equals(clazz.getClassName())))
continue;
if (allClasses.stream().noneMatch(old -> old.getClassName().equals(clazz.getClassName())))
allClasses.add(clazz);
}
final ConstraintSet<Pair> cons = getConstraints();
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.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);
}
/**
* @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();
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 - 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) -> {
@ -760,15 +786,15 @@ public class JavaTXCompiler {
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();

@ -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;
}

@ -41,4 +41,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,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 {

@ -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;
@ -711,7 +712,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 +737,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();
@ -831,7 +832,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 +891,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 +964,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 +1004,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 +1040,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 +1055,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) {

@ -333,7 +333,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 +452,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);

@ -332,4 +332,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,16 @@ 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 == null || getClass() != o.getClass()) return false;
ClassOrInterface that = (ClassOrInterface) o;
return Objects.equals(name, that.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;
}

@ -80,4 +80,6 @@ public interface StatementVisitor {
void visit(Literal literal);
void visit(Throw aThrow);
void visit(Ternary ternary);
}

@ -105,11 +105,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()) {
@ -192,7 +227,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 +253,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 +403,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){
if(t instanceof GenericRefType){
return UnifyTypeFactory.convert((GenericRefType)t, innerType);
}else if(t instanceof TypePlaceholder){
return UnifyTypeFactory.convert((TypePlaceholder)t, innerType);
}else if(t instanceof ExtendsWildcardType){
return UnifyTypeFactory.convert((ExtendsWildcardType)t, innerType);
}else if(t instanceof SuperWildcardType){
return UnifyTypeFactory.convert((SuperWildcardType)t, innerType);
}else if(t instanceof RefType){
return UnifyTypeFactory.convert((RefType)t, innerType);
public static UnifyType convert(JavaTXCompiler compiler, RefTypeOrTPHOrWildcardOrGeneric t, Boolean innerType){
if (t instanceof GenericRefType){
return UnifyTypeFactory.convert(compiler, (GenericRefType)t, innerType);
} else if (t instanceof TypePlaceholder){
return UnifyTypeFactory.convert(compiler, (TypePlaceholder)t, innerType);
} else if (t instanceof ExtendsWildcardType){
return UnifyTypeFactory.convert(compiler, (ExtendsWildcardType)t, innerType);
} else if (t instanceof SuperWildcardType) {
return UnifyTypeFactory.convert(compiler, (SuperWildcardType) t, innerType);
} else if (t instanceof RefType){
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<>();
for(RefTypeOrTPHOrWildcardOrGeneric pT : t.getParaList()){
params.add(UnifyTypeFactory.convert(pT, true));
List<UnifyType> params = new ArrayList<>();
if (t.getParaList() != null) {
for (RefTypeOrTPHOrWildcardOrGeneric pT : t.getParaList()) {
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;
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(List<RefTypeOrTPHOrWildcardOrGeneric> paraList, Boolean innerType){
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, // >

@ -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,9 +8,8 @@ import de.dhbwstuttgart.exceptions.NotImplementedException;
public class This extends Expression
{
public This(Token offset)
{
super(TypePlaceholder.fresh(offset),offset);
public This(Token offset) {
super(TypePlaceholder.fresh(offset), offset);
}
public ArgumentList arglist;

@ -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);
}

@ -380,6 +380,7 @@ public class OutputGenerator implements ASTVisitor {
out.append("super(");
superCall.arglist.accept(this);
out.append(")");
out.append(" Signature: " + superCall.signature);
}
@Override
@ -387,6 +388,7 @@ public class OutputGenerator implements ASTVisitor {
out.append("this(");
thisCall.arglist.accept(this);
out.append(")");
out.append(" Signature: " + thisCall.signature);
}
@Override
@ -427,6 +429,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(");

@ -6,6 +6,7 @@ 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;
@ -21,6 +22,7 @@ import java.lang.annotation.Target;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
/**
* @author dholle
@ -30,13 +32,11 @@ public class ASTToTargetAST {
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<>();
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,7 +51,7 @@ public class ASTToTargetAST {
return converter.result;
}
record Generics(JavaGenerics javaGenerics, TxGenerics txGenerics) {
public record Generics(JavaGenerics javaGenerics, TxGenerics txGenerics) {
}
@ -79,13 +79,18 @@ public class ASTToTargetAST {
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())
@ -126,7 +131,6 @@ public class ASTToTargetAST {
}
public TargetStructure convert(ClassOrInterface input) {
currentClass = input;
Set<TargetGeneric> javaGenerics = new HashSet<>();
Set<TargetGeneric> txGenerics = new HashSet<>();
@ -154,13 +158,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.getMethods()).stream().map(m -> convert(input, m)).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()).get(0);
if (input instanceof Record)
return new TargetRecord(input.getModifiers(), input.getClassName(), javaGenerics, txGenerics, superInterfaces, constructors, staticConstructor, fields, methods);
@ -169,7 +173,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 +183,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,7 +201,7 @@ 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<>();
@ -209,8 +213,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);
@ -285,9 +289,9 @@ 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.get(0));
}
var res = new ArrayList<Method>();
for (var method : overloadedMethods) {
@ -324,7 +328,7 @@ 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();
return res.stream().map(m -> convert(clazz, m)).flatMap(List::stream).toList();
}
private Expression makeRecordSwitch(RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList params, List<Method> overloadedMethods) {
@ -348,7 +352,28 @@ public class ASTToTargetAST {
return swtch;
}
private List<TargetMethod> convert(Method method) {
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());
System.out.println(a + " " + b);
if (!Objects.equals(a, b)) return false;
}
return true;
}).findFirst();
}
private List<TargetMethod> convert(ClassOrInterface currentClass, Method method) {
generics = all.get(0);
List<TargetMethod> result = new ArrayList<>();
Set<List<MethodParameter>> parameterSet = new HashSet<>();
@ -358,13 +383,22 @@ public class ASTToTargetAST {
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
returnType = convert(superMethod.get().getReturnType(), this.generics.javaGenerics);
params = convert(superMethod.get().getParameterList(), method.getParameterList(), this.generics.javaGenerics);
}
List<MethodParameter> finalParams = params;
if (parameterSet.stream().noneMatch(p -> p.equals(finalParams))) {
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);
@ -373,6 +407,15 @@ public class ASTToTargetAST {
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 +447,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);
}

@ -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,18 @@ 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;
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 +224,19 @@ 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);
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
@ -284,20 +298,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 +370,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();

@ -203,4 +203,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,6 +1,7 @@
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;
@ -8,7 +9,15 @@ import java.util.List;
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 = "(";

@ -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 {
}

@ -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,15 @@ public class TypeInferenceBlockInformation extends TypeInferenceInformation {
public ClassOrInterface getCurrentClass() {
return currentClass;
}
public ClassOrInterface getSuperClass() {
for (var clazz : getAvailableClasses()) {
System.out.println(currentClass.getSuperClass().getName());
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" ;
}
@ -65,5 +73,5 @@ public class Constraint<A> extends HashSet<A> {
public String toStringBase() {
return super.toString();
}
}

@ -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,
@ -126,4 +127,5 @@ public class ConstraintSet<A> {
public Set<A> getUndConstraints() {
return undConstraints;
}
}

@ -136,8 +136,12 @@ public class Pair implements Serializable
public boolean OperatorSmallerDot() {
return eOperator == PairOperator.SMALLERDOT;
}
public boolean OperatorSmallerNEQDot() {
return eOperator == PairOperator.SMALLERNEQDOT;
}
static public Map<String, TypePlaceholder> generateTPHMap(ConstraintSet<Pair> constraints) {
HashMap<String, TypePlaceholder> ret = new HashMap<>();
constraints.map((Pair p) -> {

@ -5,37 +5,103 @@ import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
import de.dhbwstuttgart.syntaxtree.statement.Statement;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.*;
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.constraints.Pair;
import de.dhbwstuttgart.util.BiRelation;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
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);
ret.addAll(getConstraintsClass(cl, new TypeInferenceInformation(allClasses)));
}
ConstraintSet<Pair> ret = new ConstraintSet();
for (ClassOrInterface cl : sf.KlassenVektor) {
var allClasses = new HashSet<ClassOrInterface>();
allClasses.addAll(allAvailableClasses);
allClasses.addAll(sf.availableClasses);
ret.addAll(getConstraintsClass(cl, new TypeInferenceInformation(allClasses)));
}
writeASP(ret);
//System.exit(0);
return ret;
}
private String toASP(RefTypeOrTPHOrWildcardOrGeneric type){
if(type instanceof TypePlaceholder){
return "_"+((TypePlaceholder) type).getName();
}else if(type instanceof RefType){
if(((RefType) type).getParaList().size() > 0){
return ((RefType) type).getName() + "<" +
((RefType) type).getParaList().stream().map(this::toASP).collect(Collectors.joining(", ")) +
">";
}else{
return ((RefType) type).getName().toString();
}
}else if(type instanceof ExtendsWildcardType){
return toASP(((ExtendsWildcardType) type).getInnerType());
} else if(type instanceof SuperWildcardType) {
return toASP(((SuperWildcardType) type).getInnerType());
} else if(type instanceof GenericRefType){
return "G"+((GenericRefType) type).getParsedName();
}
throw new RuntimeException("Unsupported Type: "+ type);
}
private String genASP(Set<Pair> cs){
String ret = "";
for(Pair p : cs) {
if (p.OperatorEqual()) {
ret +=(toASP(p.TA1) + "=." + toASP(p.TA2) + "\n");
} else if (p.OperatorSmallerDot()) {
ret +=(toASP(p.TA1) + "<." + toASP(p.TA2) + "\n");
} else if (p.OperatorSmallerNEQDot()) {
ret += (toASP(p.TA1) + "<." + toASP(p.TA2) + "\n");
}else if(p.OperatorSmaller()){
ret += toASP(p.TA1) +"<"+toASP(p.TA2)+ "\n";
} else {
throw new RuntimeException("Operator unsupported: " + p.GetOperator());
}
}
return ret;
}
private void writeASP(ConstraintSet<Pair> cs){
try(var f = new FileWriter("/tmp/output")){
f.append(genASP(cs.getUndConstraints()));
List<List<Set<Pair>>> orCons = cs.getOderConstraints().stream().map(css -> {
return css.stream().map(cp -> {
return cp.stream().collect(Collectors.toSet());
}).collect(Collectors.toList());
}).toList();
for(var orCon : orCons){
f.append("{\n");
var it = orCon.iterator();
while(it.hasNext()) {
var orC = it.next();
f.append("{\n");
f.append(genASP(orC));
f.append("}\n");
if(it.hasNext())f.append("|");
}
f.append("}\n");
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private ConstraintSet getConstraintsClass(ClassOrInterface cl, TypeInferenceInformation info) {
ConstraintSet ret = new ConstraintSet();
ConstraintSet methConstrains;

@ -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);
@ -499,7 +521,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
@ -559,20 +587,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())) {
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 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, false);
GenericsResolver resolver = getResolverInstance();
Set<Constraint<Pair>> oneMethodConstraints = generateConstraint(superCall, assumption, info, resolver);
methodConstraints.addAll(oneMethodConstraints);
}
break;
}
GenericsResolver resolver = getResolverInstance();
Set<Constraint<Pair>> oneMethodConstraints = generateConstraint(superCall, assumption, info, resolver);
methodConstraints.addAll(oneMethodConstraints);
}
constraintsSet.addUndConstraint(new Pair(superCall.receiver.getType(), getReceiverType(info.getSuperClass(), getResolverInstance()), PairOperator.EQUALSDOT));
constraintsSet.addOderConstraint(methodConstraints);
}
@ -582,23 +607,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 +683,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 +692,7 @@ public class TYPEStmt implements StatementVisitor {
Set<Constraint<Pair>> ret = new HashSet<>();
ret.add(methodConstraint);
ret.add(extendsMethodConstraint);
return ret;
}
@ -671,7 +716,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 +746,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 +784,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 +800,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,38 +886,42 @@ 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());
@ -596,7 +611,7 @@ implements IFiniteClosure {
return new HashSet<>();
return strInheritanceGraph.get(typeName).stream().map(x -> x.getContent()).collect(Collectors.toCollection(HashSet::new));
}
@Override
public Optional<UnifyType> getLeftHandedType(String typeName) {
if(!strInheritanceGraph.containsKey(typeName))
@ -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;
}
}

@ -71,9 +71,10 @@ public class AllgemeinTest {
///*
compiler = new JavaTXCompiler(
Lists.newArrayList(new File(path)),
Lists.newArrayList(new File(System.getProperty("user.dir")+"/resources/bytecode/classFiles/")));
Lists.newArrayList(new File(System.getProperty("user.dir")+"/resources/bytecode/classFiles/")),
new File(System.getProperty("user.dir")+"/resources/bytecode/classFiles/"));
//*/
compiler.generateBytecode(System.getProperty("user.dir")+"/resources/bytecode/classFiles/");
compiler.generateBytecode(new File(path));
pathToClassFile = System.getProperty("user.dir")+"/resources/bytecode/classFiles/";
loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)});
classToTest = loader.loadClass(className);

@ -3,14 +3,17 @@ import de.dhbwstuttgart.environment.ByteArrayClassLoader;
import org.junit.Ignore;
import org.junit.Test;
import java.io.FileWriter;
import java.lang.reflect.*;
import java.util.AbstractList;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
import targetast.TestCodegen;
import static org.junit.Assert.*;
import static targetast.TestCodegen.generateClassFiles;
import static targetast.TestCodegen.generateClassFiles;
public class TestComplete {
@Test
@ -179,6 +182,7 @@ public class TestComplete {
}
@Test
//@Ignore()
public void matrixOpTest() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "MatrixOP.jav");
var matrixOP = classFiles.get("MatrixOP");
@ -234,6 +238,9 @@ public class TestComplete {
@Test
//@Ignore("This is too complex")
public void matrixTest() throws Exception {
try(var f = new FileWriter("/tmp/output")){
f.append("hallo");
}
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Matrix.jav");
var matrix = classFiles.get("Matrix");
@ -261,7 +268,7 @@ public class TestComplete {
var instanceOfClass_m2 = matrix.getDeclaredConstructor(Vector.class).newInstance(vv1);
var mul = matrix.getDeclaredMethod("mul", Vector.class);
var mul = matrix.getDeclaredMethod("mul", List.class);
var result = mul.invoke(instanceOfClass_m1, instanceOfClass_m2);
System.out.println(instanceOfClass_m1.toString() + " * " + instanceOfClass_m2.toString() + " = " + result.toString());
@ -825,6 +832,8 @@ public class TestComplete {
assertNull(clazz.getDeclaredMethod("m").invoke(instance));
assertEquals(clazz.getDeclaredMethod("m2").invoke(instance), 'C');
assertEquals(clazz.getDeclaredMethod("m3").invoke(instance), 10L);
assertEquals(clazz.getDeclaredMethod("m4").invoke(instance), 10.5F);
}
@Test
@ -835,6 +844,18 @@ public class TestComplete {
assertEquals(clazz.getSuperclass().getDeclaredField("x").get(instance), 3);
}
@Test
public void testOperators() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Op1.jav");
var clazz = classFiles.get("Op1");
var instance = clazz.getDeclaredConstructor().newInstance();
assertEquals(clazz.getDeclaredMethod("not").invoke(instance), true);
assertEquals(clazz.getDeclaredMethod("or").invoke(instance), 10 | 20);
assertEquals(clazz.getDeclaredMethod("and").invoke(instance), 10 & 20);
assertEquals(clazz.getDeclaredMethod("xor").invoke(instance), 10 ^ 20);
assertEquals(clazz.getDeclaredMethod("mod").invoke(instance), 10 % 2);
}
@Ignore("Not implemented")
@Test
public void testStringConcat() throws Exception {
@ -891,6 +912,22 @@ public class TestComplete {
var instance = clazz.getDeclaredConstructor().newInstance();
}
@Test
public void testOverrideEquals() throws Exception {
var loader = new ByteArrayClassLoader();
loader.loadClass(TestCodegen.path.resolve("OverrideRoot.class"));
var classFiles = generateClassFiles(loader, "OverrideEquals.jav");
var clazz = classFiles.get("OverrideEquals");
var instance = clazz.getDeclaredConstructor().newInstance();
}
@Test
public void testTernary() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Ternary.jav");
var clazz = classFiles.get("Ternary");
var instance = clazz.getDeclaredConstructor().newInstance();
assertEquals(clazz.getDeclaredMethod("main", Integer.class).invoke(instance, 5), "small");
}
@Test
public void testBug122() throws Exception {
@ -972,4 +1009,107 @@ public class TestComplete {
var clazz = classFiles.get("Bug298");
var instance = clazz.getDeclaredConstructor().newInstance();
}
@Test
public void testBug300() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug300.jav");
var clazz = classFiles.get("Bug300");
var instance = clazz.getDeclaredConstructor().newInstance();
assertEquals(clazz.getDeclaredMethod("m").invoke(instance), "Base");
}
@Test
public void testBug301() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug301.jav");
var clazz = classFiles.get("Bug301");
var instance = clazz.getDeclaredConstructor().newInstance();
}
@Test
public void testBug302() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug302.jav");
var clazz = classFiles.get("Bug302");
clazz.getDeclaredMethod("m").invoke(null);
}
@Test
public void testBug306() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug306.jav");
var clazz = classFiles.get("Bug306");
var instance = clazz.getDeclaredConstructor().newInstance();
}
@Test
public void testBug307() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug307.jav");
var clazz = classFiles.get("Bug307");
var instance = clazz.getDeclaredConstructor().newInstance();
clazz.getDeclaredMethod("main").invoke(instance);
}
@Test
public void testBug309() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug309.jav");
var clazz = classFiles.get("Bug309");
var instance = clazz.getDeclaredConstructor().newInstance();
clazz.getDeclaredMethod("main").invoke(instance);
}
@Test
public void testBug310() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug310.jav");
var clazz = classFiles.get("Bug310");
var instance = clazz.getDeclaredConstructor().newInstance();
assertEquals(clazz.getDeclaredMethod("toString").invoke(instance), "3");
}
@Test
public void testBug311() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug311.jav");
var clazz = classFiles.get("Bug311");
var instance = clazz.getDeclaredConstructor().newInstance();
clazz.getDeclaredMethod("toString").invoke(instance);
}
@Test
public void testBug312() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug312.jav");
var clazz = classFiles.get("Bug312");
var instance = clazz.getDeclaredConstructor().newInstance();
clazz.getDeclaredMethod("main").invoke(instance);
}
@Test
public void testBug314() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug314.jav");
var clazz = classFiles.get("Bug314");
var instance = clazz.getDeclaredConstructor().newInstance();
var list = List.of(3, 4, 6, 7, 8);
var res = clazz.getDeclaredMethod("convert", List.class).invoke(instance, list);
assertEquals(res, List.of(6, 7, 8));
}
@Test
public void testBug325() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug325.jav");
var clazz = classFiles.get("Bug325");
var instance = clazz.getDeclaredConstructor().newInstance();
clazz.getDeclaredMethod("main").invoke(instance);
}
@Test
public void testBug326() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug326.jav");
var clazz = classFiles.get("Bug326");
var instance = clazz.getDeclaredConstructor().newInstance();
}
@Test
public void testBug328() throws Exception {
var loader = new ByteArrayClassLoader();
loader.loadClass(TestCodegen.path.resolve("Bug328B.class"));
var classFiles = generateClassFiles(loader, "Bug328.jav");
var clazz = classFiles.get("Bug328");
var instance = clazz.getDeclaredConstructor().newInstance();
}
}

@ -7,7 +7,7 @@ import java.util.List;
public class TestPackages {
private static final String bytecodeDirectory = System.getProperty("user.dir") + "targetTest";
private static final String bytecodeDirectory = System.getProperty("user.dir") + "/targetTest";
@Test
public void testPackages() throws Exception {
@ -16,22 +16,36 @@ public class TestPackages {
new File("resources/packageTest/pkg/sub/Test1.jav") // This should pull in Test2
//new File("resources/packageTest/pkg/sub2/Test2.jav")
),
List.of(new File("resources/packageTest"))
List.of(new File("resources/packageTest")),
new File(bytecodeDirectory)
);
cmp.generateBytecode(bytecodeDirectory);
cmp.generateBytecode();
}
@Test
@Ignore("This doesn't work")
public void testPackagesCircular() throws Exception {
var cmp = new JavaTXCompiler(
List.of(
new File("resources/packageTest/pkg/sub/Cycle1.jav")
//new File("resources/packageTest/pkg/sub2/Cycle2.jav")
),
List.of(new File("resources/packageTest"))
List.of(new File("resources/packageTest")),
new File(bytecodeDirectory)
);
cmp.generateBytecode(bytecodeDirectory);
cmp.generateBytecode();
}
@Test
public void testPackageInterface() throws Exception {
var cmp = new JavaTXCompiler(
List.of(new File("resources/packageTest/pkg/sub/Interface.jav")),
List.of(new File("resources/packageTest")),
new File(bytecodeDirectory)
);
cmp.generateBytecode();
}
}

@ -20,7 +20,7 @@ public class TestTypeDeployment {
var file = path.toFile();
var compiler = new JavaTXCompiler(file, false);
var parsedSource = compiler.sourceFiles.get(file);
var tiResults = compiler.typeInference();
var tiResults = compiler.typeInference(file);
Set<TypeInsert> tips = new HashSet<>();
for (var sf : compiler.sourceFiles.values()) {

@ -34,7 +34,7 @@ public class ASTToTypedTargetAST {
public void overloading() throws Exception {
var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Overloading.jav").toFile();
var compiler = new JavaTXCompiler(file);
var resultSet = compiler.typeInference();
var resultSet = compiler.typeInference(file);
var converter = new ASTToTargetAST(compiler, resultSet);
var classes = compiler.sourceFiles.get(file).getClasses();
@ -56,7 +56,7 @@ public class ASTToTypedTargetAST {
public void tphsAndGenerics() throws Exception {
var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Tph2.jav").toFile();
var compiler = new JavaTXCompiler(file);
var resultSet = compiler.typeInference();
var resultSet = compiler.typeInference(file);
var converter = new ASTToTargetAST(resultSet);
var classes = compiler.sourceFiles.get(file).getClasses();
@ -67,7 +67,7 @@ public class ASTToTypedTargetAST {
public void cycles() throws Exception {
var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Cycle.jav").toFile();
var compiler = new JavaTXCompiler(file);
var resultSet = compiler.typeInference();
var resultSet = compiler.typeInference(file);
var converter = new ASTToTargetAST(resultSet);
var classes = compiler.sourceFiles.get(file).getClasses();
@ -78,7 +78,7 @@ public class ASTToTypedTargetAST {
public void infimum() throws Exception {
var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Infimum.jav").toFile();
var compiler = new JavaTXCompiler(file);
var resultSet = compiler.typeInference();
var resultSet = compiler.typeInference(file);
var converter = new ASTToTargetAST(resultSet);
var classes = compiler.sourceFiles.get(file).getClasses();
@ -89,7 +89,7 @@ public class ASTToTypedTargetAST {
public void gen() throws Exception {
var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Gen.jav").toFile();
var compiler = new JavaTXCompiler(file);
var resultSet = compiler.typeInference();
var resultSet = compiler.typeInference(file);
var converter = new ASTToTargetAST(resultSet);
var classes = compiler.sourceFiles.get(file).getClasses();
@ -105,7 +105,7 @@ public class ASTToTypedTargetAST {
public void definedGenerics() throws Exception {
var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Generics.jav").toFile();
var compiler = new JavaTXCompiler(file);
var resultSet = compiler.typeInference();
var resultSet = compiler.typeInference(file);
var converter = new ASTToTargetAST(compiler, resultSet);
var classes = compiler.sourceFiles.get(file).getClasses();
@ -123,7 +123,7 @@ public class ASTToTypedTargetAST {
public void definedGenerics2() throws Exception {
var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Generics2.jav").toFile();
var compiler = new JavaTXCompiler(file);
var resultSet = compiler.typeInference();
var resultSet = compiler.typeInference(file);
var converter = new ASTToTargetAST(resultSet);
var classes = compiler.sourceFiles.get(file).getClasses();
@ -139,7 +139,7 @@ public class ASTToTypedTargetAST {
public void definedGenerics3() throws Exception {
var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Generics3.jav").toFile();
var compiler = new JavaTXCompiler(file);
var resultSet = compiler.typeInference();
var resultSet = compiler.typeInference(file);
var converter = new ASTToTargetAST(resultSet);
var classes = compiler.sourceFiles.get(file).getClasses();
@ -150,7 +150,7 @@ public class ASTToTypedTargetAST {
public void definedGenerics4() throws Exception {
var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Generics4.jav").toFile();
var compiler = new JavaTXCompiler(file);
var resultSet = compiler.typeInference();
var resultSet = compiler.typeInference(file);
var converter = new ASTToTargetAST(compiler, resultSet);
var classes = compiler.sourceFiles.get(file).getClasses();

@ -18,11 +18,12 @@ public class InheritTest {
public static void setUpBeforeClass() throws Exception {
var classLoader = new ByteArrayClassLoader();
classToTestAA = TestCodegen.generateClassFiles(classLoader, "AA.jav").get("AA");
classToTestBB = TestCodegen.generateClassFiles(classLoader, "BB.jav").get("BB");
classToTestCC = TestCodegen.generateClassFiles(classLoader, "CC.jav").get("CC");
classToTestDD = TestCodegen.generateClassFiles(classLoader, "DD.jav").get("DD");
classToTest = TestCodegen.generateClassFiles(classLoader, "Inherit.jav").get("Inherit");
var classes = TestCodegen.generateClassFiles(classLoader, "Inherit.jav");
classToTest = classes.get("Inherit");
classToTestAA = classes.get("AA");
classToTestBB = classes.get("BB");
classToTestCC = classes.get("CC");
classToTestDD = classes.get("DD");
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
instanceOfClassAA = classToTestAA.getDeclaredConstructor().newInstance();

@ -8,6 +8,7 @@ import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
import de.dhbwstuttgart.target.tree.MethodParameter;
import de.dhbwstuttgart.target.tree.TargetClass;
import de.dhbwstuttgart.target.tree.TargetMethod;
import de.dhbwstuttgart.target.tree.TargetStructure;
import de.dhbwstuttgart.target.tree.expression.*;
import de.dhbwstuttgart.target.tree.type.TargetFunNType;
@ -20,13 +21,11 @@ import static org.junit.Assert.*;
import org.objectweb.asm.Opcodes;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -38,22 +37,24 @@ public class TestCodegen {
Files.write(outputPath.resolve(name + ".class"), code);
}
public static Path path = Path.of(System.getProperty("user.dir"), "resources/bytecode/javFiles/");
public static Map<String, ? extends Class<?>> generateClassFiles(IByteArrayClassLoader classLoader, String... files) throws IOException, ClassNotFoundException {
var path = Path.of(System.getProperty("user.dir"), "resources/bytecode/javFiles/");
Files.createDirectories(outputPath);
var filenames = Arrays.stream(files).map(filename -> Path.of(path.toString(), filename).toFile()).toList();
var compiler = new JavaTXCompiler(filenames, List.of(path.toFile(), outputPath.toFile()));
var resultSet = compiler.typeInference();
var compiler = new JavaTXCompiler(filenames, List.of(path.toFile(), outputPath.toFile()), outputPath.toFile());
var result = new HashMap<String, Class<?>>();
for (var file : filenames) {
var resultSet = compiler.typeInference(file);
var sourceFile = compiler.sourceFiles.get(file);
var converter = new ASTToTargetAST(compiler, resultSet, sourceFile, classLoader);
var classes = compiler.sourceFiles.get(file).getClasses();
result.putAll(classes.stream().map(cli -> {
try {
return generateClass(converter.convert(cli), classLoader, compiler);
return generateClass(converter.convert(cli), classLoader, converter);
} catch (IOException exception) {
throw new RuntimeException(exception);
}
@ -64,18 +65,23 @@ public class TestCodegen {
}
}
for (var entry : compiler.loadedClasses.entrySet()) {
var name = entry.getKey().toString();
result.put(name, classLoader.loadClass(Path.of(entry.getValue().classFile().toURI())));
}
return result;
}
public static Class<?> generateClass(TargetStructure clazz, IByteArrayClassLoader classLoader) throws IOException, ClassNotFoundException {
Codegen codegen = new Codegen(clazz, new JavaTXCompiler(List.of()));
Codegen codegen = new Codegen(clazz, new JavaTXCompiler(List.of()), null);
var code = codegen.generate();
writeClassFile(clazz.qualifiedName().getClassName(), code);
return classLoader.loadClass(code);
}
public static Class<?> generateClass(TargetStructure clazz, IByteArrayClassLoader classLoader, JavaTXCompiler compiler) throws IOException {
Codegen codegen = new Codegen(clazz, compiler);
public static Class<?> generateClass(TargetStructure clazz, IByteArrayClassLoader classLoader, ASTToTargetAST converter) throws IOException {
Codegen codegen = new Codegen(clazz, converter.compiler, converter);
var code = codegen.generate();
writeClassFile(clazz.qualifiedName().getClassName(), code);
return classLoader.loadClass(code);
@ -83,8 +89,8 @@ public class TestCodegen {
public static Map<String, ? extends Class<?>> generateClassFiles(String filename, IByteArrayClassLoader classLoader) throws IOException, ClassNotFoundException {
var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/", filename).toFile();
var compiler = new JavaTXCompiler(List.of(file), List.of(file.getParentFile()));
var resultSet = compiler.typeInference();
var compiler = new JavaTXCompiler(List.of(file), List.of(file.getParentFile()), outputPath.toFile());
var resultSet = compiler.typeInference(file);
var sourceFile = compiler.sourceFiles.get(file);
var converter = new ASTToTargetAST(compiler, resultSet, sourceFile, classLoader);
@ -92,7 +98,7 @@ public class TestCodegen {
var result = classes.stream().map(cli -> {
try {
return generateClass(converter.convert(cli), classLoader, compiler);
return generateClass(converter.convert(cli), classLoader, converter);
} catch (IOException exception) {
throw new RuntimeException(exception);
}
@ -173,7 +179,7 @@ public class TestCodegen {
@Test
public void testMethodCall() throws Exception {
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, new JavaClassName("HelloWorld"));
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "helloWorld", List.of(), null, new TargetBlock(List.of(new TargetMethodCall(null, new TargetFieldVar(new TargetRefType("java.io.PrintStream"), new TargetRefType("java.lang.System"), true, new TargetClassName(new TargetRefType("java.lang.System")), "out"), List.of(new TargetLiteral.StringLiteral("Hello World!")), new TargetRefType("java.io.PrintStream"), "println", false, false))));
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "helloWorld", List.of(), null, new TargetBlock(List.of(new TargetMethodCall(null, new TargetFieldVar(new TargetRefType("java.io.PrintStream"), new TargetRefType("java.lang.System"), true, new TargetClassName(new TargetRefType("java.lang.System")), "out"), List.of(new TargetLiteral.StringLiteral("Hello World!")), new TargetRefType("java.io.PrintStream"), "println", false, false, false))));
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
clazz.getDeclaredMethod("helloWorld").invoke(null);
@ -270,8 +276,9 @@ public class TestCodegen {
var interfaceType = TargetFunNType.fromParams(List.of(TargetType.Integer));
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, new JavaClassName("CGLambda"));
targetClass.addConstructor(Opcodes.ACC_PUBLIC, List.of(), new TargetBlock(List.of(new TargetMethodCall(null, new TargetSuper(TargetType.Object), List.of(), TargetType.Object, "<init>", false, false))));
targetClass.addMethod(Opcodes.ACC_PUBLIC, "lambda", List.of(), TargetType.Integer, new TargetBlock(List.of(new TargetVarDecl(interfaceType, "by2", new TargetLambdaExpression(interfaceType, List.of(), List.of(new MethodParameter(TargetType.Integer, "num")), TargetType.Integer, new TargetBlock(List.of(new TargetReturn(new TargetBinaryOp.Mul(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "num"), new TargetLiteral.IntLiteral(2))))))), new TargetReturn(new TargetCast(TargetType.Integer, new TargetMethodCall(TargetType.Object, TargetType.Object, List.of(TargetType.Object), new TargetLocalVar(interfaceType, "by2"), List.of(new TargetLiteral.IntLiteral(10)), interfaceType, "apply", false, true))))));
targetClass.addConstructor(Opcodes.ACC_PUBLIC, List.of(), new TargetBlock(List.of(new TargetMethodCall(null, new TargetSuper(TargetType.Object), List.of(), TargetType.Object, "<init>", false, false, false))));
var signature = new TargetMethod.Signature(Set.of(), List.of(new MethodParameter(TargetType.Integer, "num")), TargetType.Integer);
targetClass.addMethod(Opcodes.ACC_PUBLIC, "lambda", List.of(), TargetType.Integer, new TargetBlock(List.of(new TargetVarDecl(interfaceType, "by2", new TargetLambdaExpression(interfaceType, List.of(), signature, new TargetBlock(List.of(new TargetReturn(new TargetBinaryOp.Mul(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "num"), new TargetLiteral.IntLiteral(2))))))), new TargetReturn(new TargetCast(TargetType.Integer, new TargetMethodCall(TargetType.Object, TargetType.Object, List.of(TargetType.Object), new TargetLocalVar(interfaceType, "by2"), List.of(new TargetLiteral.IntLiteral(10)), interfaceType, "apply", false, true, false))))));
var clazz = generateClass(targetClass, classLoader);
var instance = clazz.getConstructor().newInstance();
assertEquals(clazz.getDeclaredMethod("lambda").invoke(instance), 20);

@ -48,8 +48,8 @@ public class TestGenerics {
private static Result computeGenerics(String filename) throws IOException, ClassNotFoundException {
var file = Path.of(rootDirectory + filename).toFile();
var compiler = new JavaTXCompiler(List.of(file), List.of(file.getParentFile()));
var inference = compiler.typeInference();
var compiler = new JavaTXCompiler(List.of(file), List.of(file.getParentFile()), new File(bytecodeDirectory));
var inference = compiler.typeInference(file);
compiler.generateBytecode(new File(bytecodeDirectory), inference);
var sf = compiler.sourceFiles.get(file);
var clazz = sf.getClasses().get(0);

@ -34,7 +34,7 @@ public class JavaTXCompilerTest {
@Test
public void importTest() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory + "Import.jav"));
execute(new File(rootDirectory + "OrConsTest.jav"));
}
@Test
@ -166,9 +166,10 @@ public class JavaTXCompilerTest {
System.out.println(ASTTypePrinter.print(sf));
System.out.println(ASTPrinter.print(sf));
}
List<ResultSet> results = compiler.typeInference();
// compiler.generateBytecode(rootDirectory+"xxx.class", results, simplifyResultsForAllSourceFiles);
for (File f : compiler.sourceFiles.keySet()) {
List<ResultSet> results = compiler.typeInference(f);
SourceFile sf = compiler.sourceFiles.get(f);
System.out.println(ASTTypePrinter.print(sf));
System.out.println(ASTPrinter.print(sf));

@ -0,0 +1,20 @@
import java.lang.Integer;
import java.lang.String;
class C1{
m(){return this;}
}
class C2{
m(){return this;}
}
public class OrConsTest {
ol(var1) {
return var1.m().m().m().m().m().m().m().m().m().m().m().m();
}
}