Compare commits

..

28 Commits

Author SHA1 Message Date
Ruben
e1007cce30 return error Message String
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 1m29s
2025-09-26 09:33:31 +02:00
Ruben
4cfc070289 surround Method with Try-Catch
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 2m23s
2025-09-23 18:21:55 +02:00
Ruben
2920dfe68f Merge branch 'master' into LSP-Interface
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 1m42s
2025-09-22 15:57:55 +02:00
Ruben
c9d38728af set Target to 24
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 2m40s
2025-09-18 18:02:45 +02:00
Ruben
b7fad6e3c7 delete LanguageServerInterfaceTest.java
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 30s
2025-09-18 18:00:37 +02:00
Ruben
3cb9b74df1 clean up interface
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 31s
2025-09-18 17:49:28 +02:00
Ruben
effc31782f Merge remote-tracking branch 'origin/LSP-Interface' into LSP-Interface
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 32s
2025-09-18 17:42:49 +02:00
Ruben
2a24eab9d3 Merge branch 'refs/heads/master' into LSP-Interface 2025-09-18 17:33:36 +02:00
Ruben
a314013f40 feat: move compilation part into Language Server Interface
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 32s
2025-09-17 11:30:35 +02:00
Ruben
37c58be1f3 initially check Syntax when opening file
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 40s
2025-09-15 13:49:25 +02:00
Ruben
24920330c6 Merge branch 'refs/heads/master' into LSP-Interface 2025-09-10 13:45:58 +02:00
Ruben
bc43ea749d feat: update compiler Interface
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 7m22s
2025-08-07 16:18:51 +02:00
Ruben
c479b044b3 feat: add Method to only get AST
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 5m43s
2025-07-16 14:18:22 +02:00
Ruben
9046fb09e5 fix: directly use .generate Method instead of compiling each file by hand
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 7m20s
2025-07-16 11:53:48 +02:00
Ruben
42e31a3471 Merge branch 'master' into LSP-Interface
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 4m49s
2025-05-13 16:01:20 +02:00
Ruben
d3b3f92193 feat: make dir when /out does not exist
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 43s
2025-05-12 18:57:46 +02:00
Ruben
8208abcaea fix: exclude Files that do not end on .jav
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 45s
2025-05-12 18:43:10 +02:00
Ruben
e4a3939ce9 test: change TEstnames
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 41s
2025-05-09 14:11:39 +02:00
Ruben
d903ec0ebb test: change TEstnames
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Has been cancelled
2025-05-09 14:11:11 +02:00
Ruben
61de81cf92 feat: compile all classes in workspace
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 42s
2025-05-08 19:00:12 +02:00
Ruben
59888006e0 feat: compile all classes in workspace
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 42s
2025-05-08 18:51:25 +02:00
Ruben
94034912b4 feat: clean out file when generating Bytecode
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 42s
2025-05-08 17:51:17 +02:00
Ruben
f303163118 feat: clean out file when generating Bytecode
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 43s
2025-05-08 17:10:35 +02:00
Ruben
7d99fba044 fix: update Interface for Language Server to not throw random Errors anymore
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 43s
2025-05-07 18:53:47 +02:00
Ruben
3740d34954 fix: create Path if its non existent and add Try-Catch Clause when deleting Files in Case they dont exist
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 41s
2025-05-06 15:31:27 +02:00
Ruben
d8b861ea95 feat: add Method in Interface to generate Bytecode
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 43s
2025-05-06 15:10:55 +02:00
Ruben
cf45ea68bd feat: include Bytecode in /out Folder
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 42s
2025-05-05 17:26:10 +02:00
Ruben
be72e4d7fb feat: add Compiler Interface
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 1m6s
2025-05-05 14:34:23 +02:00
23 changed files with 542 additions and 293 deletions

View File

@@ -44,11 +44,6 @@ http://maven.apache.org/maven-v4_0_0.xsd">
<artifactId>asm</artifactId>
<version>9.8</version>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-util</artifactId>
<version>9.8</version>
</dependency>
</dependencies>
<build>

View File

@@ -1,3 +0,0 @@
class Bug378Id {
id2 = x -> x;
}

View File

@@ -1,8 +0,0 @@
import Bug378Id;
import java.lang.Integer;
class Bug378Main {
static main(args) {
var hallo = (new Bug378Id<Integer>().id2).apply(1);
}
}

View File

@@ -1,24 +0,0 @@
import java.lang.Integer;
import java.lang.Double;
import java.lang.System;
import java.io.PrintStream;
public class Bug379 {
public Fun1$$<Double, Double> fact = (x) -> {
if (x == 1) {
return 1;
} else {
return x * (fact.apply(x-1));
}
};
public getFact(x) {
return fact.apply(x);
}
public static void main(x) {
var f = new Bug379();
var intRes = f.getFact(3);
System.out.println(intRes);
}
}

View File

@@ -1,12 +0,0 @@
sealed interface List<T> permits Cons, Empty {}
record Cons<T>(T a , List<T> l ) implements List <T> {}
record Empty<T>() implements List <T> {}
public class Bug380 {
public <T> List<T> append(l1, List<T> l2) {
return switch ( l1 ) {
case Cons(e, rest) -> new Cons<>(e, append(rest, l2)); //::Typ TPH A
case Empty() -> l2;//::TPH B
};
}
}

View File

