Generate proper FunN types

This commit is contained in:
Vic Nightfall 2022-11-13 17:05:14 +01:00
parent be1c356a9f
commit aa156b793f
5 changed files with 37 additions and 9 deletions

View File

@ -237,7 +237,7 @@ public class Codegen {
mv.visitInsn(I2F);
else if (dest.equals(TargetType.Double))
mv.visitInsn(I2D);
} else {
} else if (!(dest instanceof TargetGenericType)) {
boxPrimitive(state, source);
mv.visitTypeInsn(CHECKCAST, dest.getInternalName());
unboxPrimitive(state, dest);

View File

@ -659,7 +659,8 @@ public class ASTToTargetAST {
);
}
private final Set<Integer> usedFunN = new HashSet<>();
private final Set<String> usedFunN = new HashSet<>();
private final Set<Integer> usedFunNSuperTypes = new HashSet<>();
protected TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input) {
return input.acceptTV(new TypeVisitor<>() {
@ -669,10 +670,16 @@ public class ASTToTargetAST {
if (name.equals("void")) return null;
var params = refType.getParaList().stream().map(ASTToTargetAST.this::convert).toList();
if (name.matches("Fun\\d\\$\\$")) { // TODO This seems like a bad idea
if (!usedFunN.contains(params.size() - 1)) {
usedFunN.add(params.size() - 1);
classLoader.loadClass(FunNGenerator.getInstance().generateSuperBytecode(params.size() - 1));
if (name.matches("Fun\\d+\\$\\$")) { // TODO This seems like a bad idea
var gen = FunNGenerator.getInstance();
var className = gen.getSpecializedClassName(gen.getArguments(refType.getParaList()), gen.getReturnType(refType.getParaList()));
if (!usedFunNSuperTypes.contains(params.size())) {
classLoader.loadClass(gen.generateSuperBytecode(params.size() - 1));
usedFunNSuperTypes.add(params.size());
}
if (!usedFunN.contains(className)) {
usedFunN.add(className);
classLoader.loadClass(gen.generateSpecializedBytecode(gen.getArguments(refType.getParaList()), gen.getReturnType(refType.getParaList())));
}
return new TargetFunNType(params.size() - 1, params);
}

View File

@ -1,11 +1,26 @@
package de.dhbwstuttgart.target.tree.type;
import java.util.List;
import java.util.stream.Collectors;
public record TargetFunNType(int N, List<TargetType> params) implements TargetSpecializedType {
private static String nameDescriptor(TargetType type) {
if (type instanceof TargetGenericType) return "LTPH;";
return type.toSignature();
}
@Override
public String getInternalName() {
return "Fun" + N + "$$";
// TODO This is duplicate code from FunNGenerator, I think we should change it to accept TargetTypes and refactor.
var returnType = params.get(params.size() - 1);
var argumentTypes = params.subList(0, params.size() - 1);
return java.lang.String.format("Fun%d$$%s%s",
argumentTypes.size(),
argumentTypes.stream().map(TargetFunNType::nameDescriptor).collect(Collectors.joining()),
nameDescriptor(returnType))
.replace('/', '$')
.replace(";", "$_$");
}
@Override

View File

@ -5,6 +5,7 @@ import org.junit.BeforeClass;
import org.junit.Test;
import java.lang.reflect.Method;
import java.nio.file.Path;
import java.util.Vector;
import static org.junit.Assert.assertEquals;
@ -16,6 +17,9 @@ public class InheritTest {
@BeforeClass
public static void setUpBeforeClass() throws Exception {
var classLoader = new ByteArrayClassLoader();
// TODO Box is loaded and has a method called m so it is generating overloads for it
classLoader.loadClass(Path.of(System.getProperty("user.dir"), "/src/test/resources/target/Box.class"));
classToTest = TestCodegen.generateClassFiles("Inherit.jav", classLoader).get("Inherit");
classToTestAA = TestCodegen.generateClassFiles("AA.jav", classLoader).get("AA");
classToTestBB = TestCodegen.generateClassFiles("BB.jav", classLoader).get("BB");

View File

@ -10,6 +10,7 @@ import de.dhbwstuttgart.target.tree.expression.*;
import de.dhbwstuttgart.target.tree.type.TargetFunNType;
import de.dhbwstuttgart.target.tree.type.TargetRefType;
import de.dhbwstuttgart.target.tree.type.TargetType;
import org.junit.Ignore;
import org.junit.Test;
import static org.junit.Assert.*;
import org.objectweb.asm.Opcodes;
@ -318,10 +319,11 @@ public class TestCodegen {
}
@Test
@Ignore("The lambda class is not generated because we don'T call ASTToTargetAST")
public void testLambda() throws Exception {
var classLoader = new ByteArrayClassLoader();
var fun = classLoader.loadClass(Path.of(System.getProperty("user.dir"), "src/test/java/targetast/Fun1$$.class"));
var interfaceType = new TargetFunNType(1, List.of());
//var fun = classLoader.loadClass(Path.of(System.getProperty("user.dir"), "src/test/java/targetast/Fun1$$.class"));
var interfaceType = new TargetFunNType(1, List.of(TargetType.Integer));
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "CGLambda");
targetClass.addConstructor(Opcodes.ACC_PUBLIC, List.of(), new TargetBlock(List.of(