Fix #294
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 2m35s

This commit is contained in:
Daniel Holle 2024-03-20 14:37:15 +01:00
parent 1f74345324
commit 1c63321b30
13 changed files with 101 additions and 14 deletions

View File

@ -7,7 +7,7 @@ import java.util.stream.Stream;
import java.util.function.Function; import java.util.function.Function;
public class Bug298 { public class Bug298 {
public <R, T> Stream<R> takes(Stream<T> s, Function<? super T, ? super R> fun) { public <R, T> Stream<R> takes(Stream<T> s, Function<? super T, ? extends R> fun) {
return null; return null;
} }

View File

@ -0,0 +1,12 @@
import java.lang.Object;
import java.lang.Boolean;
public class OverrideEquals extends OverrideRoot {
public boolean equals(Object o) {
return true;
}
public int method(int var1, float var2) {
return 0;
}
}

Binary file not shown.

View File

@ -0,0 +1,3 @@
public abstract class OverrideRoot {
public abstract int method(int a, float b);
}

View File

@ -962,13 +962,34 @@ public class Codegen {
} }
case TargetReturn ret: { case TargetReturn ret: {
if (ret.expression() != null && state.returnType != null) { if (ret.expression() != null && state.returnType != null) {
var ctype = state.contextType; if (state.returnType instanceof TargetPrimitiveType) {
state.contextType = state.returnType; var ctype = state.contextType;
generate(state, ret.expression()); state.contextType = state.returnType;
state.contextType = ctype; generate(state, ret.expression());
boxPrimitive(state, ret.expression().type()); state.contextType = ctype;
convertTo(state, ret.expression().type(), state.returnType);
mv.visitInsn(ARETURN); unboxPrimitive(state, state.returnType);
if (state.returnType.equals(TargetType.boolean_)
|| state.returnType.equals(TargetType.char_)
|| state.returnType.equals(TargetType.int_)
|| state.returnType.equals(TargetType.short_)
|| state.returnType.equals(TargetType.byte_))
mv.visitInsn(IRETURN);
else if (state.returnType.equals(TargetType.long_))
mv.visitInsn(LRETURN);
else if (state.returnType.equals(TargetType.float_))
mv.visitInsn(FRETURN);
else if (state.returnType.equals(TargetType.double_))
mv.visitInsn(DRETURN);
} else {
var ctype = state.contextType;
state.contextType = state.returnType;
generate(state, ret.expression());
state.contextType = ctype;
boxPrimitive(state, ret.expression().type());
convertTo(state, ret.expression().type(), state.returnType);
mv.visitInsn(ARETURN);
}
} else } else
mv.visitInsn(RETURN); mv.visitInsn(RETURN);
break; break;

View File

@ -68,6 +68,8 @@ public class TypeGenerator {
return new RefType(ASTFactory.createClass(Integer.class).getClassName(), typeContext.getStart()); return new RefType(ASTFactory.createClass(Integer.class).getClassName(), typeContext.getStart());
case "double": case "double":
return new RefType(ASTFactory.createClass(Double.class).getClassName(), typeContext.getStart()); return new RefType(ASTFactory.createClass(Double.class).getClassName(), typeContext.getStart());
case "float":
return new RefType(ASTFactory.createClass(Float.class).getClassName(), typeContext.getStart());
default: default:
throw new NotImplementedException(); throw new NotImplementedException();
} }

View File

@ -368,6 +368,8 @@ public class ASTFactory {
return new RefType(new JavaClassName("java.lang.Character"), new ArrayList<>(), new NullToken(), true); return new RefType(new JavaClassName("java.lang.Character"), new ArrayList<>(), new NullToken(), true);
} else if (type.getTypeName().equals("short")) { } else if (type.getTypeName().equals("short")) {
return new RefType(new JavaClassName("java.lang.Short"), new ArrayList<>(), new NullToken(), true); return new RefType(new JavaClassName("java.lang.Short"), new ArrayList<>(), new NullToken(), true);
} else if (type.getTypeName().equals("float")) {
return new RefType(new JavaClassName("java.lang.Float"), new ArrayList<>(), new NullToken(), true);
} else if (type.getTypeName().equals("double")) { } else if (type.getTypeName().equals("double")) {
return new RefType(new JavaClassName("java.lang.Double"), new ArrayList<>(), new NullToken(), true); return new RefType(new JavaClassName("java.lang.Double"), new ArrayList<>(), new NullToken(), true);
} else if (type.getTypeName().equals("long")) { } else if (type.getTypeName().equals("long")) {

View File

@ -21,6 +21,7 @@ import java.lang.annotation.Target;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import java.util.stream.StreamSupport;
/** /**
* @author dholle * @author dholle
@ -348,6 +349,27 @@ public class ASTToTargetAST {
return swtch; return swtch;
} }
private Optional<Method> findSuperMethodToOverride(String name, List<MethodParameter> params) {
var superClass = compiler.getClass(currentClass.getSuperClass().getName());
var methodStream = superClass.getMethods().stream();
for (var superInterface : currentClass.getSuperInterfaces()) {
methodStream = Stream.concat(methodStream, compiler.getClass(superInterface.getName()).getMethods().stream());
}
return methodStream.filter(m -> {
if (!m.name.equals(name)) return false;
var sParams = m.getParameterList();
if (sParams.getFormalparalist().size() != params.size()) return false;
for (var i = 0; i < params.size(); i++) {
var a = TargetType.toPrimitive(params.get(i).pattern().type());
var b = convert(sParams.getFormalparalist().get(i).getType());
System.out.println(a + " " + b);
if (!Objects.equals(a, b)) return false;
}
return true;
}).findFirst();
}
private List<TargetMethod> convert(Method method) { private List<TargetMethod> convert(Method method) {
generics = all.get(0); generics = all.get(0);
List<TargetMethod> result = new ArrayList<>(); List<TargetMethod> result = new ArrayList<>();
@ -358,13 +380,22 @@ public class ASTToTargetAST {
var javaGenerics = this.generics.javaGenerics.generics(currentClass, method); var javaGenerics = this.generics.javaGenerics.generics(currentClass, method);
var txGenerics = this.generics.txGenerics.generics(currentClass, method); var txGenerics = this.generics.txGenerics.generics(currentClass, method);
List<MethodParameter> params = convert(method.getParameterList(), this.generics.javaGenerics); List<MethodParameter> params = convert(method.getParameterList(), this.generics.javaGenerics);
if (parameterSet.stream().noneMatch(p -> p.equals(params))) { var returnType = convert(method.getReturnType(), this.generics.javaGenerics);
var superMethod = findSuperMethodToOverride(method.getName(), params);
if (superMethod.isPresent()) {
// If we find a super method to override, use its parameters and return types
returnType = convert(superMethod.get().getReturnType(), this.generics.javaGenerics);
params = convert(superMethod.get().getParameterList(), this.generics.javaGenerics);
}
List<MethodParameter> finalParams = params;
if (parameterSet.stream().noneMatch(p -> p.equals(finalParams))) {
List<MethodParameter> txParams = convert(method.getParameterList(), this.generics.txGenerics); List<MethodParameter> txParams = convert(method.getParameterList(), this.generics.txGenerics);
var javaMethodGenerics = collectMethodGenerics(generics.javaGenerics(), javaGenerics, method); var javaMethodGenerics = collectMethodGenerics(generics.javaGenerics(), javaGenerics, method);
var txMethodGenerics = collectMethodGenerics(generics.txGenerics(), txGenerics, method); var txMethodGenerics = collectMethodGenerics(generics.txGenerics(), txGenerics, method);
var javaSignature = new TargetMethod.Signature(javaMethodGenerics, params, convert(method.getReturnType(), this.generics.javaGenerics)); var javaSignature = new TargetMethod.Signature(javaMethodGenerics, params, returnType);
var txSignature = new TargetMethod.Signature(txMethodGenerics, txParams, convert(method.getReturnType(), this.generics.txGenerics)); var txSignature = new TargetMethod.Signature(txMethodGenerics, txParams, convert(method.getReturnType(), this.generics.txGenerics));
result.add(new TargetMethod(method.modifier, method.name, convert(method.block), javaSignature, txSignature)); result.add(new TargetMethod(method.modifier, method.name, convert(method.block), javaSignature, txSignature));
parameterSet.add(params); parameterSet.add(params);

View File

@ -7,4 +7,9 @@ public record TargetGuard(TargetPattern inner, TargetExpression expression) impl
public TargetGuard withType(TargetType type) { public TargetGuard withType(TargetType type) {
return new TargetGuard(inner.withType(type), expression); return new TargetGuard(inner.withType(type), expression);
} }
@Override
public TargetType type() {
return inner.type();
}
} }

View File

@ -8,4 +8,6 @@ public sealed interface TargetPattern extends TargetExpression permits TargetCom
} }
TargetPattern withType(TargetType type); TargetPattern withType(TargetType type);
TargetType type();
} }

View File

@ -12,6 +12,7 @@ import java.util.Stack;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.exceptions.DebugException; import de.dhbwstuttgart.exceptions.DebugException;
import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
@ -892,7 +893,6 @@ public class RuleSet implements IRuleSet{
//FunN$$<...> <. FunctinalInterface<...> wird umgewandelt in FunN$$<...> <. FunN$$<... args aus FuntionalInterface ...> //FunN$$<...> <. FunctinalInterface<...> wird umgewandelt in FunN$$<...> <. FunN$$<... args aus FuntionalInterface ...>
if (rhsType instanceof ReferenceType) { if (rhsType instanceof ReferenceType) {
UnifyType typeFI = pair.getRhsType(); UnifyType typeFI = pair.getRhsType();
Optional<UnifyType> opt = fc.getRightHandedFunctionalInterfaceType(typeFI.getName()); Optional<UnifyType> opt = fc.getRightHandedFunctionalInterfaceType(typeFI.getName());
@ -901,7 +901,7 @@ public class RuleSet implements IRuleSet{
// The generic Version of typeFI (FI<a1, a2, a3, ... >) // The generic Version of typeFI (FI<a1, a2, a3, ... >)
UnifyType typeDgen = opt.get(); UnifyType typeDgen = opt.get();
// Actually greater+ because the types are ensured to have different names // Actually greater+ because the types are ensured to have different names
Set<UnifyType> smaller = fc.getChildren(typeDgen); Set<UnifyType> smaller = fc.getChildren(typeDgen);
opt = smaller.stream().filter(x -> x.getName().equals(pair.getLhsType().getName())).findAny(); opt = smaller.stream().filter(x -> x.getName().equals(pair.getLhsType().getName())).findAny();
@ -915,7 +915,7 @@ public class RuleSet implements IRuleSet{
Unifier unif = Unifier.identity(); Unifier unif = Unifier.identity();
for(int i = 0; i < typeDParams.size(); i++) { for(int i = 0; i < typeDParams.size(); i++) {
if (typeDgenParams.get(i) instanceof PlaceholderType) if (typeDgenParams.get(i) instanceof PlaceholderType)
unif.add((PlaceholderType) typeDgenParams.get(i), typeDParams.get(i)); unif.add((PlaceholderType) typeDgenParams.get(i), typeDParams.get(i));
else System.out.println("ERROR"); else System.out.println("ERROR");
} }

View File

@ -891,6 +891,14 @@ public class TestComplete {
var instance = clazz.getDeclaredConstructor().newInstance(); var instance = clazz.getDeclaredConstructor().newInstance();
} }
@Test
public void testOverrideEquals() throws Exception {
var loader = new ByteArrayClassLoader();
loader.loadClass(TestCodegen.path.resolve("OverrideRoot.class"));
var classFiles = generateClassFiles(loader, "OverrideEquals.jav");
var clazz = classFiles.get("OverrideEquals");
var instance = clazz.getDeclaredConstructor().newInstance();
}
@Test @Test
public void testBug122() throws Exception { public void testBug122() throws Exception {

View File

@ -38,8 +38,9 @@ public class TestCodegen {
Files.write(outputPath.resolve(name + ".class"), code); Files.write(outputPath.resolve(name + ".class"), code);
} }
public static Path path = Path.of(System.getProperty("user.dir"), "resources/bytecode/javFiles/");
public static Map<String, ? extends Class<?>> generateClassFiles(IByteArrayClassLoader classLoader, String... files) throws IOException, ClassNotFoundException { public static Map<String, ? extends Class<?>> generateClassFiles(IByteArrayClassLoader classLoader, String... files) throws IOException, ClassNotFoundException {
var path = Path.of(System.getProperty("user.dir"), "resources/bytecode/javFiles/");
Files.createDirectories(outputPath); Files.createDirectories(outputPath);
var filenames = Arrays.stream(files).map(filename -> Path.of(path.toString(), filename).toFile()).toList(); var filenames = Arrays.stream(files).map(filename -> Path.of(path.toString(), filename).toFile()).toList();
var compiler = new JavaTXCompiler(filenames, List.of(path.toFile(), outputPath.toFile())); var compiler = new JavaTXCompiler(filenames, List.of(path.toFile(), outputPath.toFile()));