Generate proper FunN types
This commit is contained in:
parent
be1c356a9f
commit
aa156b793f
@ -237,7 +237,7 @@ public class Codegen {
|
|||||||
mv.visitInsn(I2F);
|
mv.visitInsn(I2F);
|
||||||
else if (dest.equals(TargetType.Double))
|
else if (dest.equals(TargetType.Double))
|
||||||
mv.visitInsn(I2D);
|
mv.visitInsn(I2D);
|
||||||
} else {
|
} else if (!(dest instanceof TargetGenericType)) {
|
||||||
boxPrimitive(state, source);
|
boxPrimitive(state, source);
|
||||||
mv.visitTypeInsn(CHECKCAST, dest.getInternalName());
|
mv.visitTypeInsn(CHECKCAST, dest.getInternalName());
|
||||||
unboxPrimitive(state, dest);
|
unboxPrimitive(state, dest);
|
||||||
|
@ -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) {
|
protected TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input) {
|
||||||
return input.acceptTV(new TypeVisitor<>() {
|
return input.acceptTV(new TypeVisitor<>() {
|
||||||
@ -669,10 +670,16 @@ public class ASTToTargetAST {
|
|||||||
if (name.equals("void")) return null;
|
if (name.equals("void")) return null;
|
||||||
|
|
||||||
var params = refType.getParaList().stream().map(ASTToTargetAST.this::convert).toList();
|
var params = refType.getParaList().stream().map(ASTToTargetAST.this::convert).toList();
|
||||||
if (name.matches("Fun\\d\\$\\$")) { // TODO This seems like a bad idea
|
if (name.matches("Fun\\d+\\$\\$")) { // TODO This seems like a bad idea
|
||||||
if (!usedFunN.contains(params.size() - 1)) {
|
var gen = FunNGenerator.getInstance();
|
||||||
usedFunN.add(params.size() - 1);
|
var className = gen.getSpecializedClassName(gen.getArguments(refType.getParaList()), gen.getReturnType(refType.getParaList()));
|
||||||
classLoader.loadClass(FunNGenerator.getInstance().generateSuperBytecode(params.size() - 1));
|
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);
|
return new TargetFunNType(params.size() - 1, params);
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,26 @@
|
|||||||
package de.dhbwstuttgart.target.tree.type;
|
package de.dhbwstuttgart.target.tree.type;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public record TargetFunNType(int N, List<TargetType> params) implements TargetSpecializedType {
|
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
|
@Override
|
||||||
public String getInternalName() {
|
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
|
@Override
|
||||||
|
@ -5,6 +5,7 @@ import org.junit.BeforeClass;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
@ -16,6 +17,9 @@ public class InheritTest {
|
|||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void setUpBeforeClass() throws Exception {
|
public static void setUpBeforeClass() throws Exception {
|
||||||
var classLoader = new ByteArrayClassLoader();
|
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");
|
classToTest = TestCodegen.generateClassFiles("Inherit.jav", classLoader).get("Inherit");
|
||||||
classToTestAA = TestCodegen.generateClassFiles("AA.jav", classLoader).get("AA");
|
classToTestAA = TestCodegen.generateClassFiles("AA.jav", classLoader).get("AA");
|
||||||
classToTestBB = TestCodegen.generateClassFiles("BB.jav", classLoader).get("BB");
|
classToTestBB = TestCodegen.generateClassFiles("BB.jav", classLoader).get("BB");
|
||||||
|
@ -10,6 +10,7 @@ import de.dhbwstuttgart.target.tree.expression.*;
|
|||||||
import de.dhbwstuttgart.target.tree.type.TargetFunNType;
|
import de.dhbwstuttgart.target.tree.type.TargetFunNType;
|
||||||
import de.dhbwstuttgart.target.tree.type.TargetRefType;
|
import de.dhbwstuttgart.target.tree.type.TargetRefType;
|
||||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
@ -318,10 +319,11 @@ public class TestCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Ignore("The lambda class is not generated because we don'T call ASTToTargetAST")
|
||||||
public void testLambda() throws Exception {
|
public void testLambda() throws Exception {
|
||||||
var classLoader = new ByteArrayClassLoader();
|
var classLoader = new ByteArrayClassLoader();
|
||||||
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 = new TargetFunNType(1, List.of());
|
var interfaceType = new TargetFunNType(1, List.of(TargetType.Integer));
|
||||||
|
|
||||||
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "CGLambda");
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "CGLambda");
|
||||||
targetClass.addConstructor(Opcodes.ACC_PUBLIC, List.of(), new TargetBlock(List.of(
|
targetClass.addConstructor(Opcodes.ACC_PUBLIC, List.of(), new TargetBlock(List.of(
|
||||||
|
Loading…
Reference in New Issue
Block a user