From f00ee2598f6fbd81efc52522dbbaaf1e0275179e Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Wed, 22 Jun 2022 17:06:49 +0200 Subject: [PATCH] Start implementing family of generics --- .../target/bytecode/Codegen.java | 3 +- .../target/generate/ASTToTargetAST.java | 266 +++++++++++++++--- .../generate/AbstractStatementVisitor.java | 152 ++++++++++ .../target/tree/TargetClass.java | 23 +- .../target/tree/TargetConstructor.java | 4 +- .../target/tree/TargetField.java | 2 +- .../target/tree/TargetGeneric.java | 6 + .../target/tree/TargetMethod.java | 5 +- .../target/tree/type/TargetFunNType.java | 2 +- .../target/tree/type/TargetGenericType.java | 2 +- .../target/tree/type/TargetRefType.java | 2 +- .../tree/type/TargetSpecializedType.java | 7 + .../target/tree/type/TargetType.java | 2 +- .../java/targetast/ASTToTypedTargetAST.java | 15 +- .../bytecode/javFiles/TPHsAndGenerics.jav | 16 ++ 15 files changed, 452 insertions(+), 55 deletions(-) create mode 100644 src/main/java/de/dhbwstuttgart/target/generate/AbstractStatementVisitor.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/TargetGeneric.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/type/TargetSpecializedType.java create mode 100644 src/test/resources/bytecode/javFiles/TPHsAndGenerics.jav diff --git a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java index 39974c92..822ab670 100755 --- a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java @@ -15,6 +15,7 @@ import java.lang.invoke.MethodType; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import static org.objectweb.asm.Opcodes.*; import static de.dhbwstuttgart.target.tree.expression.TargetBinaryOp.*; @@ -527,7 +528,7 @@ public class Codegen { var mv = state.mv; var name = "lambda$" + state.lambdaCounter; var impl = new TargetMethod( - ACC_PRIVATE, new TargetRefType(clazz.qualifiedName()), name, + ACC_PRIVATE, name, Set.of(), lambda.params(), lambda.returnType(), lambda.block() ); generateMethod(impl); diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index 09897269..92ff74d8 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -1,9 +1,8 @@ package de.dhbwstuttgart.target.generate; -import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; import de.dhbwstuttgart.syntaxtree.*; -import de.dhbwstuttgart.syntaxtree.statement.Block; -import de.dhbwstuttgart.syntaxtree.statement.Expression; +import de.dhbwstuttgart.syntaxtree.statement.*; import de.dhbwstuttgart.syntaxtree.type.*; import de.dhbwstuttgart.target.tree.*; import de.dhbwstuttgart.target.tree.expression.TargetBlock; @@ -11,53 +10,247 @@ import de.dhbwstuttgart.target.tree.expression.TargetExpression; import de.dhbwstuttgart.target.tree.type.*; import de.dhbwstuttgart.typeinference.result.*; -import java.lang.annotation.Target; import java.util.*; -import java.util.stream.Collectors; +import java.util.stream.Stream; public class ASTToTargetAST { - protected List> all; - protected HashMap sigma; + protected List all; + protected Sigma sigma; - private class ResultPairV implements ResultPairVisitor { - @Override - public void visit(PairTPHsmallerTPH p) { - throw new NotImplementedException(); + private class Sigma { + HashMap> computedGenerics = new HashMap<>(); + + Set simplifiedConstraints = new HashSet<>(); + Map result = new HashMap<>(); + Map equality = new HashMap<>(); + + Sigma(ResultSet constraints) { + ASTToTargetAST.this.sigma = this; + + Set> equalitySet = new HashSet<>(); + Map> unified = new HashMap<>(); + + for (var constraint : constraints.results) { + if (constraint instanceof PairTPHEqualTPH p) { + if (unified.containsKey(p.getLeft())) { + var equals = unified.get(p.getLeft()); + equals.add(p.getRight()); + unified.put(p.getLeft(), equals); + } else if (unified.containsKey(p.getRight())) { + var equals = unified.get(p.getRight()); + equals.add(p.getLeft()); + unified.put(p.getRight(), equals); + } else { + List equals = new ArrayList<>(); + equals.add(p.getLeft()); + equals.add(p.getRight()); + unified.put(p.getLeft(), equals); + unified.put(p.getRight(), equals); + equalitySet.add(equals); + } + } + } + + for (var constraint : constraints.results) { + if (constraint instanceof PairTPHsmallerTPH p) { + var left = p.left; + var right = p.right; + if (unified.containsKey(left)) + left = unified.get(left).get(0); + if (unified.containsKey(right)) + right = unified.get(right).get(0); + + simplifiedConstraints.add(new PairTPHsmallerTPH(left, right)); + result.put(right, new TargetGenericType(right.getName())); + result.put(left, new TargetGenericType(left.getName())); + } + } + System.out.println(simplifiedConstraints); + + for (var equality : equalitySet) { + var first = equality.get(0); + for (var i = 1; i < equality.size(); i++) + this.equality.put(equality.get(i), first); + } + + for (var constraint : constraints.results) { + if (constraint instanceof PairTPHequalRefTypeOrWildcardType p) { + result.put(p.left, convert(p.right)); + } + } } - @Override - public void visit(PairTPHequalRefTypeOrWildcardType p) { - sigma.put(p.left, convert(p.right)); + // Family of generated Generics + Set generics(ClassOrInterface owner, Method method) { + if (computedGenerics.containsKey(method)) + return computedGenerics.get(method); + + Set result = new HashSet<>(); + computedGenerics.put(method, result); + + method.block.accept(new AbstractStatementVisitor() { + // These two methods do the actual work + @Override + public void visit(LocalVarDecl localVarDecl) { + // TODO + } + + @Override + public void visit(MethodCall methodCall) { + if (methodCall.receiver instanceof ExpressionReceiver expressionReceiver) { + if (expressionReceiver.expr instanceof This) { + // TODO This is going to fail spectacularly for overloaded methods + var optMethod = owner.getMethods().stream().filter(m -> m.name.equals(methodCall.name)).findFirst(); + assert optMethod.isPresent(); + var method = optMethod.get(); + Set generics = generics(owner, method); + + } + } + } + + // Everything down here is just for walking the AST + @Override + public void visit(ArgumentList argumentList) { + argumentList.getArguments().forEach(expr -> expr.accept(this)); + } + + @Override + public void visit(LambdaExpression lambdaExpression) { + lambdaExpression.methodBody.accept(this); + } + + @Override + public void visit(Assign assign) { + assign.rightSide.accept(this); + } + + @Override + public void visit(BinaryExpr binary) { + binary.lexpr.accept(this); + binary.rexpr.accept(this); + } + + @Override + public void visit(Block block) { + for (var expr : block.statements) + expr.accept(this); + } + + @Override + public void visit(ForStmt forStmt) { + forStmt.body_Loop_block.accept(this); + } + + @Override + public void visit(IfStmt ifStmt) { + ifStmt.then_block.accept(this); + ifStmt.else_block.accept(this); + } + + @Override + public void visit(NewClass newClass) { + newClass.arglist.accept(this); + } + + @Override + public void visit(NewArray newArray) { + newArray.expr.forEach(expr -> expr.accept(this)); + } + + @Override + public void visit(Return aReturn) { + aReturn.retexpr.accept(this); + } + + @Override + public void visit(WhileStmt whileStmt) { + whileStmt.loopBlock.accept(this); + } + + @Override + public void visit(DoStmt whileStmt) { + whileStmt.loopBlock.accept(this); + } + + @Override + public void visit(UnaryExpr unaryExpr) { + unaryExpr.expr.accept(this); + } + }); + + return result; } - @Override - public void visit(PairTPHEqualTPH p) { - throw new NotImplementedException(); + void findAllBounds(String name, Set generics) { + for (var rsp : simplifiedConstraints) { + var left = equality.getOrDefault(rsp.left, rsp.left); + var right = equality.getOrDefault(rsp.right, rsp.right); + if (left.getName().equals(name)) { + generics.add(new TargetGeneric(name, new TargetGenericType(right.getName()))); + findAllBounds(right.getName(), generics); + return; + } + } + generics.add(new TargetGeneric(name, TargetType.Object)); + } + + Set findAllBounds(TargetGenericType type) { + Set result = new HashSet<>(); + findAllBounds(type.name(), result); + return result; + } + + Set generics(ClassOrInterface classOrInterface) { + Set result = new HashSet<>(); + for (var field : classOrInterface.getFieldDecl()) { + if (field.getType() instanceof TypePlaceholder tph) { + var tpe = get(tph); + switch (tpe) { + case TargetSpecializedType specializedType: + specializedType.params().stream().flatMap(targetType -> { + if (targetType instanceof TargetSpecializedType spc) + return Stream.concat(Stream.of(targetType), spc.params().stream()); + return Stream.of(targetType); + }).forEach(param -> { + if (param instanceof TargetGenericType genericType) { + result.addAll(findAllBounds(genericType)); + } + }); + break; + case TargetGenericType genericType: + result.addAll(findAllBounds(genericType)); + default: break; + } + } + } + return result; + } + + TargetType get(TypePlaceholder tph) { + if (equality.containsKey(tph)) { + return get(equality.get(tph)); + } + return result.get(tph); } } public ASTToTargetAST(List resultSets) { all = new ArrayList<>(); - for (var set : resultSets) { - this.sigma = new HashMap<>(); - for (var pair : set.results) { - var visitor = new ResultPairV(); - pair.accept(visitor); - } - all.add(this.sigma); + all.add(new Sigma(set)); } - this.sigma = all.get(0); } public TargetClass convert(ClassOrInterface input) { return new TargetClass(input.getModifiers(),input.getClassName().toString(), convert(input.getSuperClass()), - input.getSuperInterfaces().stream().map(it -> sigma.get(it)).toList(), - input.getConstructors().stream().map(it -> convert(input, it)).flatMap(List::stream).toList(), - input.getFieldDecl().stream().map(it -> convert(input, it)).toList(), - input.getMethods().stream().map(it -> convert(input, it)).flatMap(List::stream).toList() + sigma.generics(input), + input.getSuperInterfaces().stream().map(this::convert).toList(), + input.getConstructors().stream().map(constructor -> this.convert(input, constructor)).flatMap(List::stream).toList(), + input.getFieldDecl().stream().map(this::convert).toList(), + input.getMethods().stream().map(method -> this.convert(input, method)).flatMap(List::stream).toList() ); } @@ -75,7 +268,7 @@ public class ASTToTargetAST { sigma = s; List params = convert(input.getParameterList()); if (parameterSet.stream().noneMatch(p -> p.equals(params))) { - result.add(new TargetConstructor(input.modifier, new TargetRefType(owner.getClassName().getClassName()), params, convert(input.block))); + result.add(new TargetConstructor(input.modifier, sigma.generics(owner, input), params, convert(input.block))); parameterSet.add(params); } } @@ -94,8 +287,7 @@ public class ASTToTargetAST { if (parameterSet.stream().noneMatch(p -> p.equals(params))) { result.add(new TargetMethod( input.modifier, - new TargetRefType(owner.getClassName().getClassName()), - input.name, params, + input.name, sigma.generics(owner, input), params, convert(input.getReturnType()), convert(input.block) )); @@ -116,10 +308,9 @@ public class ASTToTargetAST { return converter.result; } - private TargetField convert(ClassOrInterface owner, Field input) { + private TargetField convert(Field input) { return new TargetField( input.modifier, - new TargetRefType(owner.getClassName().getClassName()), convert(input.getType()), input.getName() ); @@ -131,8 +322,11 @@ public class ASTToTargetAST { public TargetType visit(RefType refType) { var name = refType.getName().toString(); if (name.equals("void")) return null; - return new TargetRefType(name, - 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 + return new TargetFunNType(params.size(), params); + return new TargetRefType(name, params); } @Override diff --git a/src/main/java/de/dhbwstuttgart/target/generate/AbstractStatementVisitor.java b/src/main/java/de/dhbwstuttgart/target/generate/AbstractStatementVisitor.java new file mode 100644 index 00000000..b9e2243d --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/generate/AbstractStatementVisitor.java @@ -0,0 +1,152 @@ +package de.dhbwstuttgart.target.generate; + +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.statement.*; + +public abstract class AbstractStatementVisitor implements StatementVisitor { + @Override + public void visit(ArgumentList argumentList) { + + } + + @Override + public void visit(LambdaExpression lambdaExpression) { + + } + + @Override + public void visit(Assign assign) { + + } + + @Override + public void visit(BinaryExpr binary) { + + } + + @Override + public void visit(Block block) { + + } + + @Override + public void visit(CastExpr castExpr) { + + } + + @Override + public void visit(EmptyStmt emptyStmt) { + + } + + @Override + public void visit(FieldVar fieldVar) { + + } + + @Override + public void visit(ForStmt forStmt) { + + } + + @Override + public void visit(IfStmt ifStmt) { + + } + + @Override + public void visit(InstanceOf instanceOf) { + + } + + @Override + public void visit(LocalVar localVar) { + + } + + @Override + public void visit(LocalVarDecl localVarDecl) { + + } + + @Override + public void visit(MethodCall methodCall) { + + } + + @Override + public void visit(NewClass methodCall) { + + } + + @Override + public void visit(NewArray newArray) { + + } + + @Override + public void visit(Return aReturn) { + + } + + @Override + public void visit(ReturnVoid aReturn) { + + } + + @Override + public void visit(StaticClassName staticClassName) { + + } + + @Override + public void visit(Super aSuper) { + + } + + @Override + public void visit(This aThis) { + + } + + @Override + public void visit(WhileStmt whileStmt) { + + } + + @Override + public void visit(DoStmt whileStmt) { + + } + + @Override + public void visit(AssignToField assignLeftSide) { + + } + + @Override + public void visit(AssignToLocal assignLeftSide) { + + } + + @Override + public void visit(SuperCall superCall) { + + } + + @Override + public void visit(ExpressionReceiver expressionReceiver) { + + } + + @Override + public void visit(UnaryExpr unaryExpr) { + + } + + @Override + public void visit(Literal literal) { + + } +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java index e7f990c0..407b71b2 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java @@ -6,31 +6,42 @@ import de.dhbwstuttgart.target.tree.type.TargetType; import java.lang.annotation.Target; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; -public record TargetClass(int modifiers, String qualifiedName, TargetType superType, List implementingInterfaces, +public record TargetClass(int modifiers, String qualifiedName, TargetType superType, Set generics, List implementingInterfaces, List constructors, List fields, List methods) { + public TargetClass(int modifiers, String qualifiedName) { - this(modifiers, qualifiedName, TargetType.Object, new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); + this(modifiers, qualifiedName, TargetType.Object, new HashSet<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); } public TargetClass(int modifiers, String qualifiedName, List implementingInterfaces) { - this(modifiers, qualifiedName, TargetType.Object, implementingInterfaces, new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); + this(modifiers, qualifiedName, TargetType.Object, new HashSet<>(), implementingInterfaces, new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); } public String getName() { return qualifiedName.replaceAll("\\.", "/"); } + public void addMethod(int access, String name, Set generics, List parameterTypes, TargetType returnType, TargetBlock block) { + this.methods.add(new TargetMethod(access, name, generics, parameterTypes, returnType, block)); + } + public void addMethod(int access, String name, List parameterTypes, TargetType returnType, TargetBlock block) { - this.methods.add(new TargetMethod(access, new TargetRefType(this.qualifiedName, List.of()), name, parameterTypes, returnType, block)); + addMethod(access, name, Set.of(), parameterTypes, returnType, block); + } + + public void addConstructor(int access, Set generics, List paramterTypes, TargetBlock block) { + this.constructors.add(new TargetConstructor(access, generics, paramterTypes, block)); } public void addConstructor(int access, List paramterTypes, TargetBlock block) { - this.constructors.add(new TargetConstructor(access, new TargetRefType(this.qualifiedName, List.of()), paramterTypes, block)); + addConstructor(access, Set.of(), paramterTypes, block); } public void addField(int access, TargetRefType type, String name) { - this.fields.add(new TargetField(access, new TargetRefType(this.qualifiedName, List.of()), type, name)); + this.fields.add(new TargetField(access, type, name)); } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java index 3c353262..a0e5a365 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java @@ -1,12 +1,12 @@ package de.dhbwstuttgart.target.tree; import de.dhbwstuttgart.target.tree.expression.TargetBlock; -import de.dhbwstuttgart.target.tree.type.TargetRefType; import de.dhbwstuttgart.target.tree.type.TargetType; import java.util.List; +import java.util.Set; -public record TargetConstructor(int access, TargetType owner, List parameters, TargetBlock block) { +public record TargetConstructor(int access, Set generics, List parameters, TargetBlock block) { public String getDescriptor() { return TargetMethod.getDescriptor(null, parameters.stream().map(MethodParameter::type).toArray(TargetType[]::new)); diff --git a/src/main/java/de/dhbwstuttgart/target/tree/TargetField.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetField.java index 489192a2..a842ad66 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/TargetField.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetField.java @@ -3,7 +3,7 @@ package de.dhbwstuttgart.target.tree; import de.dhbwstuttgart.target.tree.type.TargetType; import org.objectweb.asm.Opcodes; -public record TargetField(int access, TargetType owner, TargetType type, String name) { +public record TargetField(int access, TargetType type, String name) { public String getDescriptor() { return type.toSignature(); } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/TargetGeneric.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetGeneric.java new file mode 100644 index 00000000..ad70ae71 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetGeneric.java @@ -0,0 +1,6 @@ +package de.dhbwstuttgart.target.tree; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetGeneric(String name, TargetType bound) { +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java index 52ea71a0..a1bd592f 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java @@ -1,14 +1,13 @@ package de.dhbwstuttgart.target.tree; import de.dhbwstuttgart.target.tree.expression.TargetBlock; -import de.dhbwstuttgart.target.tree.type.TargetRefType; import de.dhbwstuttgart.target.tree.type.TargetType; import org.objectweb.asm.Opcodes; import java.util.List; -import java.util.stream.Collectors; +import java.util.Set; -public record TargetMethod(int access, TargetType owner, String name, List parameters, TargetType returnType, TargetBlock block) { +public record TargetMethod(int access, String name, Set generics, List parameters, TargetType returnType, TargetBlock block) { public static String getDescriptor(TargetType returnType, TargetType... parameters) { String ret = "("; for (var parameterType : parameters) { diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetFunNType.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetFunNType.java index cfdf2b3c..531aae1c 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetFunNType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetFunNType.java @@ -2,7 +2,7 @@ package de.dhbwstuttgart.target.tree.type; import java.util.List; -public record TargetFunNType(int N, List params) implements TargetType { +public record TargetFunNType(int N, List params) implements TargetSpecializedType { @Override public String getName() { return "Fun" + N + "$$"; diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetGenericType.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetGenericType.java index ab2e3c2b..149ed52c 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetGenericType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetGenericType.java @@ -7,7 +7,7 @@ public record TargetGenericType(String name) implements TargetType { } @Override - public java.lang.String getName() { + public String getName() { return null; } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetRefType.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetRefType.java index 5944fdbe..98878f93 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetRefType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetRefType.java @@ -4,7 +4,7 @@ import de.dhbwstuttgart.target.tree.type.TargetType; import java.util.List; -public record TargetRefType(String name, List params) implements TargetType { +public record TargetRefType(String name, List params) implements TargetSpecializedType { public TargetRefType(String name) { this(name, List.of()); } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSpecializedType.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSpecializedType.java new file mode 100644 index 00000000..0dce9825 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSpecializedType.java @@ -0,0 +1,7 @@ +package de.dhbwstuttgart.target.tree.type; + +import java.util.List; + +public sealed interface TargetSpecializedType extends TargetType permits TargetFunNType, TargetRefType { + List params(); +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetType.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetType.java index 5d12cd34..263c760c 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetType.java @@ -3,7 +3,7 @@ package de.dhbwstuttgart.target.tree.type; import java.util.List; public sealed interface TargetType - permits TargetExtendsWildcard, TargetFunNType, TargetGenericType, TargetRefType, TargetSuperWildcard { + permits TargetExtendsWildcard, TargetGenericType, TargetSpecializedType, TargetSuperWildcard { // Builtin types TargetRefType Boolean = new TargetRefType("java.lang.Boolean"); diff --git a/src/test/java/targetast/ASTToTypedTargetAST.java b/src/test/java/targetast/ASTToTypedTargetAST.java index 687a1ff8..17196470 100644 --- a/src/test/java/targetast/ASTToTypedTargetAST.java +++ b/src/test/java/targetast/ASTToTypedTargetAST.java @@ -38,8 +38,8 @@ public class ASTToTypedTargetAST { var converter = new ASTToTargetAST(resultSet); var classes = compiler.sourceFiles.get(file).getClasses(); - Class overloading = TestCodegen.generateClass(converter.convert(classes.get(0))); - Class overloading2 = TestCodegen.generateClass(converter.convert(classes.get(1))); + var overloading = TestCodegen.generateClass(converter.convert(classes.get(0))); + var overloading2 = TestCodegen.generateClass(converter.convert(classes.get(1))); var test1 = overloading.getDeclaredMethod("test", overloading); test1.setAccessible(true); @@ -50,4 +50,15 @@ public class ASTToTypedTargetAST { assertEquals(test1.invoke(overloadingInstance, overloadingInstance), "Overloading"); assertEquals(test2.invoke(overloadingInstance, overloading2Instance), "Overloading2"); } + + @Test + public void generics() throws Exception { + var file = Path.of(System.getProperty("user.dir"), "/src/test/resources/bytecode/javFiles/TPHsAndGenerics.jav").toFile(); + var compiler = new JavaTXCompiler(file); + var resultSet = compiler.typeInference(); + var converter = new ASTToTargetAST(resultSet); + var classes = compiler.sourceFiles.get(file).getClasses(); + + converter.convert(classes.get(0)); + } } diff --git a/src/test/resources/bytecode/javFiles/TPHsAndGenerics.jav b/src/test/resources/bytecode/javFiles/TPHsAndGenerics.jav new file mode 100644 index 00000000..84844c9b --- /dev/null +++ b/src/test/resources/bytecode/javFiles/TPHsAndGenerics.jav @@ -0,0 +1,16 @@ +class TPHsAndGenerics { + id = x -> x; + + id2(x) { + return id.apply(x); + } + + m(a, b) { + var c = m2(a, b); + return a; + } + + m2(a, b) { + return b; + } +} \ No newline at end of file