@@ -9,10 +9,7 @@ import de.dhbwstuttgart.target.tree.*;
import de.dhbwstuttgart.target.tree.expression.*;
import de.dhbwstuttgart.target.tree.type.*;
import org.objectweb.asm.*;
import org.objectweb.asm.tree.analysis.AnalyzerException;
import org.objectweb.asm.util.CheckClassAdapter;
import java.io.PrintWriter;
import java.lang.invoke.*;
import java.lang.reflect.Modifier;
import java.util.*;
@@ -128,7 +125,7 @@ public class Codegen {
}
private void popValue(State state, TargetType type) {
if (type.equals(TargetType.double_) || type.equals(TargetType.long_))
if (type.equals(TargetType.Double) || type.equals(TargetType.Long))
state.mv.visitInsn(POP2);
else
state.mv.visitInsn(POP);
@@ -137,21 +134,21 @@ public class Codegen {
private void boxPrimitive(State state, TargetType type) {
if (type instanceof TargetExtendsWildcard ew) type = ew.innerType();
var mv = state.mv;
if (type.equals(TargetType.boolean_)) {
if (type.equals(TargetType.Boolean) || type.equals(TargetType.boolean_)) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
} else if (type.equals(TargetType.byte_)) {
} else if (type.equals(TargetType.Byte) || type.equals(TargetType.byte_)) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false);
} else if (type.equals(TargetType.double_)) {
} else if (type.equals(TargetType.Double) || type.equals(TargetType.double_)) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false);
} else if (type.equals(TargetType.long_)) {
} else if (type.equals(TargetType.Long) || type.equals(TargetType.long_)) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false);
} else if (type.equals(TargetType.int_)) {
} else if (type.equals(TargetType.Integer) || type.equals(TargetType.int_)) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
} else if (type.equals(TargetType.float_)) {
} else if (type.equals(TargetType.Float) || type.equals(TargetType.float_)) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false);
} else if (type.equals(TargetType.short_)) {
} else if (type.equals(TargetType.Short) || type.equals(TargetType.short_)) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false);
} else if (type.equals(TargetType.char_)) {
} else if (type.equals(TargetType.Char) || type.equals(TargetType.char_)) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false);
}
}
@@ -188,11 +185,9 @@ public class Codegen {
convertTo(state, op.right().type(), type);
mv.visitJumpInsn(code, if_true);
mv.visitInsn(ICONST_0);
boxPrimitive(state, TargetType.toPrimitive(op.type()));
mv.visitJumpInsn(GOTO, end);
mv.visitLabel(if_true);
mv.visitInsn(ICONST_1);
boxPrimitive(state, TargetType.toPrimitive(op.type()));
mv.visitLabel(end);
}
@@ -207,11 +202,9 @@ public class Codegen {
mv.visitInsn(cmp);
mv.visitJumpInsn(code, if_true);
mv.visitInsn(ICONST_0);
boxPrimitive(state, TargetType.toPrimitive(op.type()));
mv.visitJumpInsn(GOTO, end);
mv.visitLabel(if_true);
mv.visitInsn(ICONST_1);
boxPrimitive(state, TargetType.toPrimitive(op.type()));
mv.visitLabel(end);
}
@@ -240,82 +233,64 @@ public class Codegen {
if (source instanceof TargetExtendsWildcard ew) source = ew.innerType();
if (dest instanceof TargetExtendsWildcard ew) dest = ew.innerType();
var mv = state.mv;
if (source.equals(dest))
return;
var mv = state.mv;
if ((source instanceof TargetRefType || source instanceof TargetGenericType) &&
(dest instanceof TargetRefType || dest instanceof TargetGenericType)) {
if (dest instanceof TargetGenericType) return;
mv.visitTypeInsn(CHECKCAST, dest.getInternalName());
return;
}
if (!(source instanceof TargetPrimitiveType)) {
unboxPrimitive(state, source);
source = TargetType.toPrimitive(source);
}
var origDest = dest;
dest = TargetType.toPrimitive(dest);
if (source.equals(TargetType.long_)) {
if (dest.equals(TargetType.int_))
if (source.equals(TargetType.Long)) {
if (dest.equals(TargetType.Integer))
mv.visitInsn(L2I);
else if (dest.equals(TargetType.float_))
else if (dest.equals(TargetType.Float))
mv.visitInsn(L2F);
else if (dest.equals(TargetType.double_))
else if (dest.equals(TargetType.Double))
mv.visitInsn(L2D);
else if (dest.equals(TargetType.byte_) || dest.equals(TargetType.char_) || dest.equals(TargetType.short_)) {
else if (dest.equals(TargetType.Byte) || dest.equals(TargetType.Char) || dest.equals(TargetType.Short)) {
mv.visitInsn(L2I);
convertTo(state, TargetType.int_, dest);
convertTo(state, TargetType.Integer, dest);
}
} else if (source.equals(TargetType.float_)) {
if (dest.equals(TargetType.int_))
} else if (source.equals(TargetType.Float)) {
if (dest.equals(TargetType.Integer))
mv.visitInsn(F2I);
else if (dest.equals(TargetType.double_))
else if (dest.equals(TargetType.Double))
mv.visitInsn(F2D);
else if (dest.equals(TargetType.long_))
else if (dest.equals(TargetType.Long))
mv.visitInsn(F2L);
else if (dest.equals(TargetType.byte_) || dest.equals(TargetType.char_) || dest.equals(TargetType.short_)) {
else if (dest.equals(TargetType.Byte) || dest.equals(TargetType.Char) || dest.equals(TargetType.Short)) {
mv.visitInsn(F2I);
convertTo(state, TargetType.int_, dest);
convertTo(state, TargetType.Integer, dest);
}
} else if (source.equals(TargetType.double_)) {
if (dest.equals(TargetType.int_))
} else if (source.equals(TargetType.Double)) {
if (dest.equals(TargetType.Integer))
mv.visitInsn(D2I);
else if (dest.equals(TargetType.float_))
else if (dest.equals(TargetType.Float))
mv.visitInsn(D2F);
else if (dest.equals(TargetType.long_))
else if (dest.equals(TargetType.Long))
mv.visitInsn(D2L);
else if (dest.equals(TargetType.byte_) || dest.equals(TargetType.char_) || dest.equals(TargetType.short_)) {
else if (dest.equals(TargetType.Byte) || dest.equals(TargetType.Char) || dest.equals(TargetType.Short)) {
mv.visitInsn(D2I);
convertTo(state, TargetType.int_, dest);
convertTo(state, TargetType.Integer, dest);
}
} else if (source.equals(TargetType.byte_) || source.equals(TargetType.char_) || source.equals(TargetType.short_) || source.equals(TargetType.int_)) {
if (dest.equals(TargetType.byte_))
} else if (source.equals(TargetType.Byte) || source.equals(TargetType.Char) || source.equals(TargetType.Short) || source.equals(TargetType.Integer)) {
if (dest.equals(TargetType.Byte))
mv.visitInsn(I2B);
else if (dest.equals(TargetType.char_))
else if (dest.equals(TargetType.Char))
mv.visitInsn(I2C);
else if (dest.equals(TargetType.short_))
else if (dest.equals(TargetType.Short))
mv.visitInsn(I2S);
else if (dest.equals(TargetType.long_))
else if (dest.equals(TargetType.Long))
mv.visitInsn(I2L);
else if (dest.equals(TargetType.float_))
else if (dest.equals(TargetType.Float))
mv.visitInsn(I2F);
else if (dest.equals(TargetType.double_))
else if (dest.equals(TargetType.Double))
mv.visitInsn(I2D);
} else if (source.equals(TargetType.boolean_)) {
} else if (source.equals(TargetType.Boolean)) {
unboxPrimitive(state, dest);
} else if (isFunctionalInterface(source) && isFunctionalInterface(dest) &&
!(source instanceof TargetFunNType && dest instanceof TargetFunNType)) {
boxFunctionalInterface(state, source, dest);
return;
}
if (!(origDest instanceof TargetPrimitiveType)) {
if (dest instanceof TargetPrimitiveType)
boxPrimitive(state, dest);
else boxPrimitive(state, source);
} else if (!(dest instanceof TargetGenericType)) {
//boxPrimitive(state, source);
mv.visitTypeInsn(CHECKCAST, dest.getInternalName());
unboxPrimitive(state, dest);
}
}
@@ -375,9 +350,9 @@ public class Codegen {
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "(Ljava/lang/String;)V", false);
} else {
generate(state, add.left());
convertTo(state, add.left().type(), TargetType.toPrimitive(add.type()));
convertTo(state, add.left().type(), add.type());
generate(state, add.right());
convertTo(state, add.right().type(), TargetType.toPrimitive(add.type()));
convertTo(state, add.right().type(), add.type());
var type = add.type();
if (type.equals(TargetType.Byte) || type.equals(TargetType.Char) || type.equals(TargetType.Integer) || type.equals(TargetType.Short)) {
mv.visitInsn(IADD);
@@ -390,7 +365,6 @@ public class Codegen {
} else {
throw new CodeGenException("Invalid argument to Add expression, type: " + add.type());
}
boxPrimitive(state, TargetType.toPrimitive(op.type()));
}
if (add.type().equals(TargetType.String)) {
generate(state, add.right());
@@ -402,9 +376,9 @@ public class Codegen {
}
case Sub sub: {
generate(state, sub.left());
convertTo(state, sub.left().type(), TargetType.toPrimitive(op.type()));
convertTo(state, sub.left().type(), op.type());
generate(state, sub.right());
convertTo(state, sub.right().type(), TargetType.toPrimitive(op.type()));
convertTo(state, sub.right().type(), op.type());
var type = sub.type();
if (type.equals(TargetType.Byte) || type.equals(TargetType.Char) || type.equals(TargetType.Integer) || type.equals(TargetType.Short)) {
mv.visitInsn(ISUB);
@@ -417,14 +391,13 @@ public class Codegen {
} else {
throw new CodeGenException("Invalid argument to Sub expression");
}
boxPrimitive(state, TargetType.toPrimitive(op.type()));
break;
}
case Div div: {
generate(state, div.left());
convertTo(state, div.left().type(), TargetType.toPrimitive(op.type()));
convertTo(state, div.left().type(), op.type());
generate(state, div.right());
convertTo(state, div.right().type(), TargetType.toPrimitive(op.type()));
convertTo(state, div.right().type(), op.type());
var type = div.type();
if (type.equals(TargetType.Byte) || type.equals(TargetType.Char) || type.equals(TargetType.Integer) || type.equals(TargetType.Short)) {
mv.visitInsn(IDIV);
@@ -437,14 +410,13 @@ public class Codegen {
} else {
throw new CodeGenException("Invalid argument to Div expression");
}
boxPrimitive(state, TargetType.toPrimitive(op.type()));
break;
}
case Mul mul: {
generate(state, mul.left());
convertTo(state, mul.left().type(), TargetType.toPrimitive(op.type()));
convertTo(state, mul.left().type(), op.type());
generate(state, mul.right());
convertTo(state, mul.right().type(), TargetType.toPrimitive(op.type()));
convertTo(state, mul.right().type(), op.type());
var type = mul.type();
if (type.equals(TargetType.Byte) || type.equals(TargetType.Char) || type.equals(TargetType.Integer) || type.equals(TargetType.Short)) {
mv.visitInsn(IMUL);
@@ -457,14 +429,13 @@ public class Codegen {
} else {
throw new CodeGenException("Invalid argument to Mul expression");
}
boxPrimitive(state, TargetType.toPrimitive(op.type()));
break;
}
case Rem rem: {
generate(state, rem.left());
convertTo(state, rem.left().type(), TargetType.toPrimitive(op.type()));
convertTo(state, rem.left().type(), op.type());
generate(state, rem.right());
convertTo(state, rem.right().type(), TargetType.toPrimitive(op.type()));
convertTo(state, rem.right().type(), op.type());
var type = rem.type();
if (type.equals(TargetType.Byte) || type.equals(TargetType.Char) || type.equals(TargetType.Integer) || type.equals(TargetType.Short)) {
mv.visitInsn(IREM);
@@ -477,7 +448,6 @@ public class Codegen {
} else {
throw new CodeGenException("Invalid argument to Rem expression");
}
boxPrimitive(state, TargetType.toPrimitive(op.type()));
break;
}
case Or or: {
@@ -485,18 +455,14 @@ public class Codegen {
Label or_true = new Label();
Label end = new Label();
generate(state, or.left());
convertTo(state, or.left().type(), TargetType.toPrimitive(op.type()));
mv.visitJumpInsn(IFNE, or_true);
generate(state, or.right());
convertTo(state, or.right().type(), TargetType.toPrimitive(op.type()));
mv.visitJumpInsn(IFEQ, or_false);
mv.visitLabel(or_true);
mv.visitInsn(ICONST_1);
boxPrimitive(state, TargetType.toPrimitive(op.type()));
mv.visitJumpInsn(GOTO, end);
mv.visitLabel(or_false);
mv.visitInsn(ICONST_0);
boxPrimitive(state, TargetType.toPrimitive(op.type()));
mv.visitLabel(end);
break;
}
@@ -504,54 +470,47 @@ public class Codegen {
Label and_false = new Label();
Label end = new Label();
generate(state, and.left());
convertTo(state, and.left().type(), TargetType.toPrimitive(op.type()));
mv.visitJumpInsn(IFEQ, and_false);
generate(state, and.right());
convertTo(state, and.right().type(), TargetType.toPrimitive(op.type()));
mv.visitJumpInsn(IFEQ, and_false);
mv.visitInsn(ICONST_1);
boxPrimitive(state, TargetType.toPrimitive(op.type()));
mv.visitJumpInsn(GOTO, end);
mv.visitLabel(and_false);
mv.visitInsn(ICONST_0);
boxPrimitive(state, TargetType.toPrimitive(op.type()));
mv.visitLabel(end);
break;
}
case BAnd band: {
generate(state, band.left());
convertTo(state, band.left().type(), TargetType.toPrimitive(op.type()));
convertTo(state, band.left().type(), op.type());
generate(state, band.right());
convertTo(state, band.right().type(), TargetType.toPrimitive(op.type()));
convertTo(state, band.right().type(), op.type());
if (band.type().equals(TargetType.Long))
mv.visitInsn(LAND);
else
mv.visitInsn(IAND);
boxPrimitive(state, TargetType.toPrimitive(op.type()));
break;
}
case BOr bor: {
generate(state, bor.left());
convertTo(state, bor.left().type(), TargetType.toPrimitive(op.type()));
convertTo(state, bor.left().type(), op.type());
generate(state, bor.right());
convertTo(state, bor.right().type(), TargetType.toPrimitive(op.type()));
convertTo(state, bor.right().type(), op.type());
if (bor.type().equals(TargetType.Long))
mv.visitInsn(LOR);
else
mv.visitInsn(IOR);
boxPrimitive(state, TargetType.toPrimitive(op.type()));
break;
}
case XOr xor: {
generate(state, xor.left());
convertTo(state, xor.left().type(), TargetType.toPrimitive(op.type()));
convertTo(state, xor.left().type(), op.type());
generate(state, xor.right());
convertTo(state, xor.right().type(), TargetType.toPrimitive(op.type()));
convertTo(state, xor.right().type(), op.type());
if (xor.type().equals(TargetType.Long))
mv.visitInsn(LXOR);
else
mv.visitInsn(IXOR);
boxPrimitive(state, TargetType.toPrimitive(op.type()));
break;
}
case Instof instof: {
@@ -560,47 +519,44 @@ public class Codegen {
}
case Shl shl: {
generate(state, shl.left());
convertTo(state, shl.left().type(), TargetType.toPrimitive(op.type()));
convertTo(state, shl.left().type(), op.type());
generate(state, shl.right());
convertTo(state, shl.right().type(), TargetType.toPrimitive(op.type()));
convertTo(state, shl.right().type(), op.type());
if (shl.type().equals(TargetType.Long))
mv.visitInsn(LSHL);
else
mv.visitInsn(ISHL);
boxPrimitive(state, TargetType.toPrimitive(op.type()));
break;
}
case Shr shr: {
generate(state, shr.left());
convertTo(state, shr.left().type(), TargetType.toPrimitive(op.type()));
convertTo(state, shr.left().type(), op.type());
generate(state, shr.right());
convertTo(state, shr.right().type(), TargetType.toPrimitive(op.type()));
convertTo(state, shr.right().type(), op.type());
if (shr.type().equals(TargetType.Long))
mv.visitInsn(LSHR);
else
mv.visitInsn(ISHR);
boxPrimitive(state, TargetType.toPrimitive(op.type()));
break;
}
case UShr ushr: {
generate(state, ushr.left());
convertTo(state, ushr.left().type(), TargetType.toPrimitive(op.type()));
convertTo(state, ushr.left().type(), op.type());
generate(state, ushr.right());
convertTo(state, ushr.right().type(), TargetType.toPrimitive(op.type()));
convertTo(state, ushr.right().type(), op.type());
if (ushr.type().equals(TargetType.Long))
mv.visitInsn(LUSHR);
else
mv.visitInsn(IUSHR);
boxPrimitive(state, TargetType.toPrimitive(op.type()));
break;
}
case Greater greater: {
var type = TargetType.toPrimitive(largerType(greater.left().type(), greater.right().type()));
if (type.equals(TargetType.long_)) {
var type = largerType(greater.left().type(), greater.right().type());
if (type.equals(TargetType.Long)) {
generateRelationalOperator(state, greater, type, LCMP, IFGT);
} else if (type.equals(TargetType.float_)) {
} else if (type.equals(TargetType.Float)) {
generateRelationalOperator(state, greater, type, FCMPL, IFGT);
} else if (type.equals(TargetType.double_)) {
} else if (type.equals(TargetType.Double)) {
generateRelationalOperator(state, greater, type, DCMPL, IFGT);
} else {
generateRelationalOperator(state, greater, type, IF_ICMPGT);
@@ -608,12 +564,12 @@ public class Codegen {
break;
}
case Less less: {
var type = TargetType.toPrimitive(largerType(less.left().type(), less.right().type()));
if (type.equals(TargetType.long_)) {
var type = largerType(less.left().type(), less.right().type());
if (type.equals(TargetType.Long)) {
generateRelationalOperator(state, less, type, LCMP, IFLT);
} else if (type.equals(TargetType.float_)) {
} else if (type.equals(TargetType.Float)) {
generateRelationalOperator(state, less, type, FCMPL, IFLT);
} else if (type.equals(TargetType.double_)) {
} else if (type.equals(TargetType.Double)) {
generateRelationalOperator(state, less, type, DCMPL, IFLT);
} else {
generateRelationalOperator(state, less, type, IF_ICMPLT);
@@ -621,12 +577,12 @@ public class Codegen {
break;
}
case GreaterOrEqual greaterOrEqual: {
var type = TargetType.toPrimitive(largerType(greaterOrEqual.left().type(), greaterOrEqual.right().type()));
if (type.equals(TargetType.long_)) {
var type = largerType(greaterOrEqual.left().type(), greaterOrEqual.right().type());
if (type.equals(TargetType.Long)) {
generateRelationalOperator(state, greaterOrEqual, type, LCMP, IFGE);
} else if (type.equals(TargetType.float_)) {
} else if (type.equals(TargetType.Float)) {
generateRelationalOperator(state, greaterOrEqual, type, FCMPL, IFGE);
} else if (type.equals(TargetType.double_)) {
} else if (type.equals(TargetType.Double)) {
generateRelationalOperator(state, greaterOrEqual, type, DCMPL, IFGE);
} else {
generateRelationalOperator(state, greaterOrEqual, type, IF_ICMPGE);
@@ -634,12 +590,12 @@ public class Codegen {
break;
}
case LessOrEqual lessOrEqual: {
var type = TargetType.toPrimitive(largerType(lessOrEqual.left().type(), lessOrEqual.right().type()));
if (type.equals(TargetType.long_)) {
var type = largerType(lessOrEqual.left().type(), lessOrEqual.right().type());
if (type.equals(TargetType.Long)) {
generateRelationalOperator(state, lessOrEqual, type, LCMP, IFLE);
} else if (type.equals(TargetType.float_)) {
} else if (type.equals(TargetType.Float)) {
generateRelationalOperator(state, lessOrEqual, type, FCMPL, IFLE);
} else if (type.equals(TargetType.double_)) {
} else if (type.equals(TargetType.Double)) {
generateRelationalOperator(state, lessOrEqual, type, DCMPL, IFLE);
} else {
generateRelationalOperator(state, lessOrEqual, type, IF_ICMPLE);
@@ -647,30 +603,30 @@ public class Codegen {
break;
}
case Equal equal: {
var type = TargetType.toPrimitive(largerType(equal.left().type(), equal.right().type()));
if (type.equals(TargetType.long_)) {
generateRelationalOperator(state, equal, TargetType.long_, LCMP, IFEQ);
} else if (type.equals(TargetType.float_)) {
generateRelationalOperator(state, equal, TargetType.float_, FCMPL, IFEQ);
} else if (type.equals(TargetType.double_)) {
generateRelationalOperator(state, equal, TargetType.double_, DCMPL, IFEQ);
} else if (type.equals(TargetType.char_) || type.equals(TargetType.short_) || type.equals(TargetType.byte_) || type.equals(TargetType.int_) || type.equals(TargetType.boolean_)) {
generateRelationalOperator(state, equal, TargetType.int_, IF_ICMPEQ);
var type = largerType(equal.left().type(), equal.right().type());
if (type.equals(TargetType.Long)) {
generateRelationalOperator(state, equal, type, LCMP, IFEQ);
} else if (type.equals(TargetType.Float)) {
generateRelationalOperator(state, equal, type, FCMPL, IFEQ);
} else if (type.equals(TargetType.Double)) {
generateRelationalOperator(state, equal, type, DCMPL, IFEQ);
} else if (type.equals(TargetType.Char) || type.equals(TargetType.Short) || type.equals(TargetType.Byte) || type.equals(TargetType.Integer) || type.equals(TargetType.Boolean)) {
generateRelationalOperator(state, equal, type, IF_ICMPEQ);
} else {
generateRelationalOperator(state, equal, type, IF_ACMPEQ);
}
break;
}
case NotEqual notEqual: {
var type = TargetType.toPrimitive(largerType(notEqual.left().type(), notEqual.right().type()));
if (type.equals(TargetType.long_)) {
generateRelationalOperator(state, notEqual, TargetType.long_, LCMP, IFNE);
} else if (type.equals(TargetType.float_)) {
generateRelationalOperator(state, notEqual, TargetType.float_, FCMPL, IFNE);
} else if (type.equals(TargetType.double_)) {
generateRelationalOperator(state, notEqual, TargetType.double_, DCMPL, IFNE);
} else if (type.equals(TargetType.char_) || type.equals(TargetType.short_) || type.equals(TargetType.byte_) || type.equals(TargetType.int_) || type.equals(TargetType.boolean_)) {
generateRelationalOperator(state, notEqual, TargetType.int_, IF_ICMPNE);
var type = largerType(notEqual.left().type(), notEqual.right().type());
if (type.equals(TargetType.Long)) {
generateRelationalOperator(state, notEqual, type, LCMP, IFNE);
} else if (type.equals(TargetType.Float)) {
generateRelationalOperator(state, notEqual, type, FCMPL, IFNE);
} else if (type.equals(TargetType.Double)) {
generateRelationalOperator(state, notEqual, type, DCMPL, IFNE);
} else if (type.equals(TargetType.Char) || type.equals(TargetType.Short) || type.equals(TargetType.Byte) || type.equals(TargetType.Integer)) {
generateRelationalOperator(state, notEqual, type, IF_ICMPNE);
} else {
generateRelationalOperator(state, notEqual, type, IF_ACMPNE);
}
@@ -701,7 +657,6 @@ public class Codegen {
generate(state, add.expr());
case TargetUnaryOp.Negate negate -> {
generate(state, negate.expr());
convertTo(state, negate.expr().type(), TargetType.boolean_);
if (negate.type().equals(TargetType.Double))
mv.visitInsn(DNEG);
else if (negate.type().equals(TargetType.Float))
@@ -710,11 +665,9 @@ public class Codegen {
mv.visitInsn(LNEG);
else
mv.visitInsn(INEG);
boxPrimitive(state, TargetType.toPrimitive(negate.expr().type()));
}
case TargetUnaryOp.Not not -> {
generate(state, not.expr());
convertTo(state, not.expr().type(), TargetType.boolean_);
if (not.type().equals(TargetType.Long)) {
mv.visitLdcInsn(-1L);
mv.visitInsn(LXOR);
@@ -722,86 +675,93 @@ public class Codegen {
mv.visitInsn(ICONST_M1);
mv.visitInsn(IXOR);
}
boxPrimitive(state, TargetType.toPrimitive(not.expr().type()));
}
case TargetUnaryOp.PreIncrement preIncrement -> {
generate(state, preIncrement.expr());
convertTo(state, preIncrement.expr().type(), TargetType.toPrimitive(op.type()));
if (preIncrement.type().equals(TargetType.Float)) {
mv.visitLdcInsn(1F);
mv.visitInsn(FADD);
mv.visitInsn(DUP);
} else if (preIncrement.type().equals(TargetType.Double)) {
mv.visitLdcInsn(1D);
mv.visitInsn(DADD);
mv.visitInsn(DUP2);
} else if (preIncrement.type().equals(TargetType.Long)) {
mv.visitLdcInsn(1L);
mv.visitInsn(LADD);
mv.visitInsn(DUP2);
} else {
mv.visitLdcInsn(1);
mv.visitInsn(IADD);
mv.visitInsn(DUP);
}
boxPrimitive(state, TargetType.toPrimitive(op.type()));
mv.visitInsn(DUP);
boxPrimitive(state, preIncrement.type());
afterIncDec(state, preIncrement);
}
case TargetUnaryOp.PreDecrement preDecrement -> {
generate(state, preDecrement.expr());
convertTo(state, preDecrement.expr().type(), TargetType.toPrimitive(op.type()));
if (preDecrement.type().equals(TargetType.Float)) {
mv.visitLdcInsn(1F);
mv.visitInsn(FSUB);
mv.visitInsn(DUP);
} else if (preDecrement.type().equals(TargetType.Double)) {
mv.visitLdcInsn(1D);
mv.visitInsn(DSUB);
mv.visitInsn(DUP2);
} else if (preDecrement.type().equals(TargetType.Long)) {
mv.visitLdcInsn(1L);
mv.visitInsn(LSUB);
mv.visitInsn(DUP2);
} else {
mv.visitLdcInsn(1);
mv.visitInsn(ISUB);
mv.visitInsn(DUP);
}
boxPrimitive(state, TargetType.toPrimitive(op.type()));
mv.visitInsn(DUP);
boxPrimitive(state, preDecrement.type());
afterIncDec(state, preDecrement);
}
case TargetUnaryOp.PostIncrement postIncrement -> {
generate(state, postIncrement.expr());
mv.visitInsn(DUP);
convertTo(state, postIncrement.expr().type(), TargetType.toPrimitive(op.type()));
if (postIncrement.type().equals(TargetType.Float)) {
mv.visitInsn(DUP);
mv.visitLdcInsn(1F);
mv.visitInsn(FADD);
} else if (postIncrement.type().equals(TargetType.Double)) {
mv.visitInsn(DUP2);
mv.visitLdcInsn(1D);
mv.visitInsn(DADD);
} else if (postIncrement.type().equals(TargetType.Long)) {
mv.visitInsn(DUP2);
mv.visitLdcInsn(1L);
mv.visitInsn(LADD);
} else {
mv.visitInsn(DUP);
mv.visitLdcInsn(1);
mv.visitInsn(IADD);
}
boxPrimitive(state, TargetType.toPrimitive(op.type()));
boxPrimitive(state, postIncrement.type());
afterIncDec(state, postIncrement);
}
case TargetUnaryOp.PostDecrement postDecrement -> {
generate(state, postDecrement.expr());
mv.visitInsn(DUP);
convertTo(state, postDecrement.expr().type(), TargetType.toPrimitive(op.type()));
if (postDecrement.type().equals(TargetType.Float)) {
mv.visitInsn(DUP);
mv.visitLdcInsn(1F);
mv.visitInsn(FSUB);
} else if (postDecrement.type().equals(TargetType.Double)) {
mv.visitInsn(DUP2);
mv.visitLdcInsn(1D);
mv.visitInsn(DSUB);
} else if (postDecrement.type().equals(TargetType.Long)) {
mv.visitInsn(DUP2);
mv.visitLdcInsn(1L);
mv.visitInsn(LSUB);
} else {
mv.visitInsn(DUP);
mv.visitLdcInsn(1);
mv.visitInsn(ISUB);
}
boxPrimitive(state, TargetType.toPrimitive(op.type()));
boxPrimitive(state, postDecrement.type());
afterIncDec(state, postDecrement);
}
}
@@ -949,7 +909,7 @@ public class Codegen {
var local = state.createVariable(varDecl.name(), varDecl.varType());
if (varDecl.value() != null) {
generate(state, varDecl.value());
boxPrimitive(state, varDecl.value().type());
boxPrimitive(state, varDecl.varType());
mv.visitVarInsn(ASTORE, local.index());
} else {
mv.visitInsn(ACONST_NULL);
@@ -998,14 +958,14 @@ public class Codegen {
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());
unboxPrimitive(state, local.type());
break;
}
case TargetFieldVar dot: {
if (!dot.isStatic())
generate(state, dot.left());
mv.visitFieldInsn(dot.isStatic() ? GETSTATIC : GETFIELD, dot.left().type().getInternalName(), dot.right(), dot.type().toDescriptor());
//unboxPrimitive(state, dot.type());
unboxPrimitive(state, dot.type());
break;
}
case TargetFor _for: {
@@ -1021,14 +981,11 @@ public class Codegen {
Label start = new Label();
Label end = new Label();
mv.visitLabel(start);
if (_for.termination() != null) {
if (_for.termination() != null)
generate(state, _for.termination());
convertTo(state, _for.termination().type(), TargetType.boolean_);
mv.visitJumpInsn(IFEQ, end);
} else {
else
mv.visitInsn(ICONST_1);
mv.visitJumpInsn(IFEQ, end);
}
mv.visitJumpInsn(IFEQ, end);
var env = new BreakEnv();
env.startLabel = start;
@@ -1060,7 +1017,6 @@ public class Codegen {
Label end = new Label();
mv.visitLabel(start);
generate(state, _while.cond());
convertTo(state, _while.cond().type(), TargetType.boolean_);
mv.visitJumpInsn(IFEQ, end);
var env = new BreakEnv();
@@ -1091,7 +1047,6 @@ public class Codegen {
mv.visitLabel(check);
generate(state, _do.cond());
convertTo(state, _do.cond().type(), TargetType.boolean_);
mv.visitJumpInsn(IFEQ, end);
mv.visitJumpInsn(GOTO, start);
mv.visitLabel(end);
@@ -1099,7 +1054,6 @@ public class Codegen {
}
case TargetIf _if: {
generate(state, _if.cond());
convertTo(state, _if.cond().type(), TargetType.boolean_);
Label _else = new Label();
Label end = new Label();
mv.visitJumpInsn(IFEQ, _else);
@@ -1117,10 +1071,11 @@ public class Codegen {
if (state.returnType instanceof TargetPrimitiveType) {
generate(state, ret.expression());
convertTo(state, ret.expression().type(), state.returnType);
unboxPrimitive(state, state.returnType);
mv.visitInsn(findReturnCode(state.returnType));
} else {
generate(state, ret.expression());
boxPrimitive(state, ret.expression().type());
convertTo(state, ret.expression().type(), state.returnType);
mv.visitInsn(ARETURN);
}
@@ -1172,6 +1127,8 @@ public class Codegen {
var arg = call.parameterTypes().get(i);
generate(state, e);
convertTo(state, e.type(), arg);
if (!(arg instanceof TargetPrimitiveType))
boxPrimitive(state, e.type());
}
var descriptor = call.getDescriptor();
if (call.owner() instanceof TargetFunNType) // Decay FunN
@@ -1184,13 +1141,11 @@ public class Codegen {
mv.visitMethodInsn(insn, call.owner().getInternalName(), call.name(), descriptor, call.isInterface());
/*if (call.type() != null && call.returnType() != null && !(call.returnType() instanceof TargetPrimitiveType)) {
if (call.type() != null && call.returnType() != null && !(call.returnType() instanceof TargetPrimitiveType)) {
if (!call.returnType().equals(call.type()) && !(call.type() instanceof TargetGenericType))
mv.visitTypeInsn(CHECKCAST, call.type().getInternalName());
unboxPrimitive(state, call.type());
}*/
if (call.type() != null)
convertTo(state, call.returnType(), call.type());
}
break;
}
case TargetLambdaExpression lambda:
@@ -1213,7 +1168,6 @@ public class Codegen {
}
case TargetTernary ternary: {
generate(state, ternary.cond());
convertTo(state, ternary.cond().type(), TargetType.boolean_);
var iffalse = new Label();
var end = new Label();
mv.visitJumpInsn(IFEQ, iffalse);
@@ -1267,7 +1221,6 @@ public class Codegen {
if (instanceOf.right() instanceof TargetTypePattern right && right.name() == null) {
generate(state, instanceOf.left());
mv.visitTypeInsn(INSTANCEOF, right.type().getInternalName());
boxPrimitive(state, TargetType.boolean_);
return;
}
@@ -1290,7 +1243,6 @@ public class Codegen {
state.pushSwitch();
generate(state, aSwitch.expr());
unboxPrimitive(state, aSwitch.expr().type());
state.enterScope();
@@ -1426,7 +1378,6 @@ public class Codegen {
if (label instanceof TargetGuard gd) {
generate(state, gd.expression());
unboxPrimitive(state, TargetType.Boolean);
var next = new Label();
mv.visitJumpInsn(IFNE, next);
mv.visitVarInsn(ALOAD, tmp);
@@ -1464,7 +1415,7 @@ public class Codegen {
if (aSwitch.isExpression()) {
if (aSwitch.type() != null) {
mv.visitVarInsn(ALOAD, state.switchResultValue.peek());
//unboxPrimitive(state, aSwitch.type());
unboxPrimitive(state, aSwitch.type());
}
state.popSwitch();
}
@@ -1481,8 +1432,8 @@ public class Codegen {
}
private void bindPattern(State state, TargetType type, TargetPattern pat, Label start, int index, int depth) {
//if (pat.type() instanceof TargetPrimitiveType)
// boxPrimitive(state, pat.type());
if (pat.type() instanceof TargetPrimitiveType)
boxPrimitive(state, pat.type());
if (pat.type() instanceof TargetRefType) {
state.mv.visitInsn(DUP);
@@ -1503,14 +1454,13 @@ public class Codegen {
}
if (pat instanceof TargetExpressionPattern ep) {
var cur = state.createVariable(TargetType.toWrapper(pat.type()));
var cur = state.createVariable(pat.type());
state.mv.visitVarInsn(ASTORE, cur.index);
var expr = new Equal(pat.type(), new TargetLocalVar(cur.type, cur.name), ep.expression());
generate(state, expr);
var cont = new Label();
unboxPrimitive(state, TargetType.Boolean);
state.mv.visitJumpInsn(IFNE, cont);
for (var i = 0; i < depth - 1; i++) {
state.mv.visitInsn(POP);
@@ -1706,7 +1656,7 @@ public class Codegen {
generate(state, method.block());
if (method.signature().returnType() == null)
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
mv.visitMaxs(0, 0);
}
mv.visitEnd();
}
@@ -1722,8 +1672,6 @@ public class Codegen {
}
if (clazz.superType() != null)
ret += clazz.superType().toSignature();
else ret += "Ljava/lang/Object;";
for (var intf : clazz.implementingInterfaces()) {
ret += intf.toSignature();
}
@@ -1826,12 +1774,8 @@ public class Codegen {
} else convertTo(state, fromReturn, toReturn);
}
if (toReturn != null) {
if ((fromReturn instanceof TargetRefType || fromReturn instanceof TargetGenericType)
&& (toReturn instanceof TargetPrimitiveType))
unboxPrimitive(state, TargetType.toWrapper(toReturn));
if (toReturn != null)
mv.visitInsn(findReturnCode(toReturn));
}
else mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
@@ -1853,10 +1797,6 @@ public class Codegen {
}
cw.visitEnd();
//ClassReader cr = new ClassReader(cw.toByteArray());
//System.out.println("Checking class " + className);
// TODO This fails for multi class projects because it tries to load the other classes
//CheckClassAdapter.verify(cr, false, new PrintWriter(System.err));
return cw.toByteArray();
}

View File

@@ -6,6 +6,7 @@ import de.dhbwstuttgart.bytecode.FunNGenerator;
import de.dhbwstuttgart.environment.CompilationEnvironment;
import de.dhbwstuttgart.environment.DirectoryClassLoader;
import de.dhbwstuttgart.exceptions.DebugException;
import de.dhbwstuttgart.languageServerInterface.model.LanguageServerTransferObject;
import de.dhbwstuttgart.parser.JavaTXParser;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.scope.GenericsRegistry;
@@ -475,6 +476,85 @@ public class JavaTXCompiler {
return results.stream().map((unifyPairs -> new ResultSet(UnifyTypeFactory.convert(unifyPairs, Pair.generateTPHMap(cons))))).collect(Collectors.toList());
}
/**
* TEMPORARY - Only for Language Server Usage
*/
public LanguageServerTransferObject getResultSetAndAbstractSyntax(File file) throws IOException, ClassNotFoundException {
var sf = sourceFiles.get(file);
if(sf == null){
sf = sourceFiles.values().stream().findFirst().get();
}
Set<ClassOrInterface> allClasses = new HashSet<>();
allClasses.addAll(getAvailableClasses(sf));
allClasses.addAll(sf.getClasses());
var newClasses = CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), file, this).stream().map(ASTFactory::createClass).collect(Collectors.toSet());
for (var clazz : newClasses) {
// Don't load classes that get recompiled
if (sf.getClasses().stream().anyMatch(nf -> nf.getClassName().equals(clazz.getClassName())))
continue;
if (allClasses.stream().noneMatch(old -> old.getClassName().equals(clazz.getClassName())))
allClasses.add(clazz);
}
final ConstraintSet<Pair> cons = getConstraints(file);
Set<Set<UnifyPair>> results = new HashSet<>();
try {
Writer logFile = new OutputStreamWriter(new NullOutputStream());
IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses.stream().toList(), logFile, classLoader, this);
ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(this, cons);
Function<UnifyPair, UnifyPair> distributeInnerVars = x -> {
UnifyType lhs, rhs;
if (((lhs = x.getLhsType()) instanceof PlaceholderType) && ((rhs = x.getRhsType()) instanceof PlaceholderType) && (((PlaceholderType) lhs).isInnerType() || ((PlaceholderType) rhs).isInnerType())) {
((PlaceholderType) lhs).setInnerType(true);
((PlaceholderType) rhs).setInnerType(true);
}
return x;
};
unifyCons = unifyCons.map(distributeInnerVars);
TypeUnify unify = new TypeUnify();
Set<PlaceholderType> varianceTPHold;
Set<PlaceholderType> varianceTPH = new HashSet<>();
varianceTPH = varianceInheritanceConstraintSet(unifyCons);
List<Set<Constraint<UnifyPair>>> oderConstraints = unifyCons.getOderConstraints();
if (resultmodel) {
/* UnifyResultModel Anfang */
UnifyResultModel urm = new UnifyResultModel(cons, finiteClosure);
UnifyResultListenerImpl li = new UnifyResultListenerImpl();
urm.addUnifyResultListener(li);
unify.unifyParallel(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, urm, usedTasks);
generateBytecode(sf, li.getResults());
return new LanguageServerTransferObject(li.getResults(), sf, ASTTypePrinter.print(sf), generatedGenerics);
}
/* UnifyResultModel End */
else {
Set<Set<UnifyPair>> result = unify.unifyOderConstraints(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, new UnifyResultModel(cons, finiteClosure), usedTasks);
results.addAll(result);
results = results.stream().map(x -> {
Optional<Set<UnifyPair>> res = new RuleSet().subst(x.stream().map(y -> {
if (y.getPairOp() == PairOperator.SMALLERDOTWC)
y.setPairOp(PairOperator.EQUALSDOT);
return y; // alle Paare a <.? b erden durch a =. b ersetzt
}).collect(Collectors.toCollection(HashSet::new)));
if (res.isPresent()) {// wenn subst ein Erg liefert wurde was veraendert
return new TypeUnifyTask().applyTypeUnificationRules(res.get(), finiteClosure);
} else
return x; // wenn nichts veraendert wurde wird x zurueckgegeben
}).collect(Collectors.toCollection(HashSet::new));
}
} catch (ClassNotFoundException e) {
}
generateBytecode(sf, results.stream().map((unifyPairs -> new ResultSet(UnifyTypeFactory.convert(unifyPairs, Pair.generateTPHMap(cons))))).collect(Collectors.toList()));
return new LanguageServerTransferObject(results.stream().map((unifyPairs -> new ResultSet(UnifyTypeFactory.convert(unifyPairs, Pair.generateTPHMap(cons))))).collect(Collectors.toList()), sf, ASTTypePrinter.print(sf), generatedGenerics);
}
/**
* Vererbt alle Variancen bei Paaren (a <. theta) oder (Theta <. a) wenn a eine Variance !=0 hat auf alle Typvariablen in Theta.
*

View File

@@ -0,0 +1,120 @@
package de.dhbwstuttgart.languageServerInterface;
import de.dhbwstuttgart.bytecode.Codegen;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.environment.IByteArrayClassLoader;
import de.dhbwstuttgart.languageServerInterface.model.LanguageServerTransferObject;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.syntaxtree.SourceFile;
import de.dhbwstuttgart.syntaxtree.factory.NameGenerator;
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
import de.dhbwstuttgart.target.generate.GenericsResult;
import de.dhbwstuttgart.target.tree.TargetStructure;
import org.apache.commons.io.FileUtils;
import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Implementation of an Interface for the Language-Server to get the Resultset and abstract Syntax.
*/
public class LanguageServerInterface {
public LanguageServerTransferObject getResultSetAndAbastractSyntax(String path, String resetNamesTo) throws IOException, URISyntaxException, ClassNotFoundException {
NameGenerator.resetTo(resetNamesTo);
return getResultSetAndAbstractSyntax(path);
}
public SourceFile getAst(String path, String resetNamesTo) throws IOException, URISyntaxException, ClassNotFoundException {
NameGenerator.resetTo(resetNamesTo);
return getAST(path);
}
/**
* returns the ResultSets, GenericResultSet and the AST
* You have to give the input as well as the path because of potential locks when the File is currently opened in an IDE.
* Example: file:///c:/test/main.jav -> file:///c:/test/out/main.class
*
* @param pathAsString the URI of the File. See Example.
*/
public LanguageServerTransferObject getResultSetAndAbstractSyntax(String pathAsString){
System.setOut(new PrintStream(OutputStream.nullOutputStream()));
try {
var uri = new URI(pathAsString);
var path = Path.of(uri);
var file = path.toFile();
Files.createDirectories(path.getParent().resolve("out"));
var compiler = new JavaTXCompiler(List.of(file), List.of(path.getParent().toFile()), path.getParent().resolve("out").toFile());
var parsedSource = compiler.sourceFiles.get(file);
var tiResults = compiler.typeInference(file);
Map<JavaClassName, byte[]> bytecode = compiler.generateBytecode(parsedSource, tiResults);
Files.createDirectories(path.getParent().resolve("out"));
compiler.writeClassFile(bytecode, path.getParent().resolve("out").toFile(), false);
return new LanguageServerTransferObject(tiResults, parsedSource, "", compiler.getGeneratedGenerics());
}catch (Exception e){
throw new RuntimeException(e.getMessage());
}
}
/**
* returns the AST without calculating the result
* You have to give the input as well as the path because of potential locks when the File is currently opened in an IDE.
* Example: file:///c:/test/main.jav -> file:///c:/test/out/main.class
*
* @param path the URI of the File. See Example.
* @throws IOException
* @throws ClassNotFoundException
* @throws URISyntaxException
*/
public SourceFile getAST(String path) throws IOException, ClassNotFoundException, URISyntaxException {
System.setOut(new PrintStream(OutputStream.nullOutputStream()));
URI uri = new URI(path);
ArrayList<String> pathWithoutName = new ArrayList<>(List.of(uri.getPath().split("/")));
pathWithoutName.remove(List.of(uri.getPath().split("/")).size() - 1);
String stringPathWithoutName = "";
for (String i : pathWithoutName) {
stringPathWithoutName += "/" + i;
}
try {
FileUtils.cleanDirectory(new File(stringPathWithoutName + "/out"));
} catch (Exception e) {
}
try {
(new File(stringPathWithoutName + "/out")).mkdirs();
} catch (Exception e) {
}
var test = getAST(uri.getPath().split("/")[uri.getPath().split("/").length - 1], new File(stringPathWithoutName).getPath());
System.setOut(System.out);
return test;
}
public static SourceFile getAST(String filename, String filePath) throws IOException, ClassNotFoundException {
var file = Path.of(filePath, filename).toFile();
var compiler = new JavaTXCompiler(List.of(file), List.of(file.getParentFile()), Path.of(filePath + "/out").toFile());
return compiler.sourceFiles.get(file);
}
}

View File

@@ -0,0 +1,40 @@
package de.dhbwstuttgart.languageServerInterface;
import de.dhbwstuttgart.languageServerInterface.model.CustomParserErrorHandler;
import de.dhbwstuttgart.languageServerInterface.model.ParserError;
import de.dhbwstuttgart.parser.antlr.Java17Lexer;
import de.dhbwstuttgart.parser.antlr.Java17Parser;
import de.dhbwstuttgart.parser.antlr.Java17ParserBaseListener;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import java.util.List;
public class ParserInterface {
public List<ParserError> getParseErrors(String input){
CustomParserErrorHandler errorListener = new CustomParserErrorHandler();
CharStream charStream = CharStreams.fromString(input);
Java17Lexer lexer = new Java17Lexer(charStream);
CommonTokenStream tokens = new CommonTokenStream(lexer);
Java17Parser parser = new Java17Parser(tokens);
parser.removeErrorListeners();
parser.addErrorListener(errorListener);
ParseTree tree = parser.sourceFile();
ParseTreeWalker walker = new ParseTreeWalker();
Java17ParserBaseListener listener = new Java17ParserBaseListener();
walker.walk(listener, tree);
return errorListener.getErrorMessages();
}
}

View File

@@ -0,0 +1,47 @@
package de.dhbwstuttgart.languageServerInterface.model;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.atn.ATNConfigSet;
import org.antlr.v4.runtime.dfa.DFA;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
public class CustomParserErrorHandler implements ANTLRErrorListener {
private final List<ParserError> errorMessages = new ArrayList<>();
@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
int endCharPosition = charPositionInLine;
if (offendingSymbol instanceof Token) {
Token offendingToken = (Token) offendingSymbol;
endCharPosition = charPositionInLine + offendingToken.getText().length();
}
ParserError parserError = new ParserError(line, charPositionInLine, endCharPosition, msg);
errorMessages.add(parserError);
}
@Override
public void reportAmbiguity(Parser parser, DFA dfa, int i, int i1, boolean b, BitSet bitSet, ATNConfigSet atnConfigSet) {
}
@Override
public void reportAttemptingFullContext(Parser parser, DFA dfa, int i, int i1, BitSet bitSet, ATNConfigSet atnConfigSet) {
}
@Override
public void reportContextSensitivity(Parser parser, DFA dfa, int i, int i1, int i2, ATNConfigSet atnConfigSet) {
}
public List<ParserError> getErrorMessages() {
return errorMessages;
}
}

View File

@@ -0,0 +1,31 @@
package de.dhbwstuttgart.languageServerInterface.model;
import de.dhbwstuttgart.syntaxtree.SourceFile;
import de.dhbwstuttgart.target.generate.GenericsResult;
import de.dhbwstuttgart.typeinference.result.ResultSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class LanguageServerTransferObject {
List<ResultSet> resultSets;
SourceFile Ast;
String printedAst;
Map<SourceFile, List<GenericsResult>> generatedGenerics = new HashMap<>();
public LanguageServerTransferObject(List<ResultSet> resultSets, SourceFile Ast, String printedAst, Map<SourceFile, List<GenericsResult>> generatedGenerics) {
this.resultSets = resultSets;
this.Ast = Ast;
this.printedAst = printedAst;
this.generatedGenerics = generatedGenerics;
}
public List<ResultSet> getResultSets() {return resultSets;}
public SourceFile getAst() {return Ast;}
public String getPrintedAst() {return printedAst;}
public Map<SourceFile, List<GenericsResult>> getGeneratedGenerics() {return generatedGenerics;}
}

View File

@@ -0,0 +1,48 @@
package de.dhbwstuttgart.languageServerInterface.model;
public class ParserError {
private int line;
private int charPositionInLine;
private int endCharPosition;
String msg;
public ParserError(int line, int charPositionInLine, int endCharPosition, String msg) {
this.line = line;
this.charPositionInLine = charPositionInLine;
this. endCharPosition = endCharPosition;
this.msg = msg;
}
public int getEndCharPosition() {
return endCharPosition;
}
public void setEndCharPosition(int endCharPosition) {
this.endCharPosition = endCharPosition;
}
public void setCharPositionInLine(int charPositionInLine) {
this.charPositionInLine = charPositionInLine;
}
public void setLine(int line) {
this.line = line;
}
public void setMsg(String msg) {
this.msg = msg;
}
public int getCharPositionInLine() {
return charPositionInLine;
}
public int getLine() {
return line;
}
public String getMsg() {
return msg;
}
}

View File

@@ -0,0 +1,20 @@
package de.dhbwstuttgart.languageServerInterface.model;
import com.google.common.reflect.TypeResolver;
import de.dhbwstuttgart.typeinference.unify.UnifyResultEvent;
import de.dhbwstuttgart.typeinference.unify.UnifyResultListener;
public class ResultSetListener implements UnifyResultListener {
TypeResolver typeResolver;
public ResultSetListener(TypeResolver typeResolver){
this.typeResolver = typeResolver;
}
@Override
public void onNewTypeResultFound(UnifyResultEvent evt) {
}
}

View File

@@ -111,7 +111,7 @@ public class SyntaxTreeGenerator {
this.allmodifiers.put(Modifier.toString(Modifier.INTERFACE), Modifier.INTERFACE);
this.allmodifiers.put("sealed", 4096);
this.allmodifiers.put("non-sealed", 8192);
this.allmodifiers.put("default", 0); // Doesn't exist
this.allmodifiers.put("default", 16384);
this.allmodifiers.put("strictfp", 32768);
this.compiler = compiler;

View File

@@ -13,6 +13,10 @@ public class NameGenerator {
public static void reset() {
strNextName = "A";
}
public static void resetTo(String name) {
strNextName = name;
}
/**
* Berechnet einen neuen, eindeutigen Namen f�r eine neue

View File

@@ -1,3 +1,4 @@
package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.bytecode.FunNGenerator;

View File

@@ -161,6 +161,7 @@ public class StatementToTargetExpression implements ASTVisitor {
@Override
public void visit(FieldVar fieldVar) {
var isStatic = false;
var type = converter.convert(fieldVar.receiver.getType());
var clazz = converter.compiler.getClass(new JavaClassName(type.name()));
var field = clazz.getField(fieldVar.fieldVarName).orElseThrow();

View File

@@ -8,42 +8,42 @@ public sealed interface TargetLiteral extends TargetExpression {
record BooleanLiteral(Boolean value) implements TargetLiteral {
@Override
public TargetType type() {
return TargetType.boolean_;
return TargetType.Boolean;
}
}
record CharLiteral(Character value) implements TargetLiteral {
@Override
public TargetType type() {
return TargetType.char_;
return TargetType.Char;
}
}
record IntLiteral(Integer value) implements TargetLiteral {
@Override
public TargetType type() {
return TargetType.int_;
return TargetType.Integer;
}
}
record LongLiteral(Long value) implements TargetLiteral {
@Override
public TargetType type() {
return TargetType.long_;
return TargetType.Long;
}
}
record FloatLiteral(Float value) implements TargetLiteral {
@Override
public TargetType type() {
return TargetType.float_;
return TargetType.Float;
}
}
record DoubleLiteral(Double value) implements TargetLiteral {
@Override
public TargetType type() {
return TargetType.double_;
return TargetType.Double;
}
}

View File

@@ -33,10 +33,4 @@ public record TargetFunNType(String name, List<TargetType> funNParams, List<Targ
public String getInternalName() {
return name;
}
@Override
public String toSignature() {
var args = FunNGenerator.getArguments(params);
return "LFun" + args.size() + "$$" + TargetSpecializedType.signatureParameters(params) + ";";
}
}

View File

@@ -8,20 +8,14 @@ public sealed interface TargetSpecializedType extends TargetType permits TargetF
@Override
default String toSignature() {
String ret = "L" + getInternalName();
ret += signatureParameters(params());
ret += ";";
return ret;
}
static String signatureParameters(List<TargetType> params) {
var ret = "";
if (!params.isEmpty()) {
if (!params().isEmpty()) {
ret += "<";
for (var param : params) {
for (var param : params()) {
ret += param.toSignature();
}
ret += ">";
}
ret += ";";
return ret;
}

View File

@@ -935,7 +935,7 @@ public class TYPEStmt implements StatementVisitor {
@Override
public void visit(Yield aYield) {
aYield.retexpr.accept(this);
constraintsSet.addUndConstraint(new Pair(aYield.getType(), switchStack.peek().getType(), PairOperator.SMALLERDOT, loc(aYield.getOffset())));
constraintsSet.addUndConstraint(new Pair(aYield.getType(), switchStack.peek().getType(), PairOperator.EQUALSDOT, loc(aYield.getOffset())));
// TODO Auto-generated method stub
}
}

View File

@@ -1476,28 +1476,4 @@ public class TestComplete {
var m = clazz.getDeclaredMethod("main");
m.invoke(null);
}
@Disabled("Doesn't work yet")
@Test
public void testBug378() throws Exception {
var classFiles = generateClassFiles(createClassLoader(), "Bug378Main.jav");
var clazz = classFiles.get("Bug378Main");
var main = clazz.getDeclaredMethod("main", List.class);
main.setAccessible(true);
main.invoke(null, List.of());
}
@Test
public void testBug379() throws Exception {
var classFiles = generateClassFiles(createClassLoader(), "Bug379.jav");
var clazz = classFiles.get("Bug379");
clazz.getDeclaredConstructor().newInstance();
}
@Test
public void testBug380() throws Exception {
var classFiles = generateClassFiles(createClassLoader(), "Bug380.jav");
var clazz = classFiles.get("Bug380");
clazz.getDeclaredConstructor().newInstance();
}
}

View File

@@ -0,0 +1,5 @@
public class t{
public mofus(){
return 1;
}
}