Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
78a8f82325 | ||
|
|
20b974fd2a | ||
|
|
a504743a40 | ||
|
|
70764640d6 | ||
|
|
090263b6ca |
@@ -1,5 +1,5 @@
|
|||||||
sealed interface List<T> permits Cons, Empty {}
|
sealed interface List<T> permits Cons, Empty {}
|
||||||
record Cons<T>(T a , List<T> l ) implements List <T> {}
|
record Cons<T>(T a, List<T> l ) implements List <T> {}
|
||||||
record Empty<T>() implements List <T> {}
|
record Empty<T>() implements List <T> {}
|
||||||
|
|
||||||
public class Bug380 {
|
public class Bug380 {
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
import java.lang.String;
|
|
||||||
|
|
||||||
public class Bug389 {
|
public class Bug389 {
|
||||||
public swap(f) {
|
//public swap(f) {
|
||||||
return x -> y -> f.apply(y).apply(x);
|
// return x -> y -> f.apply(y).apply(x);
|
||||||
}
|
//}
|
||||||
public swap(f) {
|
public swap(f) {
|
||||||
return x -> y -> z -> f.apply(z).apply(x).apply(y);
|
return x -> y -> z -> f.apply(z).apply(x).apply(y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
import Bug389;
|
import Bug389;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.lang.String;
|
|
||||||
import java.lang.Integer;
|
import java.lang.Integer;
|
||||||
|
|
||||||
public class Bug389Main {
|
public class Bug389Main {
|
||||||
public static main(args) {
|
public static main(args) {
|
||||||
var func = x -> y -> z -> x + y + z;
|
var func = (Integer x) -> y -> z -> x + y + z;
|
||||||
var swap = new Bug389();
|
var swap = new Bug389();
|
||||||
swap.swap(func).apply(1).apply(2).apply(3);
|
swap.swap(func).apply(1).apply(2).apply(3);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import java.lang.Integer;
|
||||||
|
|
||||||
|
public class Bug395 {
|
||||||
|
dup(x) {
|
||||||
|
//Hier beliebiger Seiteneffekt
|
||||||
|
return x + x;
|
||||||
|
}
|
||||||
|
|
||||||
|
dup(s) {
|
||||||
|
return s + s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -7,7 +7,6 @@ import java.lang.Integer;
|
|||||||
import java.lang.String;
|
import java.lang.String;
|
||||||
import java.lang.System;
|
import java.lang.System;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
public sealed interface LazyList permits Empty, Cons {
|
public sealed interface LazyList permits Empty, Cons {
|
||||||
public Integer fst();
|
public Integer fst();
|
||||||
@@ -15,11 +14,11 @@ public sealed interface LazyList permits Empty, Cons {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Der Konstruktor Cons muss lazy sein, deshalb hier Supplier<...>
|
//Der Konstruktor Cons muss lazy sein, deshalb hier Supplier<...>
|
||||||
record Cons(Integer x, Supplier<LazyList> l) implements LazyList {
|
record Cons(Integer x, Fun0$$<LazyList> l) implements LazyList {
|
||||||
public Integer fst() { return this.x; }
|
public Integer fst() { return this.x; }
|
||||||
public LazyList rest() { return this.l.get(); }
|
public LazyList rest() { return this.l.apply(); }
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Cons(" + this.x.toString() + ", " + this.l.get().toString() + ")";
|
return "Cons(" + this.x.toString() + ", " + this.l.apply().toString() + ")";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,23 +3,29 @@ import java.lang.String;
|
|||||||
import java.lang.System;
|
import java.lang.System;
|
||||||
import java.lang.Boolean;
|
import java.lang.Boolean;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.util.function.Supplier;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import LazyList;
|
import LazyList;
|
||||||
import Cons;
|
import Cons;
|
||||||
import Empty;
|
import Empty;
|
||||||
|
|
||||||
public class Primzahlen {
|
public class Primzahlen {
|
||||||
static LazyList from(int i) { return new Cons(i, () -> from(i+1)); }
|
static LazyList from(Integer i) { return new Cons(i, () -> from(i+1)); }
|
||||||
|
|
||||||
LazyList filter(Function<Integer, Boolean> p, LazyList l) {
|
LazyList filter(Fun1$$<Integer, Boolean> p, LazyList l) {
|
||||||
return switch (l) {
|
return switch(l) {
|
||||||
case Empty() -> l;
|
case Empty e -> e;
|
||||||
case Cons(Integer x, Supplier<LazyList> l1) ->
|
case Cons(Integer x, Fun0$$<LazyList> l1) ->
|
||||||
p.apply(x) ? new Cons(x, () -> filter(p, l1.get())) : filter(p, l1.get());
|
p.apply(x) ? new Cons(x, () -> filter(p, l1.apply())) : filter(p, l1.apply());
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
|
/*LazyList filter(Fun1$$<Integer, Boolean> p, Empty()@l) {
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
LazyList filter(Fun1$$<Integer, Boolean> p, Cons(Integer x, Fun0$$<LazyList> l1)) {
|
||||||
|
return p.apply(x) ? new Cons(x, () -> filter(p, l1.apply())) : filter(p, l1.apply());
|
||||||
|
}*/
|
||||||
|
|
||||||
LazyList dropMul(Integer x, LazyList xs) {
|
LazyList dropMul(Integer x, LazyList xs) {
|
||||||
return filter(y -> (y % x != 0), xs);
|
return filter(y -> (y % x != 0), xs);
|
||||||
@@ -37,8 +43,8 @@ public class Primzahlen {
|
|||||||
if (n == 0) return new Empty();
|
if (n == 0) return new Empty();
|
||||||
else return switch (l) {
|
else return switch (l) {
|
||||||
case Empty() -> l;
|
case Empty() -> l;
|
||||||
case Cons(Integer x, Supplier<LazyList> l1) ->
|
case Cons(Integer x, Fun0$$<LazyList> l1) ->
|
||||||
new Cons(x, () -> take(n-1, l1.get()));
|
new Cons(x, () -> take(n-1, l1.apply()));
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import java.lang.Integer;
|
||||||
|
|
||||||
|
public record RecordTestInstanceVariables(Integer a, Integer b) {
|
||||||
|
public Integer getA() { return a; }
|
||||||
|
public Integer getB() { return b; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
public class StaticFail {
|
||||||
|
void nonStaticM() {}
|
||||||
|
|
||||||
|
static void staticM() {
|
||||||
|
nonStaticM();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -41,6 +41,15 @@ public class Codegen {
|
|||||||
protected ClassLoader getClassLoader() {
|
protected ClassLoader getClassLoader() {
|
||||||
return compiler.getClassLoader();
|
return compiler.getClassLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getCommonSuperClass(String type1, String type2) {
|
||||||
|
var t1 = new TargetRefType(type1.replaceAll("/", "."));
|
||||||
|
var t2 = new TargetRefType(type2.replaceAll("/", "."));
|
||||||
|
var common = ASTToTargetAST.getCommonSuperType(t1, t2, compiler);
|
||||||
|
return common.getClassName().toString().replaceAll("\\.", "/");
|
||||||
|
//return super.getCommonSuperClass(type1, type2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Codegen(TargetStructure clazz, JavaTXCompiler compiler, ASTToTargetAST converter) {
|
public Codegen(TargetStructure clazz, JavaTXCompiler compiler, ASTToTargetAST converter) {
|
||||||
@@ -244,10 +253,16 @@ public class Codegen {
|
|||||||
if (source.equals(dest))
|
if (source.equals(dest))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (isFunctionalInterface(source) && isFunctionalInterface(dest) &&
|
if (/*isFunctionalInterface(source) &&*/ isFunctionalInterface(dest) && !source.equals(dest)) {
|
||||||
!(source instanceof TargetFunNType && dest instanceof TargetFunNType)) {
|
if (source instanceof TargetFunNType funs && dest instanceof TargetFunNType fund) {
|
||||||
boxFunctionalInterface(state, source, dest);
|
if (funs.funNParams().size() == fund.funNParams().size() && !fund.isInterface()) {
|
||||||
return;
|
boxFunctionalInterface(state, source, dest);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
boxFunctionalInterface(state, source, dest);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var mv = state.mv;
|
var mv = state.mv;
|
||||||
@@ -336,7 +351,7 @@ public class Codegen {
|
|||||||
mv.visitTypeInsn(NEW, className);
|
mv.visitTypeInsn(NEW, className);
|
||||||
mv.visitInsn(DUP_X1);
|
mv.visitInsn(DUP_X1);
|
||||||
mv.visitInsn(SWAP);
|
mv.visitInsn(SWAP);
|
||||||
mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "(" + source.toDescriptor() + ")V", false);
|
mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "(Ljava/lang/Object;)V", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isFunctionalInterface(TargetType type) {
|
private boolean isFunctionalInterface(TargetType type) {
|
||||||
@@ -865,7 +880,8 @@ public class Codegen {
|
|||||||
var pattern = (TargetTypePattern) capture.pattern();
|
var pattern = (TargetTypePattern) capture.pattern();
|
||||||
var variable = state.scope.get(pattern.name());
|
var variable = state.scope.get(pattern.name());
|
||||||
mv.visitVarInsn(ALOAD, variable.index);
|
mv.visitVarInsn(ALOAD, variable.index);
|
||||||
mv.visitTypeInsn(CHECKCAST, capture.pattern().type().getInternalName());
|
if (!(capture.pattern().type() instanceof TargetGenericType))
|
||||||
|
mv.visitTypeInsn(CHECKCAST, capture.pattern().type().getInternalName());
|
||||||
}
|
}
|
||||||
|
|
||||||
var descriptor = TargetMethod.getDescriptor(lambda.type(), params.toArray(TargetType[]::new));
|
var descriptor = TargetMethod.getDescriptor(lambda.type(), params.toArray(TargetType[]::new));
|
||||||
@@ -1189,6 +1205,12 @@ public class Codegen {
|
|||||||
}
|
}
|
||||||
case TargetMethodCall call: {
|
case TargetMethodCall call: {
|
||||||
if (!call.isStatic()) {
|
if (!call.isStatic()) {
|
||||||
|
if (call.expr() instanceof TargetThis && state.isStatic) {
|
||||||
|
throw new CodeGenException(
|
||||||
|
"Attempted to call instance method " + call.name() +
|
||||||
|
" with descriptor " + call.getDescriptor() + " from a static context"
|
||||||
|
);
|
||||||
|
}
|
||||||
generate(state, call.expr());
|
generate(state, call.expr());
|
||||||
boxPrimitive(state, call.expr().type());
|
boxPrimitive(state, call.expr().type());
|
||||||
}
|
}
|
||||||
@@ -1199,11 +1221,13 @@ public class Codegen {
|
|||||||
convertTo(state, e.type(), arg);
|
convertTo(state, e.type(), arg);
|
||||||
}
|
}
|
||||||
var descriptor = call.getDescriptor();
|
var descriptor = call.getDescriptor();
|
||||||
|
TargetType casted = call.type();
|
||||||
if (call.owner() instanceof TargetFunNType owner) {
|
if (call.owner() instanceof TargetFunNType owner) {
|
||||||
// Decay FunN
|
|
||||||
descriptor = TargetMethod.getDescriptor(
|
descriptor = TargetMethod.getDescriptor(
|
||||||
(owner.returnArguments() == 0 ? null : TargetType.Object),
|
(owner.returnArguments() == 0 ? null : TargetType.Object),
|
||||||
call.parameterTypes().stream().map(x -> TargetType.Object).toArray(TargetType[]::new));
|
call.parameterTypes().stream().map(x -> TargetType.Object).toArray(TargetType[]::new));
|
||||||
|
if (owner.returnArguments() != 0)
|
||||||
|
casted = FunNGenerator.getReturnType(owner.funNParams());
|
||||||
}
|
}
|
||||||
|
|
||||||
int insn = INVOKEVIRTUAL;
|
int insn = INVOKEVIRTUAL;
|
||||||
@@ -1219,7 +1243,7 @@ public class Codegen {
|
|||||||
unboxPrimitive(state, call.type());
|
unboxPrimitive(state, call.type());
|
||||||
}*/
|
}*/
|
||||||
if (call.type() != null)
|
if (call.type() != null)
|
||||||
convertTo(state, call.returnType(), call.type());
|
convertTo(state, call.returnType(), casted);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TargetLambdaExpression lambda:
|
case TargetLambdaExpression lambda:
|
||||||
@@ -1744,7 +1768,7 @@ public class Codegen {
|
|||||||
generate(state, method.block());
|
generate(state, method.block());
|
||||||
if (method.signature().returnType() == null)
|
if (method.signature().returnType() == null)
|
||||||
mv.visitInsn(RETURN);
|
mv.visitInsn(RETURN);
|
||||||
mv.visitMaxs(0, 0);
|
mv.visitMaxs(0, 0);
|
||||||
}
|
}
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
@@ -1810,54 +1834,77 @@ public class Codegen {
|
|||||||
// Generate wrapper classes for function types
|
// Generate wrapper classes for function types
|
||||||
for (var pair : funWrapperClasses.keySet()) {
|
for (var pair : funWrapperClasses.keySet()) {
|
||||||
var className = funWrapperClasses.get(pair);
|
var className = funWrapperClasses.get(pair);
|
||||||
ClassWriter cw2 = new CustomClassWriter();
|
|
||||||
cw2.visit(V1_8, ACC_PUBLIC, className, null, "java/lang/Object", new String[] { pair.to.getInternalName() });
|
|
||||||
cw2.visitField(ACC_PRIVATE, "wrapped", pair.from.toDescriptor(), null, null).visitEnd();
|
|
||||||
|
|
||||||
// Generate constructor
|
var toName = "apply";
|
||||||
var ctor = cw2.visitMethod(ACC_PUBLIC, "<init>", "(" + pair.from.toDescriptor() + ")V", null, null);
|
TargetType toReturn;
|
||||||
ctor.visitVarInsn(ALOAD, 0);
|
TargetType[] toParams;
|
||||||
ctor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
|
||||||
ctor.visitVarInsn(ALOAD, 0);
|
if (!(pair.to instanceof TargetFunNType to)) {
|
||||||
ctor.visitVarInsn(ALOAD, 1);
|
var toClass = compiler.getClass(new JavaClassName(pair.to.name()));
|
||||||
ctor.visitFieldInsn(PUTFIELD, className, "wrapped", pair.from.toDescriptor());
|
var toMethod = toClass.getMethods().stream().filter(m -> (m.modifier & ACC_ABSTRACT) != 0).findFirst().orElseThrow();
|
||||||
ctor.visitInsn(RETURN);
|
toReturn = converter.convert(toMethod.getReturnType());
|
||||||
ctor.visitMaxs(0, 0);
|
toParams = converter.convert(toMethod.getParameterList()).stream().map(m -> m.pattern().type()).toArray(TargetType[]::new);
|
||||||
ctor.visitEnd();
|
toName = toMethod.name;
|
||||||
|
} else if (pair.from instanceof TargetFunNType from) {
|
||||||
|
toReturn = from.returnArguments() == 0 ? null : TargetType.Object;
|
||||||
|
toParams = from.funNParams().subList(0, from.funNParams().size() - 1).stream().map(x -> TargetType.Object).toArray(TargetType[]::new);
|
||||||
|
} else {
|
||||||
|
toReturn = to.returnArguments() == 0 ? null : TargetType.Object;
|
||||||
|
toParams = to.funNParams().subList(0, to.funNParams().size() - 1).stream().map(x -> TargetType.Object).toArray(TargetType[]::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
var toDescriptor = TargetMethod.getDescriptor(toReturn, toParams);
|
||||||
|
var fieldDescriptor = pair.from.toDescriptor();
|
||||||
|
|
||||||
String methodName = "apply";
|
String methodName = "apply";
|
||||||
String fromDescriptor = null;
|
String fromDescriptor = null;
|
||||||
TargetType fromReturn = null;
|
TargetType fromReturn = null;
|
||||||
if (!(pair.from instanceof TargetFunNType funNType)) {
|
String fromClass = pair.from.getInternalName();
|
||||||
var fromClass = compiler.getClass(new JavaClassName(pair.from.name()));
|
if (isFunctionalInterface(pair.from) && !(pair.from instanceof TargetFunNType)) {
|
||||||
var fromMethod = fromClass.getMethods().stream().filter(m -> (m.modifier & ACC_ABSTRACT) != 0).findFirst().orElseThrow();
|
var clazz = compiler.getClass(new JavaClassName(pair.from.name()));
|
||||||
|
var fromMethod = clazz.getMethods().stream().filter(m -> (m.modifier & ACC_ABSTRACT) != 0).findFirst().orElseThrow();
|
||||||
methodName = fromMethod.name;
|
methodName = fromMethod.name;
|
||||||
|
|
||||||
fromReturn = converter.convert(fromMethod.getReturnType());
|
fromReturn = converter.convert(fromMethod.getReturnType());
|
||||||
var fromParams = converter.convert(fromMethod.getParameterList()).stream().map(m -> m.pattern().type()).toArray(TargetType[]::new);
|
var fromParams = converter.convert(fromMethod.getParameterList()).stream().map(m -> m.pattern().type()).toArray(TargetType[]::new);
|
||||||
fromDescriptor = TargetMethod.getDescriptor(fromReturn, fromParams);
|
fromDescriptor = TargetMethod.getDescriptor(fromReturn, fromParams);
|
||||||
} else {
|
} else if (pair.from instanceof TargetFunNType funNType) {
|
||||||
fromReturn = funNType.returnArguments() > 0 ? TargetType.Object : null;
|
fromReturn = funNType.returnArguments() > 0 ? TargetType.Object : null;
|
||||||
fromDescriptor = funNType.toMethodDescriptor();
|
fromDescriptor = funNType.toMethodDescriptor();
|
||||||
|
} else {
|
||||||
|
fromDescriptor = toDescriptor;
|
||||||
|
fromReturn = toReturn;
|
||||||
|
var to = (TargetFunNType) pair.to;
|
||||||
|
fromClass = FunNGenerator.getSuperClassName(to.funNParams().size() - 1, to.returnArguments());
|
||||||
|
fieldDescriptor = "L" + fromClass + ";";
|
||||||
}
|
}
|
||||||
|
|
||||||
var toClass = compiler.getClass(new JavaClassName(pair.to.name()));
|
ClassWriter cw2 = new CustomClassWriter();
|
||||||
var toMethod = toClass.getMethods().stream().filter(m -> (m.modifier & ACC_ABSTRACT) != 0).findFirst().orElseThrow();
|
cw2.visit(V1_8, ACC_PUBLIC, className, null, "java/lang/Object", new String[] { pair.to.getInternalName() });
|
||||||
var toReturn = converter.convert(toMethod.getReturnType());
|
cw2.visitField(ACC_PRIVATE, "wrapped", fieldDescriptor, null, null).visitEnd();
|
||||||
var toParams = converter.convert(toMethod.getParameterList()).stream().map(m -> m.pattern().type()).toArray(TargetType[]::new);
|
|
||||||
var toDescriptor = TargetMethod.getDescriptor(toReturn, toParams);
|
// Generate constructor
|
||||||
|
var ctor = cw2.visitMethod(ACC_PUBLIC, "<init>", "(Ljava/lang/Object;)V", null, null);
|
||||||
|
ctor.visitVarInsn(ALOAD, 0);
|
||||||
|
ctor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
||||||
|
ctor.visitVarInsn(ALOAD, 0);
|
||||||
|
ctor.visitVarInsn(ALOAD, 1);
|
||||||
|
ctor.visitFieldInsn(PUTFIELD, className, "wrapped", fieldDescriptor);
|
||||||
|
ctor.visitInsn(RETURN);
|
||||||
|
ctor.visitMaxs(0, 0);
|
||||||
|
ctor.visitEnd();
|
||||||
|
|
||||||
// Generate wrapper method
|
// Generate wrapper method
|
||||||
var mv = cw2.visitMethod(ACC_PUBLIC, toMethod.name, toDescriptor, null, null);
|
var mv = cw2.visitMethod(ACC_PUBLIC, toName, toDescriptor, null, null);
|
||||||
var state = new State(null, mv, 0, false);
|
var state = new State(null, mv, 0, false);
|
||||||
|
|
||||||
mv.visitVarInsn(ALOAD, 0);
|
mv.visitVarInsn(ALOAD, 0);
|
||||||
mv.visitFieldInsn(GETFIELD, className, "wrapped", pair.from.toDescriptor());
|
mv.visitFieldInsn(GETFIELD, className, "wrapped", fieldDescriptor);
|
||||||
for (var i = 0; i < toParams.length; i++) {
|
for (var i = 0; i < toParams.length; i++) {
|
||||||
var arg = toParams[i];
|
var arg = toParams[i];
|
||||||
mv.visitVarInsn(findLoadCode(arg), i + 1);
|
mv.visitVarInsn(findLoadCode(arg), i + 1);
|
||||||
}
|
}
|
||||||
mv.visitMethodInsn(INVOKEINTERFACE, pair.from.getInternalName(), methodName, fromDescriptor, true);
|
mv.visitMethodInsn(INVOKEINTERFACE, fromClass, methodName, fromDescriptor, true);
|
||||||
if (fromReturn != null) {
|
if (fromReturn != null) {
|
||||||
if (toReturn instanceof TargetPrimitiveType) {
|
if (toReturn instanceof TargetPrimitiveType) {
|
||||||
convertTo(state, fromReturn, TargetType.toWrapper(toReturn));
|
convertTo(state, fromReturn, TargetType.toWrapper(toReturn));
|
||||||
|
|||||||
@@ -714,6 +714,9 @@ public class JavaTXCompiler {
|
|||||||
new SuperWildcardType(toRefType(targetSuperWildcard.innerType()), new NullToken());
|
new SuperWildcardType(toRefType(targetSuperWildcard.innerType()), new NullToken());
|
||||||
case TargetGenericType targetGenericType -> new GenericRefType(targetGenericType.name(), new NullToken());
|
case TargetGenericType targetGenericType -> new GenericRefType(targetGenericType.name(), new NullToken());
|
||||||
case TargetPrimitiveType targetPrimitiveType -> toRefType(TargetType.toWrapper(targetPrimitiveType));
|
case TargetPrimitiveType targetPrimitiveType -> toRefType(TargetType.toWrapper(targetPrimitiveType));
|
||||||
|
case TargetFunNType targetFunNType ->
|
||||||
|
new RefType(new JavaClassName(FunNGenerator.getSuperClassName(targetFunNType.funNParams().size() - 1, targetFunNType.returnArguments())),
|
||||||
|
targetFunNType.funNParams().stream().map(JavaTXCompiler::toRefType).toList(), new NullToken());
|
||||||
case TargetSpecializedType targetSpecializedType ->
|
case TargetSpecializedType targetSpecializedType ->
|
||||||
new RefType(new JavaClassName(targetSpecializedType.name()),
|
new RefType(new JavaClassName(targetSpecializedType.name()),
|
||||||
targetSpecializedType.params().stream().map(JavaTXCompiler::toRefType).toList(), new NullToken()
|
targetSpecializedType.params().stream().map(JavaTXCompiler::toRefType).toList(), new NullToken()
|
||||||
|
|||||||
+20
-16
@@ -80,7 +80,7 @@ public class SyntaxTreeGenerator {
|
|||||||
HashMap<String, Integer> allmodifiers = new HashMap<>();
|
HashMap<String, Integer> allmodifiers = new HashMap<>();
|
||||||
// PL 2018-11-01 fields eingefuegt, damit die fields immer die gleiche TPH
|
// PL 2018-11-01 fields eingefuegt, damit die fields immer die gleiche TPH
|
||||||
// bekommen
|
// bekommen
|
||||||
private final Map<String, FieldEntry> fields = new HashMap<>();
|
//private final Map<String, FieldEntry> fields = new HashMap<>();
|
||||||
// PL 2019-10-23: Muss für jede Klasse neu initilisiert werden
|
// PL 2019-10-23: Muss für jede Klasse neu initilisiert werden
|
||||||
List<Statement> fieldInitializations = new ArrayList<>();
|
List<Statement> fieldInitializations = new ArrayList<>();
|
||||||
List<Statement> staticFieldInitializations = new ArrayList<>();
|
List<Statement> staticFieldInitializations = new ArrayList<>();
|
||||||
@@ -178,6 +178,7 @@ public class SyntaxTreeGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ClassOrInterface convertClass(Java17Parser.ClassDeclarationContext ctx, int modifiers) {
|
private ClassOrInterface convertClass(Java17Parser.ClassDeclarationContext ctx, int modifiers) {
|
||||||
|
var fieldDecls = new HashMap<String, FieldEntry>();
|
||||||
String className = this.pkgName + (this.pkgName.length() > 0 ? "." : "") + ctx.identifier().getText();
|
String className = this.pkgName + (this.pkgName.length() > 0 ? "." : "") + ctx.identifier().getText();
|
||||||
JavaClassName name = reg.getName(className); // Holt den Package Namen mit dazu
|
JavaClassName name = reg.getName(className); // Holt den Package Namen mit dazu
|
||||||
if (!name.toString().equals(className)) { // Kommt die Klasse schon in einem anderen Package vor?
|
if (!name.toString().equals(className)) { // Kommt die Klasse schon in einem anderen Package vor?
|
||||||
@@ -206,7 +207,7 @@ public class SyntaxTreeGenerator {
|
|||||||
List<RefType> implementedInterfaces = new ArrayList<>();
|
List<RefType> implementedInterfaces = new ArrayList<>();
|
||||||
List<RefType> permittedSubtypes = null;
|
List<RefType> permittedSubtypes = null;
|
||||||
for (ClassBodyDeclarationContext clsbodydecl : ctx.classBody().classBodyDeclaration()) {
|
for (ClassBodyDeclarationContext clsbodydecl : ctx.classBody().classBodyDeclaration()) {
|
||||||
convert(clsbodydecl, fielddecl, constructors, methods, name, superClass, generics);
|
convert(clsbodydecl, fielddecl, constructors, methods, name, superClass, generics, fieldDecls);
|
||||||
}
|
}
|
||||||
if (constructors.isEmpty()) {
|
if (constructors.isEmpty()) {
|
||||||
constructors.add(generateStandardConstructor(ctx.identifier().getText(), name, superClass, genericClassParameters, offset));
|
constructors.add(generateStandardConstructor(ctx.identifier().getText(), name, superClass, genericClassParameters, offset));
|
||||||
@@ -255,6 +256,8 @@ public class SyntaxTreeGenerator {
|
|||||||
List<Pattern> constructorParameters = new ArrayList<>();
|
List<Pattern> constructorParameters = new ArrayList<>();
|
||||||
List<Statement> constructorStatements = new ArrayList<>();
|
List<Statement> constructorStatements = new ArrayList<>();
|
||||||
|
|
||||||
|
var fieldDecl = new HashMap<String, FieldEntry>();
|
||||||
|
|
||||||
List<Java17Parser.RecordComponentContext> components = recordDeclaration.recordHeader().recordComponentList() != null ?
|
List<Java17Parser.RecordComponentContext> components = recordDeclaration.recordHeader().recordComponentList() != null ?
|
||||||
recordDeclaration.recordHeader().recordComponentList().recordComponent(): List.of();
|
recordDeclaration.recordHeader().recordComponentList().recordComponent(): List.of();
|
||||||
for (RecordComponentContext component : components) {
|
for (RecordComponentContext component : components) {
|
||||||
@@ -270,6 +273,7 @@ public class SyntaxTreeGenerator {
|
|||||||
fielddecl.add(new Field(fieldname, fieldtype, fieldmodifiers, fieldoffset));
|
fielddecl.add(new Field(fieldname, fieldtype, fieldmodifiers, fieldoffset));
|
||||||
constructorParameters.add(new FormalParameter(fieldname, fieldtype, fieldoffset));
|
constructorParameters.add(new FormalParameter(fieldname, fieldtype, fieldoffset));
|
||||||
FieldVar fieldvar = new FieldVar(new This(offset), fieldname, fieldtype, fieldoffset);
|
FieldVar fieldvar = new FieldVar(new This(offset), fieldname, fieldtype, fieldoffset);
|
||||||
|
fieldDecl.put(fieldname, new FieldEntry(fieldname, fieldtype, Modifier.PRIVATE));
|
||||||
constructorStatements.add(new Assign(new AssignToField(fieldvar), new LocalVar(fieldname, fieldtype, fieldoffset), offset));
|
constructorStatements.add(new Assign(new AssignToField(fieldvar), new LocalVar(fieldname, fieldtype, fieldoffset), offset));
|
||||||
Statement returnStatement = new Return(fieldvar, offset);
|
Statement returnStatement = new Return(fieldvar, offset);
|
||||||
methods.add(new Method(allmodifiers.get("public"), fieldname, fieldtype, new ParameterList(new ArrayList<>(), offset), new Block(Arrays.asList(returnStatement), offset), new GenericDeclarationList(new ArrayList<>(), offset), offset));
|
methods.add(new Method(allmodifiers.get("public"), fieldname, fieldtype, new ParameterList(new ArrayList<>(), offset), new Block(Arrays.asList(returnStatement), offset), new GenericDeclarationList(new ArrayList<>(), offset), offset));
|
||||||
@@ -279,7 +283,7 @@ public class SyntaxTreeGenerator {
|
|||||||
//Optional<Constructor> initializations = Optional.of(implicitConstructor);
|
//Optional<Constructor> initializations = Optional.of(implicitConstructor);
|
||||||
constructors.add(implicitConstructor);
|
constructors.add(implicitConstructor);
|
||||||
for (ClassBodyDeclarationContext bodyDeclaration : recordDeclaration.recordBody().classBodyDeclaration()) {
|
for (ClassBodyDeclarationContext bodyDeclaration : recordDeclaration.recordBody().classBodyDeclaration()) {
|
||||||
convert(bodyDeclaration, fielddecl, constructors, methods, name, superClass, generics);
|
convert(bodyDeclaration, fielddecl, constructors, methods, name, superClass, generics, fieldDecl);
|
||||||
}
|
}
|
||||||
if (!Objects.isNull(recordDeclaration.IMPLEMENTS())) {
|
if (!Objects.isNull(recordDeclaration.IMPLEMENTS())) {
|
||||||
implementedInterfaces.addAll(convert(recordDeclaration.typeList(), generics));
|
implementedInterfaces.addAll(convert(recordDeclaration.typeList(), generics));
|
||||||
@@ -288,7 +292,7 @@ public class SyntaxTreeGenerator {
|
|||||||
return new Record(modifiers, name, fielddecl, Optional.empty(), staticCtor, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, offset, fileName);
|
return new Record(modifiers, name, fielddecl, Optional.empty(), staticCtor, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, offset, fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void convert(ClassBodyDeclarationContext classBody, List<Field> fields, List<Constructor> constructors, List<Method> methods, JavaClassName name, RefType superClass, GenericsRegistry generics) {
|
private void convert(ClassBodyDeclarationContext classBody, List<Field> fields, List<Constructor> constructors, List<Method> methods, JavaClassName name, RefType superClass, GenericsRegistry generics, HashMap<String, FieldEntry> fieldDecls) {
|
||||||
MemberdeclContext member;
|
MemberdeclContext member;
|
||||||
if (classBody instanceof MemberdeclContext) {
|
if (classBody instanceof MemberdeclContext) {
|
||||||
member = (MemberdeclContext) classBody;
|
member = (MemberdeclContext) classBody;
|
||||||
@@ -303,11 +307,11 @@ public class SyntaxTreeGenerator {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MemberfieldContext memberfield: {
|
case MemberfieldContext memberfield: {
|
||||||
fields.addAll(convert(memberfield.fieldDeclaration(), membermodifiers, generics));
|
fields.addAll(convert(memberfield.fieldDeclaration(), membermodifiers, generics, fieldDecls));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MembermethodContext membermethod: {
|
case MembermethodContext membermethod: {
|
||||||
Method convertedMethod = convert(membermodifiers, membermethod.method(), name, superClass, generics);
|
Method convertedMethod = convert(membermodifiers, membermethod.method(), name, superClass, generics, fieldDecls);
|
||||||
if (convertedMethod instanceof Constructor constructor) {
|
if (convertedMethod instanceof Constructor constructor) {
|
||||||
constructors.add(constructor);
|
constructors.add(constructor);
|
||||||
} else {
|
} else {
|
||||||
@@ -316,7 +320,7 @@ public class SyntaxTreeGenerator {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MemberconstructorContext memberconstructor: {
|
case MemberconstructorContext memberconstructor: {
|
||||||
constructors.add(convert(membermodifiers, memberconstructor.constructor(), name, superClass, generics));
|
constructors.add(convert(membermodifiers, memberconstructor.constructor(), name, superClass, generics, fieldDecls));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -324,7 +328,7 @@ public class SyntaxTreeGenerator {
|
|||||||
}
|
}
|
||||||
} else if (classBody instanceof Java17Parser.ClassblockContext ctx && ctx.STATIC() != null) {
|
} else if (classBody instanceof Java17Parser.ClassblockContext ctx && ctx.STATIC() != null) {
|
||||||
// Static blocks
|
// Static blocks
|
||||||
var stmtgen = new StatementGenerator(superClass, compiler, reg, generics, this.fields, new HashMap<>());
|
var stmtgen = new StatementGenerator(superClass, compiler, reg, generics, fieldDecls, new HashMap<>());
|
||||||
var block = stmtgen.convert(((Java17Parser.ClassblockContext) classBody).block(), false);
|
var block = stmtgen.convert(((Java17Parser.ClassblockContext) classBody).block(), false);
|
||||||
staticFieldInitializations.addAll(block.statements);
|
staticFieldInitializations.addAll(block.statements);
|
||||||
}
|
}
|
||||||
@@ -434,7 +438,7 @@ public class SyntaxTreeGenerator {
|
|||||||
retType = new Void(bodydeclaration.refType().getStart());
|
retType = new Void(bodydeclaration.refType().getStart());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StatementGenerator stmtgen = new StatementGenerator(superClass, compiler, reg, generics, fields, new HashMap<>());
|
StatementGenerator stmtgen = new StatementGenerator(superClass, compiler, reg, generics, new HashMap<>(), new HashMap<>());
|
||||||
ParameterList paramlist = stmtgen.convert(bodydeclaration.formalParameters().formalParameterList(), true);
|
ParameterList paramlist = stmtgen.convert(bodydeclaration.formalParameters().formalParameterList(), true);
|
||||||
MethodBodyContext body = bodydeclaration.methodBody();
|
MethodBodyContext body = bodydeclaration.methodBody();
|
||||||
Block block = null;
|
Block block = null;
|
||||||
@@ -507,7 +511,7 @@ public class SyntaxTreeGenerator {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Method convert(int modifiers, Java17Parser.MethodContext methodContext, JavaClassName parentClass, RefType superClass, GenericsRegistry generics) {
|
public Method convert(int modifiers, Java17Parser.MethodContext methodContext, JavaClassName parentClass, RefType superClass, GenericsRegistry generics, Map<String, FieldEntry> fieldDecls) {
|
||||||
GenericsRegistry localgenerics = generics;
|
GenericsRegistry localgenerics = generics;
|
||||||
MethodDeclarationContext methoddeclaration;
|
MethodDeclarationContext methoddeclaration;
|
||||||
GenericDeclarationListContext genericdeclarations;
|
GenericDeclarationListContext genericdeclarations;
|
||||||
@@ -540,7 +544,7 @@ public class SyntaxTreeGenerator {
|
|||||||
retType = new Void(header.refType().getStart());
|
retType = new Void(header.refType().getStart());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StatementGenerator stmtgen = new StatementGenerator(superClass, compiler, reg, localgenerics, fields, new HashMap<>());
|
StatementGenerator stmtgen = new StatementGenerator(superClass, compiler, reg, localgenerics, fieldDecls, new HashMap<>());
|
||||||
ParameterList paramlist = stmtgen.convert(header.formalParameters().formalParameterList(), true);
|
ParameterList paramlist = stmtgen.convert(header.formalParameters().formalParameterList(), true);
|
||||||
MethodBodyContext body = methoddeclaration.methodBody();
|
MethodBodyContext body = methoddeclaration.methodBody();
|
||||||
Block block = null;
|
Block block = null;
|
||||||
@@ -559,7 +563,7 @@ public class SyntaxTreeGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Constructor convert(int modifiers, Java17Parser.ConstructorContext constructorContext, JavaClassName parentClass, RefType superClass, GenericsRegistry generics) {
|
public Constructor convert(int modifiers, Java17Parser.ConstructorContext constructorContext, JavaClassName parentClass, RefType superClass, GenericsRegistry generics, Map<String, FieldEntry> fields) {
|
||||||
GenericsRegistry localgenerics = generics;
|
GenericsRegistry localgenerics = generics;
|
||||||
GenericDeclarationListContext genericdeclarations;
|
GenericDeclarationListContext genericdeclarations;
|
||||||
GenericDeclarationList gtvDeclarations;
|
GenericDeclarationList gtvDeclarations;
|
||||||
@@ -586,7 +590,7 @@ public class SyntaxTreeGenerator {
|
|||||||
return new Constructor(modifiers, name, retType, paramlist, block, gtvDeclarations, constructordeclaration.getStart());
|
return new Constructor(modifiers, name, retType, paramlist, block, gtvDeclarations, constructordeclaration.getStart());
|
||||||
}
|
}
|
||||||
|
|
||||||
List<? extends Field> convert(Java17Parser.FieldDeclarationContext fieldDeclContext, int modifiers, GenericsRegistry generics) {
|
List<? extends Field> convert(Java17Parser.FieldDeclarationContext fieldDeclContext, int modifiers, GenericsRegistry generics, HashMap<String, FieldEntry> fields) {
|
||||||
List<Field> ret = new ArrayList<>();
|
List<Field> ret = new ArrayList<>();
|
||||||
RefTypeOrTPHOrWildcardOrGeneric fieldType;
|
RefTypeOrTPHOrWildcardOrGeneric fieldType;
|
||||||
if (fieldDeclContext.typeType() != null) {
|
if (fieldDeclContext.typeType() != null) {
|
||||||
@@ -598,9 +602,9 @@ public class SyntaxTreeGenerator {
|
|||||||
}
|
}
|
||||||
for (Java17Parser.VariableDeclaratorContext varDecl : fieldDeclContext.variableDeclarators().variableDeclarator()) {
|
for (Java17Parser.VariableDeclaratorContext varDecl : fieldDeclContext.variableDeclarators().variableDeclarator()) {
|
||||||
String fieldName = varDecl.variableDeclaratorId().getText();
|
String fieldName = varDecl.variableDeclaratorId().getText();
|
||||||
this.fields.put(fieldName, new FieldEntry(fieldName, fieldType, modifiers));
|
fields.put(fieldName, new FieldEntry(fieldName, fieldType, modifiers));
|
||||||
if (varDecl.variableInitializer() != null) {
|
if (varDecl.variableInitializer() != null) {
|
||||||
initializeField(varDecl, Modifier.isStatic(modifiers), fieldType, generics);
|
initializeField(varDecl, Modifier.isStatic(modifiers), fieldType, generics, fields);
|
||||||
}
|
}
|
||||||
ret.add(new Field(fieldName, fieldType, modifiers, varDecl.getStart()));
|
ret.add(new Field(fieldName, fieldType, modifiers, varDecl.getStart()));
|
||||||
}
|
}
|
||||||
@@ -612,7 +616,7 @@ public class SyntaxTreeGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initialize a field by creating implicit constructor.
|
// Initialize a field by creating implicit constructor.
|
||||||
private void initializeField(Java17Parser.VariableDeclaratorContext ctx, boolean isStatic, RefTypeOrTPHOrWildcardOrGeneric typeOfField, GenericsRegistry generics) {
|
private void initializeField(Java17Parser.VariableDeclaratorContext ctx, boolean isStatic, RefTypeOrTPHOrWildcardOrGeneric typeOfField, GenericsRegistry generics, Map<String, FieldEntry> fields) {
|
||||||
StatementGenerator statementGenerator = new StatementGenerator(superClass, compiler, reg, generics, fields, new HashMap<>());
|
StatementGenerator statementGenerator = new StatementGenerator(superClass, compiler, reg, generics, fields, new HashMap<>());
|
||||||
var assignment = statementGenerator.generateFieldAssignment(ctx, typeOfField);
|
var assignment = statementGenerator.generateFieldAssignment(ctx, typeOfField);
|
||||||
if (isStatic) {
|
if (isStatic) {
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package de.dhbwstuttgart.target.generate;
|
package de.dhbwstuttgart.target.generate;
|
||||||
|
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import de.dhbwstuttgart.bytecode.CodeGenException;
|
||||||
import de.dhbwstuttgart.bytecode.FunNGenerator;
|
import de.dhbwstuttgart.bytecode.FunNGenerator;
|
||||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||||
import de.dhbwstuttgart.environment.IByteArrayClassLoader;
|
import de.dhbwstuttgart.environment.IByteArrayClassLoader;
|
||||||
@@ -21,6 +23,7 @@ import de.dhbwstuttgart.target.tree.type.*;
|
|||||||
import de.dhbwstuttgart.typeinference.result.*;
|
import de.dhbwstuttgart.typeinference.result.*;
|
||||||
import de.dhbwstuttgart.typeinference.unify.MartelliMontanariUnify;
|
import de.dhbwstuttgart.typeinference.unify.MartelliMontanariUnify;
|
||||||
import de.dhbwstuttgart.typeinference.unify.model.*;
|
import de.dhbwstuttgart.typeinference.unify.model.*;
|
||||||
|
import de.dhbwstuttgart.util.Logger;
|
||||||
import org.antlr.v4.runtime.Token;
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@@ -80,8 +83,8 @@ public class ASTToTargetAST {
|
|||||||
this(new JavaGenerics(compiler, set), new TxGenerics(compiler, set));
|
this(new JavaGenerics(compiler, set), new TxGenerics(compiler, set));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Generics nullGenerics() {
|
public static Generics nullGenerics(JavaTXCompiler compiler) {
|
||||||
return new Generics(null, new ResultSet(Set.of()));
|
return new Generics(compiler, new ResultSet(Set.of()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,16 +116,38 @@ public class ASTToTargetAST {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Optional<Method> findMethod(ClassOrInterface owner, String name, List<TargetType> argumentList, JavaTXCompiler compiler) {
|
public static Optional<Method> findMethod(ClassOrInterface owner, String name, List<TargetType> argumentList, JavaTXCompiler compiler) {
|
||||||
return findMethod(owner, name, argumentList, Generics.nullGenerics().javaGenerics(), compiler);
|
return findMethod(owner, name, argumentList, Generics.nullGenerics(compiler).javaGenerics(), compiler);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Optional<Method> findMethod(ClassOrInterface owner, String name, List<TargetType> argumentList, IGenerics generics, JavaTXCompiler compiler) {
|
public static Optional<Method> findMethod(ClassOrInterface owner, String name, List<TargetType> argumentList, IGenerics generics, JavaTXCompiler compiler) {
|
||||||
Optional<Method> method = Optional.empty();
|
Optional<Method> method = Optional.empty();
|
||||||
while (method.isEmpty()) {
|
while (method.isEmpty()) {
|
||||||
method = owner.getMethods().stream().filter(m -> {
|
var methods = owner.getMethods().stream().filter(m -> {
|
||||||
return m.name.equals(name) &&
|
if (!m.name.equals(name)) return false;
|
||||||
parameterEquals(m.getParameterList().getFormalparalist().stream().map(p -> generics.getTargetType(p.getType())).toList(), argumentList);
|
var plist = m.getParameterList().getFormalparalist().stream().map(p -> generics.getTargetType(p.getType())).toList();
|
||||||
}).findFirst();
|
return parameterEquals(plist, argumentList, compiler);
|
||||||
|
}).toList();
|
||||||
|
|
||||||
|
if (!methods.isEmpty()) {
|
||||||
|
// Find the most specific method
|
||||||
|
var resultMethods = new ArrayList<Method>();
|
||||||
|
|
||||||
|
outer: for (var ma : methods) {
|
||||||
|
for (Method mb : methods) {
|
||||||
|
for (var k = 0; k < ma.getParameterList().getFormalparalist().size(); k++) {
|
||||||
|
var parama = generics.getTargetType(ma.getParameterList().getParameterAt(k).getType());
|
||||||
|
var paramb = generics.getTargetType(mb.getParameterList().getParameterAt(k).getType());
|
||||||
|
|
||||||
|
if (!Objects.equals(parama, paramb) && isFunOrSubtype(paramb, parama, compiler)) {
|
||||||
|
continue outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultMethods.add(ma);
|
||||||
|
}
|
||||||
|
if (resultMethods.isEmpty()) method = Optional.of(methods.getFirst());
|
||||||
|
else method = Optional.of(resultMethods.getFirst());
|
||||||
|
}
|
||||||
if (owner.getClassName().toString().equals("java.lang.Object")) break;
|
if (owner.getClassName().toString().equals("java.lang.Object")) break;
|
||||||
owner = compiler.getClass(owner.getSuperClass().getName());
|
owner = compiler.getClass(owner.getSuperClass().getName());
|
||||||
}
|
}
|
||||||
@@ -131,10 +156,10 @@ public class ASTToTargetAST {
|
|||||||
|
|
||||||
Optional<Constructor> findConstructor(ClassOrInterface owner, List<TargetType> argumentList, IGenerics generics) {
|
Optional<Constructor> findConstructor(ClassOrInterface owner, List<TargetType> argumentList, IGenerics generics) {
|
||||||
return owner.getConstructors().stream().filter(c ->
|
return owner.getConstructors().stream().filter(c ->
|
||||||
parameterEquals(c.getParameterList().getFormalparalist().stream().map(p -> generics.getTargetType(p.getType())).toList(), argumentList)).findFirst();
|
parameterEquals(c.getParameterList().getFormalparalist().stream().map(p -> generics.getTargetType(p.getType())).toList(), argumentList, compiler)).findFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean parameterEquals(List<TargetType> pars, List<TargetType> arguments) {
|
static boolean parameterEquals(List<TargetType> pars, List<TargetType> arguments, JavaTXCompiler compiler) {
|
||||||
if (pars.size() != arguments.size())
|
if (pars.size() != arguments.size())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -145,6 +170,8 @@ public class ASTToTargetAST {
|
|||||||
return true;
|
return true;
|
||||||
if (TargetType.toPrimitive(type2).equals(type1))
|
if (TargetType.toPrimitive(type2).equals(type1))
|
||||||
return true;
|
return true;
|
||||||
|
if (type1 instanceof TargetFunNType tfun1 && type2 instanceof TargetFunNType tfun2)
|
||||||
|
return funNIsSubtype(tfun2, tfun1, compiler);
|
||||||
if (!type1.equals(type2))
|
if (!type1.equals(type2))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -152,6 +179,33 @@ public class ASTToTargetAST {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isFunOrSubtype(TargetType from, TargetType to, JavaTXCompiler compiler) {
|
||||||
|
if (to instanceof TargetGenericType) return true;
|
||||||
|
if (from instanceof TargetFunNType ffun && to instanceof TargetFunNType tfun)
|
||||||
|
return funNIsSubtype(ffun, tfun, compiler);
|
||||||
|
return isSubtype(from, to, compiler);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean funNIsSubtype(TargetFunNType from, TargetFunNType to, JavaTXCompiler compiler) {
|
||||||
|
if (!from.isInterface() && !to.isInterface()) {
|
||||||
|
if (from.funNParams().size() != to.funNParams().size()) return false;
|
||||||
|
for (var i = 0; i < from.funNParams().size() - from.returnArguments(); i++) {
|
||||||
|
var left = from.funNParams().get(i);
|
||||||
|
var right = to.funNParams().get(i);
|
||||||
|
if (!Objects.equals(left, right) && isFunOrSubtype(right, left, compiler))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (from.returnArguments() != 0) {
|
||||||
|
var ret1 = from.funNParams().getLast();
|
||||||
|
var ret2 = to.funNParams().getLast();
|
||||||
|
if (Objects.equals(ret1, ret2)) return true;
|
||||||
|
return isFunOrSubtype(ret1, ret2, compiler);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return from.name().equals(to.name());
|
||||||
|
}
|
||||||
|
|
||||||
Set<TargetGeneric> convert(Set<GenerateGenerics.Pair> result, IGenerics generics) {
|
Set<TargetGeneric> convert(Set<GenerateGenerics.Pair> result, IGenerics generics) {
|
||||||
return result.stream().map(p -> {
|
return result.stream().map(p -> {
|
||||||
if (p instanceof GenerateGenerics.PairLT pair) {
|
if (p instanceof GenerateGenerics.PairLT pair) {
|
||||||
@@ -188,7 +242,7 @@ public class ASTToTargetAST {
|
|||||||
case ExtendsType extendType -> new TargetExtendsWildcard(toTargetType(extendType.getExtendedType()));
|
case ExtendsType extendType -> new TargetExtendsWildcard(toTargetType(extendType.getExtendedType()));
|
||||||
case SuperType superType -> new TargetSuperWildcard(toTargetType(superType.getSuperedType()));
|
case SuperType superType -> new TargetSuperWildcard(toTargetType(superType.getSuperedType()));
|
||||||
case PlaceholderType placeholderType -> new TargetGenericType(placeholderType.getName());
|
case PlaceholderType placeholderType -> new TargetGenericType(placeholderType.getName());
|
||||||
case FunNType funNType -> TargetFunNType.fromParams(StreamSupport.stream(funNType.getTypeParams().spliterator(), false).map(ASTToTargetAST::toTargetType).toList(), 1, false); // FIXME How does this work with Fun0??
|
case FunNType funNType -> TargetFunNType.fromParams(StreamSupport.stream(funNType.getTypeParams().spliterator(), false).map(ASTToTargetAST::toTargetType).toList(), 1); // FIXME How does this work with Fun0??
|
||||||
case ReferenceType referenceType -> new TargetRefType(referenceType.getName(), StreamSupport.stream(referenceType.getTypeParams().spliterator(), false).map(ASTToTargetAST::toTargetType).toList());
|
case ReferenceType referenceType -> new TargetRefType(referenceType.getName(), StreamSupport.stream(referenceType.getTypeParams().spliterator(), false).map(ASTToTargetAST::toTargetType).toList());
|
||||||
default -> throw new NotImplementedException();
|
default -> throw new NotImplementedException();
|
||||||
};
|
};
|
||||||
@@ -240,7 +294,6 @@ public class ASTToTargetAST {
|
|||||||
// Strip off patterns, we don't need them for merged methods, they do a switch case
|
// Strip off patterns, we don't need them for merged methods, they do a switch case
|
||||||
result.add(new MethodParameter(u.get(), a.get(i).pattern().name()));
|
result.add(new MethodParameter(u.get(), a.get(i).pattern().name()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Optional.of(result);
|
return Optional.of(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,7 +415,7 @@ public class ASTToTargetAST {
|
|||||||
return R;
|
return R;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final record CtorWithGenerics(TargetConstructor ctor, IGenerics generics) {}
|
private record CtorWithGenerics(TargetConstructor ctor, IGenerics generics) {}
|
||||||
|
|
||||||
public TargetStructure convert(ClassOrInterface input) {
|
public TargetStructure convert(ClassOrInterface input) {
|
||||||
var generics = all.getFirst();
|
var generics = all.getFirst();
|
||||||
@@ -483,7 +536,7 @@ public class ASTToTargetAST {
|
|||||||
var res = new ArrayList<MethodParameter>();
|
var res = new ArrayList<MethodParameter>();
|
||||||
for (var i = 0; i < input.getFormalparalist().size(); i++) {
|
for (var i = 0; i < input.getFormalparalist().size(); i++) {
|
||||||
var param = input.getFormalparalist().get(i);
|
var param = input.getFormalparalist().get(i);
|
||||||
var pattern = (TargetPattern) convert(param, Generics.nullGenerics().javaGenerics);
|
var pattern = (TargetPattern) convert(param, Generics.nullGenerics(compiler).javaGenerics);
|
||||||
if (pattern instanceof TargetComplexPattern) pattern = pattern.withName("__var" + i);
|
if (pattern instanceof TargetComplexPattern) pattern = pattern.withName("__var" + i);
|
||||||
res.add(new MethodParameter(pattern));
|
res.add(new MethodParameter(pattern));
|
||||||
}
|
}
|
||||||
@@ -583,7 +636,7 @@ public class ASTToTargetAST {
|
|||||||
return caseBody;
|
return caseBody;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TargetExpression generatePatternOverloadsRec(int offset, TargetExpression switchExpr, List<TargetLocalVar> params, List<TargetPattern> patterns, List<TargetMethod> methods, TargetType classType) {
|
private TargetExpression generatePatternOverloadsRec(int offset, TargetExpression switchExpr, List<TargetLocalVar> params, List<TargetPattern> patterns, List<TargetMethod> methods, TargetType classType) {
|
||||||
if (methods.isEmpty()) throw new DebugException("Couldn't find a candidate for switch overloading");
|
if (methods.isEmpty()) throw new DebugException("Couldn't find a candidate for switch overloading");
|
||||||
if (methods.size() == 1) {
|
if (methods.size() == 1) {
|
||||||
var method = methods.getFirst();
|
var method = methods.getFirst();
|
||||||
@@ -593,6 +646,17 @@ public class ASTToTargetAST {
|
|||||||
var cases = new ArrayList<TargetSwitch.Case>();
|
var cases = new ArrayList<TargetSwitch.Case>();
|
||||||
var usedPatterns = new HashSet<TargetPattern>();
|
var usedPatterns = new HashSet<TargetPattern>();
|
||||||
|
|
||||||
|
for (int i = 0; i < methods.size(); i++) {
|
||||||
|
for (int j = i + 1; j < methods.size(); j++) {
|
||||||
|
var m1 = methods.get(i);
|
||||||
|
var m2 = methods.get(j);
|
||||||
|
if (m1.signature().equals(m2.signature()) && m1.base() != m2.base()) {
|
||||||
|
compiler.warn(new CompilerWarning(m1.base().getOffset(), "Duplicate Method definition " + m1.getSimpleName() +
|
||||||
|
" found, signature " + m1.signature().getDescriptor() + " clashes with signature " + m2.signature().getDescriptor()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (var method : methods) {
|
for (var method : methods) {
|
||||||
var patternsRec = new ArrayList<>(patterns);
|
var patternsRec = new ArrayList<>(patterns);
|
||||||
|
|
||||||
@@ -722,7 +786,6 @@ public class ASTToTargetAST {
|
|||||||
|
|
||||||
var classType = new TargetRefType(clazz.getClassName().getClassName());
|
var classType = new TargetRefType(clazz.getClassName().getClassName());
|
||||||
var stmt = generatePatternOverloadsRec(0, new TargetLocalVar(resParams.getFirst().pattern().type(), resParams.getFirst().pattern().name()), parameters, List.of(), methods, classType);
|
var stmt = generatePatternOverloadsRec(0, new TargetLocalVar(resParams.getFirst().pattern().type(), resParams.getFirst().pattern().name()), parameters, List.of(), methods, classType);
|
||||||
System.out.println(stmt);
|
|
||||||
var block = new TargetBlock(List.of(stmt));
|
var block = new TargetBlock(List.of(stmt));
|
||||||
|
|
||||||
var generics = new HashSet<>(firstMethod.signature().generics());
|
var generics = new HashSet<>(firstMethod.signature().generics());
|
||||||
@@ -745,8 +808,8 @@ public class ASTToTargetAST {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isSubtype(a.type(), b.type())) return -1;
|
if (isSubtype(a.type(), b.type(), compiler)) return -1;
|
||||||
if (isSubtype(b.type(), a.type())) return 1;
|
if (isSubtype(b.type(), a.type(), compiler)) return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -892,6 +955,7 @@ public class ASTToTargetAST {
|
|||||||
if (right instanceof TargetExtendsWildcard wc) right = wc.innerType();
|
if (right instanceof TargetExtendsWildcard wc) right = wc.innerType();
|
||||||
|
|
||||||
if (!Objects.equals(left, right)) {
|
if (!Objects.equals(left, right)) {
|
||||||
|
Target.logger.error(m.name + " Discarded " + tph + " was " + left.name() + " and " + right.name());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -946,7 +1010,7 @@ public class ASTToTargetAST {
|
|||||||
.filter(m -> typesAreDifferent(method, m.generics.javaGenerics, signature.generics.javaGenerics)).findFirst();
|
.filter(m -> typesAreDifferent(method, m.generics.javaGenerics, signature.generics.javaGenerics)).findFirst();
|
||||||
if (duplicate.isPresent()) {
|
if (duplicate.isPresent()) {
|
||||||
var d = duplicate.get();
|
var d = duplicate.get();
|
||||||
compiler.warn(new CompilerWarning(method.block.getOffset(), "Duplicate Method definition " + method.name +
|
compiler.warn(new CompilerWarning(method.block.getOffset(), "Duplicate Method definition " + method.getName() +
|
||||||
" found, signature " + d.signature.java.getDescriptor() + " clashes with signature " + signature.java.getDescriptor()));
|
" found, signature " + d.signature.java.getDescriptor() + " clashes with signature " + signature.java.getDescriptor()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1005,7 +1069,7 @@ public class ASTToTargetAST {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static TargetType flattenFunNType(List<TargetType> params, FunNGenerator.GenericParameters gep, boolean isInterface) {
|
static TargetType flattenFunNType(List<TargetType> params, FunNGenerator.GenericParameters gep) {
|
||||||
var newParams = new ArrayList<TargetType>();
|
var newParams = new ArrayList<TargetType>();
|
||||||
for (TargetType param : params) {
|
for (TargetType param : params) {
|
||||||
if (param instanceof TargetSpecializedType fn) {
|
if (param instanceof TargetSpecializedType fn) {
|
||||||
@@ -1019,19 +1083,38 @@ public class ASTToTargetAST {
|
|||||||
if (i < gep.inParams.size() && gep.inParams.get(i) != null)
|
if (i < gep.inParams.size() && gep.inParams.get(i) != null)
|
||||||
filteredParams.add(newParams.get(i));
|
filteredParams.add(newParams.get(i));
|
||||||
}
|
}
|
||||||
return TargetFunNType.fromParams(params, filteredParams, gep.getReturnType() != null ? 1 : 0, isInterface);
|
return TargetFunNType.fromParams(params, filteredParams, gep.getReturnType() != null ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private FunNGenerator.GenericParameters convertToParameters(TargetFunNType input) {
|
private FunNGenerator.GenericParameters convertToParameters(TargetFunNType input) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSubtype(TargetType test, TargetType other) {
|
public static ClassOrInterface getCommonSuperType(TargetType test, TargetType other, JavaTXCompiler compiler) {
|
||||||
|
var testClass = compiler.getClass(new JavaClassName(test.name()));
|
||||||
|
var otherClass = compiler.getClass(new JavaClassName(other.name()));
|
||||||
|
if (testClass == null) return null;
|
||||||
|
while (testClass != null) {
|
||||||
|
if (otherClass.isInterface()) {
|
||||||
|
for (var superInterface : testClass.getSuperInterfaces()) {
|
||||||
|
if (superInterface.getName().equals(otherClass.getClassName())) return otherClass;
|
||||||
|
var c = getCommonSuperType(new TargetRefType(superInterface.getName().toString()), other, compiler);
|
||||||
|
if (c != null) return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (testClass.equals(otherClass)) return testClass;
|
||||||
|
if (testClass.getClassName().equals(new JavaClassName("java.lang.Object"))) return testClass;
|
||||||
|
testClass = compiler.getClass(testClass.getSuperClass().getName());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isSubtype(TargetType test, TargetType other, JavaTXCompiler compiler) {
|
||||||
if (other == null) return false;
|
if (other == null) return false;
|
||||||
if (other.equals(TargetType.Object)) return true;
|
if (other.equals(TargetType.Object)) return true;
|
||||||
if (test instanceof TargetGenericType || other instanceof TargetGenericType) return false;
|
if (test instanceof TargetGenericType || other instanceof TargetGenericType) return false;
|
||||||
if (test instanceof TargetFunNType tfun && other instanceof TargetFunNType ofun)
|
if (test instanceof TargetFunNType tfun && other instanceof TargetFunNType ofun)
|
||||||
return isSubtype(new FunNGenerator.GenericParameters(tfun), new FunNGenerator.GenericParameters(ofun));
|
return isSubtype(new FunNGenerator.GenericParameters(tfun), new FunNGenerator.GenericParameters(ofun), compiler);
|
||||||
if (other instanceof TargetFunNType) return false;
|
if (other instanceof TargetFunNType) return false;
|
||||||
|
|
||||||
var testClass = compiler.getClass(new JavaClassName(test.name()));
|
var testClass = compiler.getClass(new JavaClassName(test.name()));
|
||||||
@@ -1041,7 +1124,7 @@ public class ASTToTargetAST {
|
|||||||
if (otherClass.isInterface()) {
|
if (otherClass.isInterface()) {
|
||||||
for (var superInterface : testClass.getSuperInterfaces()) {
|
for (var superInterface : testClass.getSuperInterfaces()) {
|
||||||
if (superInterface.getName().equals(otherClass.getClassName())) return true;
|
if (superInterface.getName().equals(otherClass.getClassName())) return true;
|
||||||
if (isSubtype(new TargetRefType(superInterface.getName().toString()), other)) return true;
|
if (isSubtype(new TargetRefType(superInterface.getName().toString()), other, compiler)) return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (testClass.equals(otherClass)) return true;
|
if (testClass.equals(otherClass)) return true;
|
||||||
@@ -1051,17 +1134,17 @@ public class ASTToTargetAST {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSupertype(TargetType test, TargetType other) {
|
private static boolean isSupertype(TargetType test, TargetType other, JavaTXCompiler compiler) {
|
||||||
return isSubtype(other, test);
|
return isSubtype(other, test, compiler);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSubtype(FunNGenerator.GenericParameters test, FunNGenerator.GenericParameters other) {
|
private static boolean isSubtype(FunNGenerator.GenericParameters test, FunNGenerator.GenericParameters other, JavaTXCompiler compiler) {
|
||||||
if (test.getArguments().size() != other.getArguments().size()) return false;
|
if (test.getArguments().size() != other.getArguments().size()) return false;
|
||||||
if (!isSubtype(test.getReturnType(), other.getReturnType())) return false;
|
if (!isSubtype(test.getReturnType(), other.getReturnType(), compiler)) return false;
|
||||||
for (int i = 0; i < test.getArguments().size(); i++) {
|
for (int i = 0; i < test.getArguments().size(); i++) {
|
||||||
var arg1 = test.getArguments().get(i);
|
var arg1 = test.getArguments().get(i);
|
||||||
var arg2 = other.getArguments().get(i);
|
var arg2 = other.getArguments().get(i);
|
||||||
if (!isSupertype(arg1, arg2)) return false;
|
if (!isSupertype(arg1, arg2, compiler)) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1071,7 +1154,7 @@ public class ASTToTargetAST {
|
|||||||
var gep = entry.getValue();
|
var gep = entry.getValue();
|
||||||
var superInterfaces = compiler.usedFunN.values().stream()
|
var superInterfaces = compiler.usedFunN.values().stream()
|
||||||
.filter(g -> !g.equals(gep))
|
.filter(g -> !g.equals(gep))
|
||||||
.filter(genericParameters -> isSubtype(gep, genericParameters))
|
.filter(genericParameters -> isSubtype(gep, genericParameters, compiler))
|
||||||
.map(FunNGenerator::getSpecializedClassName)
|
.map(FunNGenerator::getSpecializedClassName)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
@@ -1129,7 +1212,7 @@ public class ASTToTargetAST {
|
|||||||
} else {
|
} else {
|
||||||
gep = compiler.usedFunN.get(className);
|
gep = compiler.usedFunN.get(className);
|
||||||
}
|
}
|
||||||
return flattenFunNType(params, gep, true);
|
return flattenFunNType(params, gep);
|
||||||
} else if (name.matches("Fun\\d+\\$\\$.*")) {
|
} else if (name.matches("Fun\\d+\\$\\$.*")) {
|
||||||
return new TargetFunNType(name, List.of(), List.of(), 0, false);
|
return new TargetFunNType(name, List.of(), List.of(), 0, false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,12 +142,12 @@ public abstract class GenerateGenerics implements IGenerics {
|
|||||||
this.constraints = constraints;
|
this.constraints = constraints;
|
||||||
for (var constraint : constraints.results) {
|
for (var constraint : constraints.results) {
|
||||||
if (constraint instanceof PairTPHsmallerTPH p) {
|
if (constraint instanceof PairTPHsmallerTPH p) {
|
||||||
Target.logger.info(p.left + " " + p.left.getVariance());
|
Target.logger.debug(p.left + " " + p.left.getVariance());
|
||||||
simplifiedConstraints.add(new PairLT(new TPH(p.left), new TPH(p.right)));
|
simplifiedConstraints.add(new PairLT(new TPH(p.left), new TPH(p.right)));
|
||||||
} else if (constraint instanceof PairTPHEqualTPH p) {
|
} else if (constraint instanceof PairTPHEqualTPH p) {
|
||||||
equality.put(p.getLeft(), p.getRight());
|
equality.put(p.getLeft(), p.getRight());
|
||||||
} else if (constraint instanceof PairTPHequalRefTypeOrWildcardType p) {
|
} else if (constraint instanceof PairTPHequalRefTypeOrWildcardType p) {
|
||||||
Target.logger.info(p.left + " = " + p.right);
|
Target.logger.debug(p.left + " = " + p.right);
|
||||||
concreteTypes.put(new TPH(p.left), p.right);
|
concreteTypes.put(new TPH(p.left), p.right);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -242,7 +242,7 @@ public abstract class GenerateGenerics implements IGenerics {
|
|||||||
equality.put(entry.getKey(), to);
|
equality.put(entry.getKey(), to);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Target.logger.info(from + " -> " + to + " " + from.getVariance());
|
Target.logger.debug(from + " -> " + to + " " + from.getVariance());
|
||||||
//from.setVariance(to.getVariance());
|
//from.setVariance(to.getVariance());
|
||||||
equality.put(from, to);
|
equality.put(from, to);
|
||||||
referenced.remove(new TPH(from));
|
referenced.remove(new TPH(from));
|
||||||
@@ -311,7 +311,7 @@ public abstract class GenerateGenerics implements IGenerics {
|
|||||||
Set<TPH> T2s = new HashSet<>();
|
Set<TPH> T2s = new HashSet<>();
|
||||||
findTphs(superType, T2s);
|
findTphs(superType, T2s);
|
||||||
|
|
||||||
Target.logger.info("T1s: " + T1s + " T2s: " + T2s);
|
Target.logger.debug("T1s: " + T1s + " T2s: " + T2s);
|
||||||
//Ende
|
//Ende
|
||||||
|
|
||||||
superType = methodCall.receiverType;
|
superType = methodCall.receiverType;
|
||||||
@@ -326,7 +326,7 @@ public abstract class GenerateGenerics implements IGenerics {
|
|||||||
var optMethod = ASTToTargetAST.findMethod(owner, methodCall.name, methodCall.signatureArguments().stream().map(x -> getTargetType(x)).toList(), GenerateGenerics.this, compiler);
|
var optMethod = ASTToTargetAST.findMethod(owner, methodCall.name, methodCall.signatureArguments().stream().map(x -> getTargetType(x)).toList(), GenerateGenerics.this, compiler);
|
||||||
if (optMethod.isEmpty()) return;
|
if (optMethod.isEmpty()) return;
|
||||||
var method2 = optMethod.get();
|
var method2 = optMethod.get();
|
||||||
Target.logger.info("In: " + method.getName() + " Method: " + method2.getName());
|
Target.logger.debug("In: " + method.getName() + " Method: " + method2.getName());
|
||||||
var generics = family(owner, method2);
|
var generics = family(owner, method2);
|
||||||
|
|
||||||
// transitive and
|
// transitive and
|
||||||
@@ -359,7 +359,7 @@ public abstract class GenerateGenerics implements IGenerics {
|
|||||||
if (!T1s.contains(R1) || !T2s.contains(R2)) continue;
|
if (!T1s.contains(R1) || !T2s.contains(R2)) continue;
|
||||||
|
|
||||||
var newPair = new PairLT(R1, R2);
|
var newPair = new PairLT(R1, R2);
|
||||||
Target.logger.info("New pair: " + newPair);
|
Target.logger.debug("New pair: " + newPair);
|
||||||
newPairs.add(newPair);
|
newPairs.add(newPair);
|
||||||
|
|
||||||
if (!containsRelation(result, newPair))
|
if (!containsRelation(result, newPair))
|
||||||
@@ -560,7 +560,7 @@ public abstract class GenerateGenerics implements IGenerics {
|
|||||||
public Set<Pair> generics(ClassOrInterface owner, Method method) {
|
public Set<Pair> generics(ClassOrInterface owner, Method method) {
|
||||||
if (computedGenericsOfMethods.containsKey(method)) {
|
if (computedGenericsOfMethods.containsKey(method)) {
|
||||||
var cached = computedGenericsOfMethods.get(method);
|
var cached = computedGenericsOfMethods.get(method);
|
||||||
Target.logger.info("Cached " + method.getName() + ": " + cached);
|
Target.logger.debug("Cached " + method.getName() + ": " + cached);
|
||||||
return cached;
|
return cached;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -589,7 +589,7 @@ public abstract class GenerateGenerics implements IGenerics {
|
|||||||
|
|
||||||
normalize(result, classGenerics, usedTphs);
|
normalize(result, classGenerics, usedTphs);
|
||||||
|
|
||||||
Target.logger.info(this.getClass().getSimpleName() + " " + method.name + ": " + result);
|
Target.logger.debug(this.getClass().getSimpleName() + " " + method.name + ": " + result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -721,7 +721,7 @@ public abstract class GenerateGenerics implements IGenerics {
|
|||||||
if (!added) break;
|
if (!added) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Target.logger.info(chain + " " + chain.stream().map(e -> e.resolve().getVariance()).toList());
|
Target.logger.debug(chain + " " + chain.stream().map(e -> e.resolve().getVariance()).toList());
|
||||||
var variance = chain.get(0).resolve().getVariance();
|
var variance = chain.get(0).resolve().getVariance();
|
||||||
if (variance != 1) continue;
|
if (variance != 1) continue;
|
||||||
var index = 0;
|
var index = 0;
|
||||||
@@ -916,7 +916,7 @@ public abstract class GenerateGenerics implements IGenerics {
|
|||||||
for (var pair : infima) {
|
for (var pair : infima) {
|
||||||
var returnTypes = findTypeVariables(method.getReturnType());
|
var returnTypes = findTypeVariables(method.getReturnType());
|
||||||
var chain = findConnectionToReturnType(returnTypes, input, new HashSet<>(), pair.left);
|
var chain = findConnectionToReturnType(returnTypes, input, new HashSet<>(), pair.left);
|
||||||
Target.logger.info("Find: " + pair.left + " " + chain);
|
Target.logger.debug("Find: " + pair.left + " " + chain);
|
||||||
chain.remove(pair.left);
|
chain.remove(pair.left);
|
||||||
if (chain.size() > 0) {
|
if (chain.size() > 0) {
|
||||||
for (var tph : chain)
|
for (var tph : chain)
|
||||||
@@ -954,8 +954,8 @@ public abstract class GenerateGenerics implements IGenerics {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
newTph.setVariance(variance);
|
newTph.setVariance(variance);
|
||||||
Target.logger.info(infima + " " + infima.stream().map(i -> i.right.resolve().getVariance()).toList());
|
Target.logger.debug(infima + " " + infima.stream().map(i -> i.right.resolve().getVariance()).toList());
|
||||||
Target.logger.info("Infima new TPH " + newTph + " variance " + variance);
|
Target.logger.debug("Infima new TPH " + newTph + " variance " + variance);
|
||||||
|
|
||||||
//referenced.add(newTph);
|
//referenced.add(newTph);
|
||||||
addToPairs(input, new PairLT(left, new TPH(newTph)));
|
addToPairs(input, new PairLT(left, new TPH(newTph)));
|
||||||
|
|||||||
@@ -282,7 +282,7 @@ public class StatementToTargetExpression implements ASTVisitor {
|
|||||||
if (!isStatic && receiverType instanceof TargetRefType) {
|
if (!isStatic && receiverType instanceof TargetRefType) {
|
||||||
for (var g2 : conflicitGenerics) {
|
for (var g2 : conflicitGenerics) {
|
||||||
var otherReceiver = converter.convert(methodCall.receiver.getType(), g2.javaGenerics());
|
var otherReceiver = converter.convert(methodCall.receiver.getType(), g2.javaGenerics());
|
||||||
if (!Objects.equals(receiverType, otherReceiver) && converter.isSubtype(receiverType, otherReceiver)) {
|
if (!Objects.equals(receiverType, otherReceiver) && ASTToTargetAST.isSubtype(receiverType, otherReceiver, converter.compiler)) {
|
||||||
ClassOrInterface clazz = converter.compiler.getClass(new JavaClassName(otherReceiver.name()));
|
ClassOrInterface clazz = converter.compiler.getClass(new JavaClassName(otherReceiver.name()));
|
||||||
if (clazz != null) {
|
if (clazz != null) {
|
||||||
var optMethod = ASTToTargetAST.findMethod(clazz, methodCall.name, argList, converter.compiler);
|
var optMethod = ASTToTargetAST.findMethod(clazz, methodCall.name, argList, converter.compiler);
|
||||||
@@ -300,7 +300,7 @@ public class StatementToTargetExpression implements ASTVisitor {
|
|||||||
for (var tph : Iterables.concat(methodCall.signatureArguments())) {
|
for (var tph : Iterables.concat(methodCall.signatureArguments())) {
|
||||||
var currentType = converter.convert(tph, generics);
|
var currentType = converter.convert(tph, generics);
|
||||||
var type = converter.convert(tph, g2.javaGenerics());
|
var type = converter.convert(tph, g2.javaGenerics());
|
||||||
if (!Objects.equals(type, currentType) && converter.isSubtype(type, currentType)) {
|
if (!Objects.equals(type, currentType) && ASTToTargetAST.isSubtype(type, currentType, converter.compiler)) {
|
||||||
throw new DiscardResultSet();
|
throw new DiscardResultSet();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package de.dhbwstuttgart.target.tree;
|
|||||||
import de.dhbwstuttgart.syntaxtree.Method;
|
import de.dhbwstuttgart.syntaxtree.Method;
|
||||||
import de.dhbwstuttgart.target.generate.IGenerics;
|
import de.dhbwstuttgart.target.generate.IGenerics;
|
||||||
import de.dhbwstuttgart.target.tree.expression.TargetBlock;
|
import de.dhbwstuttgart.target.tree.expression.TargetBlock;
|
||||||
|
import de.dhbwstuttgart.target.tree.expression.TargetComplexPattern;
|
||||||
import de.dhbwstuttgart.target.tree.expression.TargetPattern;
|
import de.dhbwstuttgart.target.tree.expression.TargetPattern;
|
||||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
@@ -16,6 +17,13 @@ public record TargetMethod(int access, String name, TargetBlock block, Signature
|
|||||||
this(access, name, block, signature, txSignature, null, null);
|
this(access, name, block, signature, txSignature, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this was a generated method it has an unwieldy name, this returns the original name
|
||||||
|
// like for instance dup$0$Ljava$lang$Integer$_$ -> dup
|
||||||
|
public String getSimpleName() {
|
||||||
|
if (name.contains("$")) return name.split("\\$")[0];
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
public record Signature(Set<TargetGeneric> generics, List<MethodParameter> parameters, TargetType returnType) {
|
public record Signature(Set<TargetGeneric> generics, List<MethodParameter> parameters, TargetType returnType) {
|
||||||
public String getSignature() {
|
public String getSignature() {
|
||||||
return TargetMethod.getSignature(generics, parameters, returnType);
|
return TargetMethod.getSignature(generics, parameters, returnType);
|
||||||
@@ -30,7 +38,13 @@ public record TargetMethod(int access, String name, TargetBlock block, Signature
|
|||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
Signature signature = (Signature) o;
|
Signature signature = (Signature) o;
|
||||||
return Objects.equals(parameters, signature.parameters);
|
if (this.parameters.size() != signature.parameters.size()) return false;
|
||||||
|
for (var i = 0; i < this.parameters.size(); i++) {
|
||||||
|
var p1 = this.parameters.get(i);
|
||||||
|
var p2 = signature.parameters.get(i);
|
||||||
|
if (!p1.pattern().fuzzyEquals(p2.pattern())) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package de.dhbwstuttgart.target.tree.expression;
|
|||||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public record TargetComplexPattern(TargetType ctor, TargetType type, String name, List<TargetPattern> subPatterns) implements TargetPattern {
|
public record TargetComplexPattern(TargetType ctor, TargetType type, String name, List<TargetPattern> subPatterns) implements TargetPattern {
|
||||||
@Override
|
@Override
|
||||||
@@ -19,4 +20,10 @@ public record TargetComplexPattern(TargetType ctor, TargetType type, String name
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return type + "(" + String.join(", ", subPatterns.stream().map(Object::toString).toList()) + ") " + name;
|
return type + "(" + String.join(", ", subPatterns.stream().map(Object::toString).toList()) + ") " + name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean fuzzyEquals(TargetPattern other) {
|
||||||
|
if (!(other instanceof TargetComplexPattern op)) return false;
|
||||||
|
return Objects.equals(this.type, op.type) && Objects.equals(this.subPatterns, op.subPatterns);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package de.dhbwstuttgart.target.tree.expression;
|
|||||||
|
|
||||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public sealed interface TargetPattern extends TargetExpression permits TargetComplexPattern, TargetExpressionPattern, TargetGuard, TargetTypePattern {
|
public sealed interface TargetPattern extends TargetExpression permits TargetComplexPattern, TargetExpressionPattern, TargetGuard, TargetTypePattern {
|
||||||
default String name() {
|
default String name() {
|
||||||
return null;
|
return null;
|
||||||
@@ -12,4 +14,8 @@ public sealed interface TargetPattern extends TargetExpression permits TargetCom
|
|||||||
TargetType type();
|
TargetType type();
|
||||||
|
|
||||||
TargetPattern withName(String name);
|
TargetPattern withName(String name);
|
||||||
|
|
||||||
|
default boolean fuzzyEquals(TargetPattern other) {
|
||||||
|
return Objects.equals(this.type(), other.type());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ import java.util.Objects;
|
|||||||
|
|
||||||
public record TargetFunNType(String name, List<TargetType> funNParams, List<TargetType> params, int returnArguments, boolean isInterface) implements TargetSpecializedType {
|
public record TargetFunNType(String name, List<TargetType> funNParams, List<TargetType> params, int returnArguments, boolean isInterface) implements TargetSpecializedType {
|
||||||
|
|
||||||
public static TargetFunNType fromParams(List<TargetType> params, int returnArguments, boolean isInterface) {
|
public static TargetFunNType fromParams(List<TargetType> params, int returnArguments) {
|
||||||
return fromParams(params, params, returnArguments, isInterface);
|
return fromParams(params, params, returnArguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TargetFunNType fromParams(List<TargetType> params, List<TargetType> realParams, int returnArguments, boolean isInterface) {
|
public static TargetFunNType fromParams(List<TargetType> params, List<TargetType> realParams, int returnArguments) {
|
||||||
var name = FunNGenerator.getSpecializedClassName(FunNGenerator.getArguments(params), FunNGenerator.getReturnType(params));
|
var name = FunNGenerator.getSpecializedClassName(FunNGenerator.getArguments(params), FunNGenerator.getReturnType(params));
|
||||||
return new TargetFunNType(name, params, realParams, returnArguments, isInterface);
|
return new TargetFunNType(name, params, realParams, returnArguments, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toMethodDescriptor() {
|
public String toMethodDescriptor() {
|
||||||
@@ -43,6 +43,18 @@ public record TargetFunNType(String name, List<TargetType> funNParams, List<Targ
|
|||||||
|
|
||||||
public boolean equals(Object other) {
|
public boolean equals(Object other) {
|
||||||
if (!(other instanceof TargetFunNType otfn)) return false;
|
if (!(other instanceof TargetFunNType otfn)) return false;
|
||||||
|
if (!isInterface && !otfn.isInterface) {
|
||||||
|
if (!Objects.equals(name, otfn.name)) return false;
|
||||||
|
if (funNParams.size() != otfn.funNParams.size()) return false;
|
||||||
|
|
||||||
|
for (var i = 0; i < funNParams.size(); i++) {
|
||||||
|
var p1 = funNParams.get(i);
|
||||||
|
var p2 = otfn.funNParams.get(i);
|
||||||
|
if (p1 instanceof TargetGenericType || p2 instanceof TargetGenericType) continue;
|
||||||
|
if (!Objects.equals(p1, p2)) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return Objects.equals(name, otfn.name);
|
return Objects.equals(name, otfn.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
|
|
||||||
|
import de.dhbwstuttgart.bytecode.CodeGenException;
|
||||||
import de.dhbwstuttgart.core.ConsoleInterface;
|
import de.dhbwstuttgart.core.ConsoleInterface;
|
||||||
|
import de.dhbwstuttgart.exceptions.WarningsException;
|
||||||
import de.dhbwstuttgart.util.Logger;
|
import de.dhbwstuttgart.util.Logger;
|
||||||
import de.dhbwstuttgart.util.Logger.LogLevel;
|
import de.dhbwstuttgart.util.Logger.LogLevel;
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
@@ -24,8 +27,8 @@ import static targetast.TestCodegen.generateClassFiles;
|
|||||||
|
|
||||||
public class TestComplete {
|
public class TestComplete {
|
||||||
|
|
||||||
@BeforeAll
|
@BeforeEach
|
||||||
public static void setup() throws IOException {
|
public void setup() throws IOException {
|
||||||
TestCodegen.outputPath.toFile().mkdirs();
|
TestCodegen.outputPath.toFile().mkdirs();
|
||||||
FileUtils.cleanDirectory(TestCodegen.outputPath.toFile());
|
FileUtils.cleanDirectory(TestCodegen.outputPath.toFile());
|
||||||
}
|
}
|
||||||
@@ -674,6 +677,15 @@ public class TestComplete {
|
|||||||
System.out.println(clazz.getDeclaredMethod("toString").invoke(instance));
|
System.out.println(clazz.getDeclaredMethod("toString").invoke(instance));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void recordTestInstanceVariables() throws Exception {
|
||||||
|
var classFiles = generateClassFiles(createClassLoader(), "RecordTestInstanceVariables.jav");
|
||||||
|
var clazz = classFiles.get("RecordTestInstanceVariables");
|
||||||
|
var instance = clazz.getDeclaredConstructor(Integer.class, Integer.class).newInstance(10, 20);
|
||||||
|
assertEquals(10, clazz.getDeclaredMethod("getA").invoke(instance));
|
||||||
|
assertEquals(20, clazz.getDeclaredMethod("getB").invoke(instance));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void genericRecordTest() throws Exception {
|
public void genericRecordTest() throws Exception {
|
||||||
var classFiles = generateClassFiles(createClassLoader(), "GenericRecord.jav");
|
var classFiles = generateClassFiles(createClassLoader(), "GenericRecord.jav");
|
||||||
@@ -1084,6 +1096,16 @@ public class TestComplete {
|
|||||||
assertEquals(50, m.invoke(null));
|
assertEquals(50, m.invoke(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStaticFail() throws Exception {
|
||||||
|
try {
|
||||||
|
generateClassFiles(createClassLoader(), "StaticFail.jav");
|
||||||
|
fail("No exception thrown!");
|
||||||
|
} catch (CodeGenException e) {
|
||||||
|
assertEquals("Attempted to call instance method nonStaticM with descriptor ()V from a static context", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFor() throws Exception {
|
public void testFor() throws Exception {
|
||||||
var classFiles = generateClassFiles(createClassLoader(), "For.jav");
|
var classFiles = generateClassFiles(createClassLoader(), "For.jav");
|
||||||
@@ -1475,7 +1497,6 @@ public class TestComplete {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Disabled("too slow")
|
|
||||||
public void testBug325() throws Exception {
|
public void testBug325() throws Exception {
|
||||||
var classFiles = generateClassFiles(createClassLoader(), "Bug325.jav");
|
var classFiles = generateClassFiles(createClassLoader(), "Bug325.jav");
|
||||||
var clazz = classFiles.get("Bug325");
|
var clazz = classFiles.get("Bug325");
|
||||||
@@ -1628,7 +1649,7 @@ public class TestComplete {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBug389() throws Exception {
|
public void testBug389() throws Exception {
|
||||||
var classFiles = generateClassFiles(createClassLoader(), true, "Bug389.jav", "Bug389Main.jav");
|
var classFiles = generateClassFiles(createClassLoader(), false, "Bug389.jav", "Bug389Main.jav");
|
||||||
var clazz = classFiles.get("Bug389Main");
|
var clazz = classFiles.get("Bug389Main");
|
||||||
clazz.getDeclaredMethod("main", List.class).invoke(null, List.of());
|
clazz.getDeclaredMethod("main", List.class).invoke(null, List.of());
|
||||||
}
|
}
|
||||||
@@ -1640,4 +1661,15 @@ public class TestComplete {
|
|||||||
clazz.getDeclaredMethod("main", List.class).invoke(null, List.of());
|
clazz.getDeclaredMethod("main", List.class).invoke(null, List.of());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBug395() throws Exception {
|
||||||
|
try {
|
||||||
|
var classFiles = generateClassFiles(createClassLoader(), "Bug395.jav");
|
||||||
|
fail("Shouldn't compile!");
|
||||||
|
} catch (WarningsException e) {
|
||||||
|
assertEquals(1, e.compilerWarnings.size());
|
||||||
|
var warning = e.compilerWarnings.get(0);
|
||||||
|
assertEquals("Duplicate Method definition dup found, signature (Ljava/lang/Integer;)Ljava/lang/Integer; clashes with signature (Ljava/lang/Integer;)Ljava/lang/Integer;", warning.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ public class TestCodegen {
|
|||||||
public void testLambda() throws Exception {
|
public void testLambda() throws Exception {
|
||||||
var classLoader = createClassLoader();
|
var classLoader = createClassLoader();
|
||||||
// var fun = classLoader.loadClass(Path.of(System.getProperty("user.dir"), "src/test/java/targetast/Fun1$$.class"));
|
// var fun = classLoader.loadClass(Path.of(System.getProperty("user.dir"), "src/test/java/targetast/Fun1$$.class"));
|
||||||
var interfaceType = TargetFunNType.fromParams(List.of(TargetType.Integer), 1, false);
|
var interfaceType = TargetFunNType.fromParams(List.of(TargetType.Integer), 1);
|
||||||
|
|
||||||
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, new JavaClassName("CGLambda"));
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, new JavaClassName("CGLambda"));
|
||||||
targetClass.addConstructor(Opcodes.ACC_PUBLIC, List.of(), new TargetBlock(List.of(new TargetMethodCall(null, new TargetSuper(TargetType.Object), List.of(), TargetType.Object, "<init>", false, false, false))));
|
targetClass.addConstructor(Opcodes.ACC_PUBLIC, List.of(), new TargetBlock(List.of(new TargetMethodCall(null, new TargetSuper(TargetType.Object), List.of(), TargetType.Object, "<init>", false, false, false))));
|
||||||
|
|||||||
Reference in New Issue
Block a user