Compare commits
11 Commits
LSP-Interf
...
master
Author | SHA1 | Date | |
---|---|---|---|
eb09117a67 | |||
c7891b4965 | |||
f7891b1196 | |||
1e926e4996 | |||
acdaa1185b | |||
a20a45d7c3 | |||
a68035748c | |||
8c476b9e29 | |||
6bb462cd06 | |||
71555486b0 | |||
4048902442 |
5
pom.xml
5
pom.xml
@@ -44,6 +44,11 @@ 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>
|
||||
|
3
resources/bytecode/javFiles/Bug378Id.jav
Normal file
3
resources/bytecode/javFiles/Bug378Id.jav
Normal file
@@ -0,0 +1,3 @@
|
||||
class Bug378Id {
|
||||
id2 = x -> x;
|
||||
}
|
8
resources/bytecode/javFiles/Bug378Main.jav
Normal file
8
resources/bytecode/javFiles/Bug378Main.jav
Normal file
@@ -0,0 +1,8 @@
|
||||
import Bug378Id;
|
||||
import java.lang.Integer;
|
||||
|
||||
public class Bug378Main {
|
||||
public static main(args) {
|
||||
var hallo = (new Bug378Id<Integer>().id2).apply(1);
|
||||
}
|
||||
}
|
24
resources/bytecode/javFiles/Bug379.jav
Normal file
24
resources/bytecode/javFiles/Bug379.jav
Normal file
@@ -0,0 +1,24 @@
|
||||
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);
|
||||
}
|
||||
}
|
12
resources/bytecode/javFiles/Bug380.jav
Normal file
12
resources/bytecode/javFiles/Bug380.jav
Normal file
@@ -0,0 +1,12 @@
|
||||
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
|
||||
};
|
||||
}
|
||||
}
|
13
resources/bytecode/javFiles/Bug382.jav
Normal file
13
resources/bytecode/javFiles/Bug382.jav
Normal file
@@ -0,0 +1,13 @@
|
||||
import java.lang.Runnable;
|
||||
import java.lang.String;
|
||||
import java.lang.System;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.Thread;
|
||||
|
||||
public class Bug382 {
|
||||
public static main(a) {
|
||||
var f = () -> System.out.println("Hallo Welt!");
|
||||
new Thread(f).run();
|
||||
}
|
||||
}
|
||||
|
10
resources/bytecode/javFiles/Bug383.jav
Normal file
10
resources/bytecode/javFiles/Bug383.jav
Normal file
@@ -0,0 +1,10 @@
|
||||
import java.lang.String;
|
||||
import java.lang.System;
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class Bug383 {
|
||||
public static main(a) {
|
||||
var f = () -> System.out.println("Hello from Thread!");
|
||||
f.apply();
|
||||
}
|
||||
}
|
@@ -9,7 +9,10 @@ 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.*;
|
||||
@@ -125,7 +128,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);
|
||||
@@ -134,21 +137,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) || type.equals(TargetType.boolean_)) {
|
||||
if (type.equals(TargetType.boolean_)) {
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
|
||||
} else if (type.equals(TargetType.Byte) || type.equals(TargetType.byte_)) {
|
||||
} else if (type.equals(TargetType.byte_)) {
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false);
|
||||
} else if (type.equals(TargetType.Double) || type.equals(TargetType.double_)) {
|
||||
} else if (type.equals(TargetType.double_)) {
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false);
|
||||
} else if (type.equals(TargetType.Long) || type.equals(TargetType.long_)) {
|
||||
} else if (type.equals(TargetType.long_)) {
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false);
|
||||
} else if (type.equals(TargetType.Integer) || type.equals(TargetType.int_)) {
|
||||
} else if (type.equals(TargetType.int_)) {
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
|
||||
} else if (type.equals(TargetType.Float) || type.equals(TargetType.float_)) {
|
||||
} else if (type.equals(TargetType.float_)) {
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false);
|
||||
} else if (type.equals(TargetType.Short) || type.equals(TargetType.short_)) {
|
||||
} else if (type.equals(TargetType.short_)) {
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false);
|
||||
} else if (type.equals(TargetType.Char) || type.equals(TargetType.char_)) {
|
||||
} else if (type.equals(TargetType.char_)) {
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false);
|
||||
}
|
||||
}
|
||||
@@ -185,9 +188,11 @@ 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);
|
||||
}
|
||||
|
||||
@@ -202,9 +207,11 @@ 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);
|
||||
}
|
||||
|
||||
@@ -233,65 +240,85 @@ 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;
|
||||
if (source.equals(TargetType.Long)) {
|
||||
if (dest.equals(TargetType.Integer))
|
||||
mv.visitInsn(L2I);
|
||||
else if (dest.equals(TargetType.Float))
|
||||
mv.visitInsn(L2F);
|
||||
else if (dest.equals(TargetType.Double))
|
||||
mv.visitInsn(L2D);
|
||||
else if (dest.equals(TargetType.Byte) || dest.equals(TargetType.Char) || dest.equals(TargetType.Short)) {
|
||||
mv.visitInsn(L2I);
|
||||
convertTo(state, TargetType.Integer, dest);
|
||||
}
|
||||
} else if (source.equals(TargetType.Float)) {
|
||||
if (dest.equals(TargetType.Integer))
|
||||
mv.visitInsn(F2I);
|
||||
else if (dest.equals(TargetType.Double))
|
||||
mv.visitInsn(F2D);
|
||||
else if (dest.equals(TargetType.Long))
|
||||
mv.visitInsn(F2L);
|
||||
else if (dest.equals(TargetType.Byte) || dest.equals(TargetType.Char) || dest.equals(TargetType.Short)) {
|
||||
mv.visitInsn(F2I);
|
||||
convertTo(state, TargetType.Integer, dest);
|
||||
}
|
||||
} else if (source.equals(TargetType.Double)) {
|
||||
if (dest.equals(TargetType.Integer))
|
||||
mv.visitInsn(D2I);
|
||||
else if (dest.equals(TargetType.Float))
|
||||
mv.visitInsn(D2F);
|
||||
else if (dest.equals(TargetType.Long))
|
||||
mv.visitInsn(D2L);
|
||||
else if (dest.equals(TargetType.Byte) || dest.equals(TargetType.Char) || dest.equals(TargetType.Short)) {
|
||||
mv.visitInsn(D2I);
|
||||
convertTo(state, TargetType.Integer, dest);
|
||||
}
|
||||
} 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))
|
||||
mv.visitInsn(I2C);
|
||||
else if (dest.equals(TargetType.Short))
|
||||
mv.visitInsn(I2S);
|
||||
else if (dest.equals(TargetType.Long))
|
||||
mv.visitInsn(I2L);
|
||||
else if (dest.equals(TargetType.Float))
|
||||
mv.visitInsn(I2F);
|
||||
else if (dest.equals(TargetType.Double))
|
||||
mv.visitInsn(I2D);
|
||||
} else if (source.equals(TargetType.Boolean)) {
|
||||
unboxPrimitive(state, dest);
|
||||
} else if (isFunctionalInterface(source) && isFunctionalInterface(dest) &&
|
||||
|
||||
if (isFunctionalInterface(source) && isFunctionalInterface(dest) &&
|
||||
!(source instanceof TargetFunNType && dest instanceof TargetFunNType)) {
|
||||
boxFunctionalInterface(state, source, dest);
|
||||
} else if (!(dest instanceof TargetGenericType)) {
|
||||
//boxPrimitive(state, source);
|
||||
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_))
|
||||
mv.visitInsn(L2I);
|
||||
else if (dest.equals(TargetType.float_))
|
||||
mv.visitInsn(L2F);
|
||||
else if (dest.equals(TargetType.double_))
|
||||
mv.visitInsn(L2D);
|
||||
else if (dest.equals(TargetType.byte_) || dest.equals(TargetType.char_) || dest.equals(TargetType.short_)) {
|
||||
mv.visitInsn(L2I);
|
||||
convertTo(state, TargetType.int_, dest);
|
||||
}
|
||||
} else if (source.equals(TargetType.float_)) {
|
||||
if (dest.equals(TargetType.int_))
|
||||
mv.visitInsn(F2I);
|
||||
else if (dest.equals(TargetType.double_))
|
||||
mv.visitInsn(F2D);
|
||||
else if (dest.equals(TargetType.long_))
|
||||
mv.visitInsn(F2L);
|
||||
else if (dest.equals(TargetType.byte_) || dest.equals(TargetType.char_) || dest.equals(TargetType.short_)) {
|
||||
mv.visitInsn(F2I);
|
||||
convertTo(state, TargetType.int_, dest);
|
||||
}
|
||||
} else if (source.equals(TargetType.double_)) {
|
||||
if (dest.equals(TargetType.int_))
|
||||
mv.visitInsn(D2I);
|
||||
else if (dest.equals(TargetType.float_))
|
||||
mv.visitInsn(D2F);
|
||||
else if (dest.equals(TargetType.long_))
|
||||
mv.visitInsn(D2L);
|
||||
else if (dest.equals(TargetType.byte_) || dest.equals(TargetType.char_) || dest.equals(TargetType.short_)) {
|
||||
mv.visitInsn(D2I);
|
||||
convertTo(state, TargetType.int_, dest);
|
||||
}
|
||||
} else if (source.equals(TargetType.byte_) || source.equals(TargetType.char_) || source.equals(TargetType.short_) || source.equals(TargetType.int_)) {
|
||||
if (dest.equals(TargetType.byte_))
|
||||
mv.visitInsn(I2B);
|
||||
else if (dest.equals(TargetType.char_))
|
||||
mv.visitInsn(I2C);
|
||||
else if (dest.equals(TargetType.short_))
|
||||
mv.visitInsn(I2S);
|
||||
else if (dest.equals(TargetType.long_))
|
||||
mv.visitInsn(I2L);
|
||||
else if (dest.equals(TargetType.float_))
|
||||
mv.visitInsn(I2F);
|
||||
else if (dest.equals(TargetType.double_))
|
||||
mv.visitInsn(I2D);
|
||||
} else if (source.equals(TargetType.boolean_)) {
|
||||
unboxPrimitive(state, dest);
|
||||
}
|
||||
|
||||
if (!(origDest instanceof TargetPrimitiveType)) {
|
||||
if (dest instanceof TargetPrimitiveType)
|
||||
boxPrimitive(state, dest);
|
||||
else boxPrimitive(state, source);
|
||||
}
|
||||
}
|
||||
|
||||
record TypePair(TargetType from, TargetType to) {}
|
||||
@@ -350,9 +377,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(), add.type());
|
||||
convertTo(state, add.left().type(), TargetType.toPrimitive(add.type()));
|
||||
generate(state, add.right());
|
||||
convertTo(state, add.right().type(), add.type());
|
||||
convertTo(state, add.right().type(), TargetType.toPrimitive(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);
|
||||
@@ -365,6 +392,7 @@ 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());
|
||||
@@ -376,9 +404,9 @@ public class Codegen {
|
||||
}
|
||||
case Sub sub: {
|
||||
generate(state, sub.left());
|
||||
convertTo(state, sub.left().type(), op.type());
|
||||
convertTo(state, sub.left().type(), TargetType.toPrimitive(op.type()));
|
||||
generate(state, sub.right());
|
||||
convertTo(state, sub.right().type(), op.type());
|
||||
convertTo(state, sub.right().type(), TargetType.toPrimitive(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);
|
||||
@@ -391,13 +419,14 @@ 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(), op.type());
|
||||
convertTo(state, div.left().type(), TargetType.toPrimitive(op.type()));
|
||||
generate(state, div.right());
|
||||
convertTo(state, div.right().type(), op.type());
|
||||
convertTo(state, div.right().type(), TargetType.toPrimitive(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);
|
||||
@@ -410,13 +439,14 @@ 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(), op.type());
|
||||
convertTo(state, mul.left().type(), TargetType.toPrimitive(op.type()));
|
||||
generate(state, mul.right());
|
||||
convertTo(state, mul.right().type(), op.type());
|
||||
convertTo(state, mul.right().type(), TargetType.toPrimitive(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);
|
||||
@@ -429,13 +459,14 @@ 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(), op.type());
|
||||
convertTo(state, rem.left().type(), TargetType.toPrimitive(op.type()));
|
||||
generate(state, rem.right());
|
||||
convertTo(state, rem.right().type(), op.type());
|
||||
convertTo(state, rem.right().type(), TargetType.toPrimitive(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);
|
||||
@@ -448,6 +479,7 @@ public class Codegen {
|
||||
} else {
|
||||
throw new CodeGenException("Invalid argument to Rem expression");
|
||||
}
|
||||
boxPrimitive(state, TargetType.toPrimitive(op.type()));
|
||||
break;
|
||||
}
|
||||
case Or or: {
|
||||
@@ -455,14 +487,18 @@ 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;
|
||||
}
|
||||
@@ -470,47 +506,54 @@ 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(), op.type());
|
||||
convertTo(state, band.left().type(), TargetType.toPrimitive(op.type()));
|
||||
generate(state, band.right());
|
||||
convertTo(state, band.right().type(), op.type());
|
||||
convertTo(state, band.right().type(), TargetType.toPrimitive(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(), op.type());
|
||||
convertTo(state, bor.left().type(), TargetType.toPrimitive(op.type()));
|
||||
generate(state, bor.right());
|
||||
convertTo(state, bor.right().type(), op.type());
|
||||
convertTo(state, bor.right().type(), TargetType.toPrimitive(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(), op.type());
|
||||
convertTo(state, xor.left().type(), TargetType.toPrimitive(op.type()));
|
||||
generate(state, xor.right());
|
||||
convertTo(state, xor.right().type(), op.type());
|
||||
convertTo(state, xor.right().type(), TargetType.toPrimitive(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: {
|
||||
@@ -519,44 +562,47 @@ public class Codegen {
|
||||
}
|
||||
case Shl shl: {
|
||||
generate(state, shl.left());
|
||||
convertTo(state, shl.left().type(), op.type());
|
||||
convertTo(state, shl.left().type(), TargetType.toPrimitive(op.type()));
|
||||
generate(state, shl.right());
|
||||
convertTo(state, shl.right().type(), op.type());
|
||||
convertTo(state, shl.right().type(), TargetType.toPrimitive(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(), op.type());
|
||||
convertTo(state, shr.left().type(), TargetType.toPrimitive(op.type()));
|
||||
generate(state, shr.right());
|
||||
convertTo(state, shr.right().type(), op.type());
|
||||
convertTo(state, shr.right().type(), TargetType.toPrimitive(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(), op.type());
|
||||
convertTo(state, ushr.left().type(), TargetType.toPrimitive(op.type()));
|
||||
generate(state, ushr.right());
|
||||
convertTo(state, ushr.right().type(), op.type());
|
||||
convertTo(state, ushr.right().type(), TargetType.toPrimitive(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 = largerType(greater.left().type(), greater.right().type());
|
||||
if (type.equals(TargetType.Long)) {
|
||||
var type = TargetType.toPrimitive(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);
|
||||
@@ -564,12 +610,12 @@ public class Codegen {
|
||||
break;
|
||||
}
|
||||
case Less less: {
|
||||
var type = largerType(less.left().type(), less.right().type());
|
||||
if (type.equals(TargetType.Long)) {
|
||||
var type = TargetType.toPrimitive(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);
|
||||
@@ -577,12 +623,12 @@ public class Codegen {
|
||||
break;
|
||||
}
|
||||
case GreaterOrEqual greaterOrEqual: {
|
||||
var type = largerType(greaterOrEqual.left().type(), greaterOrEqual.right().type());
|
||||
if (type.equals(TargetType.Long)) {
|
||||
var type = TargetType.toPrimitive(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);
|
||||
@@ -590,12 +636,12 @@ public class Codegen {
|
||||
break;
|
||||
}
|
||||
case LessOrEqual lessOrEqual: {
|
||||
var type = largerType(lessOrEqual.left().type(), lessOrEqual.right().type());
|
||||
if (type.equals(TargetType.Long)) {
|
||||
var type = TargetType.toPrimitive(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);
|
||||
@@ -603,30 +649,30 @@ public class Codegen {
|
||||
break;
|
||||
}
|
||||
case Equal equal: {
|
||||
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);
|
||||
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);
|
||||
} else {
|
||||
generateRelationalOperator(state, equal, type, IF_ACMPEQ);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NotEqual notEqual: {
|
||||
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);
|
||||
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);
|
||||
} else {
|
||||
generateRelationalOperator(state, notEqual, type, IF_ACMPNE);
|
||||
}
|
||||
@@ -657,6 +703,7 @@ 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))
|
||||
@@ -665,9 +712,11 @@ 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);
|
||||
@@ -675,93 +724,86 @@ 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, preIncrement.type());
|
||||
boxPrimitive(state, TargetType.toPrimitive(op.type()));
|
||||
mv.visitInsn(DUP);
|
||||
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, preDecrement.type());
|
||||
boxPrimitive(state, TargetType.toPrimitive(op.type()));
|
||||
mv.visitInsn(DUP);
|
||||
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, postIncrement.type());
|
||||
boxPrimitive(state, TargetType.toPrimitive(op.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, postDecrement.type());
|
||||
boxPrimitive(state, TargetType.toPrimitive(op.type()));
|
||||
afterIncDec(state, postDecrement);
|
||||
}
|
||||
}
|
||||
@@ -909,7 +951,7 @@ public class Codegen {
|
||||
var local = state.createVariable(varDecl.name(), varDecl.varType());
|
||||
if (varDecl.value() != null) {
|
||||
generate(state, varDecl.value());
|
||||
boxPrimitive(state, varDecl.varType());
|
||||
boxPrimitive(state, varDecl.value().type());
|
||||
mv.visitVarInsn(ASTORE, local.index());
|
||||
} else {
|
||||
mv.visitInsn(ACONST_NULL);
|
||||
@@ -958,14 +1000,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: {
|
||||
@@ -981,11 +1023,14 @@ 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());
|
||||
else
|
||||
convertTo(state, _for.termination().type(), TargetType.boolean_);
|
||||
mv.visitJumpInsn(IFEQ, end);
|
||||
} else {
|
||||
mv.visitInsn(ICONST_1);
|
||||
mv.visitJumpInsn(IFEQ, end);
|
||||
mv.visitJumpInsn(IFEQ, end);
|
||||
}
|
||||
|
||||
var env = new BreakEnv();
|
||||
env.startLabel = start;
|
||||
@@ -1017,6 +1062,7 @@ 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();
|
||||
@@ -1047,6 +1093,7 @@ 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);
|
||||
@@ -1054,6 +1101,7 @@ 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);
|
||||
@@ -1067,20 +1115,23 @@ public class Codegen {
|
||||
break;
|
||||
}
|
||||
case TargetReturn ret: {
|
||||
if (ret.expression() != null && state.returnType != null) {
|
||||
if (ret.expression() != null) {
|
||||
if (state.returnType instanceof TargetPrimitiveType) {
|
||||
generate(state, ret.expression());
|
||||
|
||||
unboxPrimitive(state, state.returnType);
|
||||
mv.visitInsn(findReturnCode(state.returnType));
|
||||
// Lambdas wrap the expression in a return if they are a single expression
|
||||
// It means we have to execute the code anyway but not return anything
|
||||
if (state.returnType != null) {
|
||||
convertTo(state, ret.expression().type(), 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);
|
||||
if (state.returnType != null) {
|
||||
convertTo(state, ret.expression().type(), state.returnType);
|
||||
mv.visitInsn(ARETURN);
|
||||
}
|
||||
}
|
||||
} else
|
||||
mv.visitInsn(RETURN);
|
||||
} else mv.visitInsn(RETURN);
|
||||
break;
|
||||
}
|
||||
case TargetYield yield: {
|
||||
@@ -1127,12 +1178,14 @@ 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
|
||||
descriptor = TargetMethod.getDescriptor(call.returnType() == null ? null : TargetType.Object, call.parameterTypes().stream().map(x -> TargetType.Object).toArray(TargetType[]::new));
|
||||
if (call.owner() instanceof TargetFunNType owner) {
|
||||
// Decay FunN
|
||||
descriptor = TargetMethod.getDescriptor(
|
||||
(owner.returnArguments() == 0 ? null : TargetType.Object),
|
||||
call.parameterTypes().stream().map(x -> TargetType.Object).toArray(TargetType[]::new));
|
||||
}
|
||||
|
||||
int insn = INVOKEVIRTUAL;
|
||||
if (call.isStatic()) insn = INVOKESTATIC;
|
||||
@@ -1141,11 +1194,13 @@ 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:
|
||||
@@ -1154,9 +1209,10 @@ public class Codegen {
|
||||
case TargetNew _new: {
|
||||
mv.visitTypeInsn(NEW, _new.type().getInternalName());
|
||||
mv.visitInsn(DUP);
|
||||
for (TargetExpression e : _new.params()) {
|
||||
for (var i = 0; i < _new.params().size(); i++) {
|
||||
var e = _new.params().get(i);
|
||||
generate(state, e);
|
||||
boxPrimitive(state, e.type());
|
||||
convertTo(state, e.type(), _new.signature().get(i));
|
||||
}
|
||||
mv.visitMethodInsn(INVOKESPECIAL, _new.type().getInternalName(), "<init>", _new.getDescriptor(), false);
|
||||
break;
|
||||
@@ -1168,6 +1224,7 @@ 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);
|
||||
@@ -1221,6 +1278,7 @@ 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;
|
||||
}
|
||||
|
||||
@@ -1243,6 +1301,7 @@ public class Codegen {
|
||||
state.pushSwitch();
|
||||
|
||||
generate(state, aSwitch.expr());
|
||||
unboxPrimitive(state, aSwitch.expr().type());
|
||||
|
||||
state.enterScope();
|
||||
|
||||
@@ -1378,6 +1437,7 @@ 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);
|
||||
@@ -1415,7 +1475,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();
|
||||
}
|
||||
@@ -1432,8 +1492,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);
|
||||
@@ -1454,13 +1514,14 @@ public class Codegen {
|
||||
}
|
||||
|
||||
if (pat instanceof TargetExpressionPattern ep) {
|
||||
var cur = state.createVariable(pat.type());
|
||||
var cur = state.createVariable(TargetType.toWrapper(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);
|
||||
@@ -1656,7 +1717,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();
|
||||
}
|
||||
@@ -1672,6 +1733,8 @@ public class Codegen {
|
||||
}
|
||||
if (clazz.superType() != null)
|
||||
ret += clazz.superType().toSignature();
|
||||
else ret += "Ljava/lang/Object;";
|
||||
|
||||
for (var intf : clazz.implementingInterfaces()) {
|
||||
ret += intf.toSignature();
|
||||
}
|
||||
@@ -1774,8 +1837,12 @@ public class Codegen {
|
||||
} else convertTo(state, fromReturn, toReturn);
|
||||
}
|
||||
|
||||
if (toReturn != null)
|
||||
if (toReturn != null) {
|
||||
if ((fromReturn instanceof TargetRefType || fromReturn instanceof TargetGenericType)
|
||||
&& (toReturn instanceof TargetPrimitiveType))
|
||||
unboxPrimitive(state, TargetType.toWrapper(toReturn));
|
||||
mv.visitInsn(findReturnCode(toReturn));
|
||||
}
|
||||
|
||||
else mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(0, 0);
|
||||
@@ -1784,19 +1851,13 @@ public class Codegen {
|
||||
cw2.visitEnd();
|
||||
var bytes = cw2.toByteArray();
|
||||
compiler.auxiliaries.put(className, bytes);
|
||||
|
||||
// TODO These class loading shenanigans happen in a few places, the tests load the classes individually.
|
||||
// Instead we should just look at the folder.
|
||||
try {
|
||||
converter.classLoader.findClass(className);
|
||||
} catch (ClassNotFoundException e) {
|
||||
try {
|
||||
converter.classLoader.loadClass(className, bytes);
|
||||
} catch (LinkageError ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
@@ -75,7 +75,7 @@ public class FunNGenerator {
|
||||
if (type == null) return VOID;
|
||||
var res = "L" + type.getInternalName();
|
||||
if (type instanceof TargetSpecializedType a) {
|
||||
if (a.params().size() > 0) {
|
||||
if (!a.params().isEmpty() && !(a.params().size() == 1 && a.params().getFirst() == null)) {
|
||||
res += "<";
|
||||
for (var param : a.params()) {
|
||||
if (param instanceof TargetGenericType gp) {
|
||||
@@ -115,11 +115,12 @@ public class FunNGenerator {
|
||||
superFunNMethodSignature.append(String.format("T%s;", argumentGenericBase + currentParameter));
|
||||
superFunNMethodDescriptor.append(objectSignature);
|
||||
}
|
||||
superFunNClassSignature.append(String.format("%s:%s>%s", returnGeneric, objectSignature, objectSignature));
|
||||
if (numReturnTypes > 0) {
|
||||
superFunNClassSignature.append(String.format("%s:%s>%s", returnGeneric, objectSignature, objectSignature));
|
||||
superFunNMethodSignature.append(String.format(")T%s;", returnGeneric));
|
||||
superFunNMethodDescriptor.append(String.format(")%s", objectSignature));
|
||||
} else {
|
||||
superFunNClassSignature = new StringBuilder(objectSignature);
|
||||
superFunNMethodSignature.append(")V");
|
||||
superFunNMethodDescriptor.append(")V");
|
||||
}
|
||||
|
@@ -67,8 +67,8 @@ public class LanguageServerInterface {
|
||||
compiler.writeClassFile(bytecode, path.getParent().resolve("out").toFile(), false);
|
||||
|
||||
return new LanguageServerTransferObject(tiResults, parsedSource, "", compiler.getGeneratedGenerics());
|
||||
}catch (Exception e){
|
||||
throw new RuntimeException(e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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", 16384);
|
||||
this.allmodifiers.put("default", 0); // Doesn't exist
|
||||
this.allmodifiers.put("strictfp", 32768);
|
||||
|
||||
this.compiler = compiler;
|
||||
|
@@ -168,7 +168,7 @@ public class TypeGenerator {
|
||||
if (generics.contains(name)) {
|
||||
return new GenericRefType(name, offset);
|
||||
} else {
|
||||
Pattern p = Pattern.compile("Fun(\\d+)[$][$]");
|
||||
Pattern p = Pattern.compile("Fun(Void|VoidImpl|Wrapper)?(\\d+)[$][$]"); // TODO Regex shenanigans
|
||||
Matcher m = p.matcher(name);
|
||||
if (m.matches()) {// es ist FunN$$-Type
|
||||
return new RefType(new JavaClassName(name), convert(typeArguments, reg, generics), offset);
|
||||
|
@@ -846,13 +846,6 @@ public class ASTToTargetAST {
|
||||
compiler.usedFunNSuperTypes.add(params.size());
|
||||
var code = FunNGenerator.generateSuperBytecode(params.size() - 1, returnType != null ? 1 : 0);
|
||||
var superClassName = FunNGenerator.getSuperClassName(params.size() - 1, returnType != null ? 1 : 0);
|
||||
try {
|
||||
compiler.classLoader.findClass(superClassName);
|
||||
} catch (ClassNotFoundException e) {
|
||||
try {
|
||||
compiler.classLoader.loadClass(superClassName, code);
|
||||
} catch (LinkageError ignored) {}
|
||||
}
|
||||
compiler.auxiliaries.put(superClassName, code);
|
||||
}
|
||||
FunNGenerator.GenericParameters gep = null;
|
||||
|
@@ -161,7 +161,6 @@ 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();
|
||||
|
@@ -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.Integer;
|
||||
return TargetType.int_;
|
||||
}
|
||||
}
|
||||
|
||||
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_;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -33,4 +33,10 @@ public record TargetFunNType(String name, List<TargetType> funNParams, List<Targ
|
||||
public String getInternalName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSignature() {
|
||||
var args = FunNGenerator.getArguments(funNParams);
|
||||
return "LFun" + args.size() + "$$" + TargetSpecializedType.signatureParameters(funNParams) + ";";
|
||||
}
|
||||
}
|
||||
|
@@ -8,14 +8,20 @@ public sealed interface TargetSpecializedType extends TargetType permits TargetF
|
||||
@Override
|
||||
default String toSignature() {
|
||||
String ret = "L" + getInternalName();
|
||||
if (!params().isEmpty()) {
|
||||
ret += signatureParameters(params());
|
||||
ret += ";";
|
||||
return ret;
|
||||
}
|
||||
|
||||
static String signatureParameters(List<TargetType> params) {
|
||||
var ret = "";
|
||||
if (!params.isEmpty()) {
|
||||
ret += "<";
|
||||
for (var param : params()) {
|
||||
for (var param : params) {
|
||||
ret += param.toSignature();
|
||||
}
|
||||
ret += ">";
|
||||
}
|
||||
ret += ";";
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@@ -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.EQUALSDOT, loc(aYield.getOffset())));
|
||||
constraintsSet.addUndConstraint(new Pair(aYield.getType(), switchStack.peek().getType(), PairOperator.SMALLERDOT, loc(aYield.getOffset())));
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
}
|
||||
|
@@ -1476,4 +1476,42 @@ 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.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();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBug382() throws Exception {
|
||||
var classFiles = generateClassFiles(createClassLoader(), "Bug382.jav");
|
||||
var clazz = classFiles.get("Bug382");
|
||||
clazz.getDeclaredMethod("main", List.class).invoke(null, List.of());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBug383() throws Exception {
|
||||
var classFiles = generateClassFiles(createClassLoader(), "Bug383.jav");
|
||||
var clazz = classFiles.get("Bug383");
|
||||
clazz.getDeclaredMethod("main", List.class).invoke(null, List.of());
|
||||
// TODO This logs output that we should validate
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user