diff --git a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java index c7b74331d..39974c925 100755 --- a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java @@ -809,7 +809,7 @@ public class Codegen { public byte[] generate() { cw.visit(V1_8, clazz.modifiers(), clazz.qualifiedName(), - null, clazz.superType().getName(), + null, clazz.superType() != null ? clazz.superType().getName(): "java/lang/Object", clazz.implementingInterfaces().stream().map(TargetType::toSignature).toArray(String[]::new) ); clazz.fields().forEach(this::generateField); diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index 595ac922a..67e2330a5 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -1,58 +1,113 @@ package de.dhbwstuttgart.target.generate; import de.dhbwstuttgart.exceptions.NotImplementedException; -import de.dhbwstuttgart.syntaxtree.ASTVisitor; -import de.dhbwstuttgart.syntaxtree.ClassOrInterface; -import de.dhbwstuttgart.syntaxtree.Field; -import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.statement.Block; import de.dhbwstuttgart.syntaxtree.statement.Expression; -import de.dhbwstuttgart.syntaxtree.statement.Statement; import de.dhbwstuttgart.syntaxtree.type.*; import de.dhbwstuttgart.target.tree.*; import de.dhbwstuttgart.target.tree.expression.TargetBlock; import de.dhbwstuttgart.target.tree.expression.TargetExpression; import de.dhbwstuttgart.target.tree.type.*; -import de.dhbwstuttgart.typeinference.result.ResultSet; +import de.dhbwstuttgart.typeinference.result.*; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.lang.annotation.Target; +import java.util.*; import java.util.stream.Collectors; public class ASTToTargetAST { + protected List> all; protected HashMap sigma; - public ASTToTargetAST(ResultSet resultSet) { - this.sigma = new HashMap<>(); + private class ResultPairV implements ResultPairVisitor { + @Override + public void visit(PairTPHsmallerTPH p) { + throw new NotImplementedException(); + } + + @Override + public void visit(PairTPHequalRefTypeOrWildcardType p) { + sigma.put(p.left, convert(p.right)); + } + + @Override + public void visit(PairTPHEqualTPH p) { + throw new NotImplementedException(); + } + } + + 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); + } + + this.sigma = all.get(0); } public TargetClass convert(ClassOrInterface input) { - List targetConstructors = new ArrayList<>(); - //TODO constructor conversion -> also reduce syntactic sugar - return new TargetClass(input.getModifiers(),input.getClassName().toString(), sigma.get(input.getSuperClass()), - input.getSuperInterfaces().stream().map(it -> sigma.get(it)).collect(Collectors.toList()), - targetConstructors, - input.getFieldDecl().stream().map(it -> convert(input, it)).collect(Collectors.toList()), - input.getMethods().stream().map(it -> convert(input, it)).collect(Collectors.toList())); - } - - private TargetMethod convert(ClassOrInterface owner, Method input) { - List params = input.getParameterList().getFormalparalist().stream() - .map(param -> new MethodParameter(convert(param.getType()), param.getName())).collect(Collectors.toList()); - return new TargetMethod( - input.modifier, - new TargetRefType(owner.getClassName().getClassName()), - input.name, params, - convert(input.getReturnType()), - convert(input.block) + 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() ); } + private List convert(ParameterList input) { + return input.getFormalparalist().stream() + .map(param -> new MethodParameter(convert(param.getType()), param.getName())).toList(); + } + + private List convert(ClassOrInterface owner, Constructor input) { + sigma = all.get(0); + List result = new ArrayList<>(); + Set> parameterSet = new HashSet<>(); + + for (var s : all) { + sigma = s; + List params = convert(input.getParameterList()); + if (!parameterSet.stream().filter(p -> p.equals(params)).findFirst().isPresent()) { + result.add(new TargetConstructor(input.modifier, new TargetRefType(owner.getClassName().getClassName()), params, convert(input.block))); + parameterSet.add(params); + } + } + + return result; + } + + private List convert(ClassOrInterface owner, Method input) { + sigma = all.get(0); + List result = new ArrayList<>(); + Set> parameterSet = new HashSet<>(); + + for (var s : all) { + sigma = s; + List params = convert(input.getParameterList()); + if (!parameterSet.stream().filter(p -> p.equals(params)).findFirst().isPresent()) { + result.add(new TargetMethod( + input.modifier, + new TargetRefType(owner.getClassName().getClassName()), + input.name, params, + convert(input.getReturnType()), + convert(input.block) + )); + parameterSet.add(params); + } + } + + return result; + } + protected TargetBlock convert(Block block) { - return new TargetBlock(block.statements.stream().map(this::convert).collect(Collectors.toList())); + return new TargetBlock(block.statements.stream().map(this::convert).toList()); } protected TargetExpression convert(Expression expr) { @@ -74,8 +129,10 @@ public class ASTToTargetAST { return input.acceptTV(new TypeVisitor<>() { @Override public TargetType visit(RefType refType) { - return new TargetRefType(refType.getName().toString(), - refType.getParaList().stream().map(ASTToTargetAST.this::convert).collect(Collectors.toList())); + var name = refType.getName().toString(); + if (name.equals("void")) return null; + return new TargetRefType(name, + refType.getParaList().stream().map(ASTToTargetAST.this::convert).toList()); } @Override diff --git a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java index 3f16fa6e7..2bc06235f 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java @@ -7,7 +7,9 @@ import de.dhbwstuttgart.syntaxtree.statement.*; import de.dhbwstuttgart.target.tree.MethodParameter; import de.dhbwstuttgart.target.tree.expression.*; import de.dhbwstuttgart.target.tree.type.TargetFunNType; +import de.dhbwstuttgart.target.tree.type.TargetRefType; +import java.util.List; import java.util.stream.StreamSupport; public class StatementToTargetExpression implements StatementVisitor { @@ -128,7 +130,7 @@ public class StatementToTargetExpression implements StatementVisitor { var receiver = methodCall.receiver; result = new TargetMethodCall( converter.convert(methodCall.getType()), - methodCall.argTypes.stream().map(converter::convert).toList(), + methodCall.argTypes == null ? List.of() : methodCall.argTypes.stream().map(converter::convert).toList(), converter.convert(receiver), methodCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), converter.convert(receiver.getType()), @@ -177,7 +179,7 @@ public class StatementToTargetExpression implements StatementVisitor { @Override public void visit(WhileStmt whileStmt) { - + result = new TargetWhile(converter.convert(whileStmt.expr), converter.convert(whileStmt.loopBlock)); } @Override @@ -198,13 +200,19 @@ public class StatementToTargetExpression implements StatementVisitor { @Override public void visit(SuperCall superCall) { - this.visit((MethodCall) superCall); + result = new TargetMethodCall( + converter.convert(superCall.getType()), + superCall.argTypes == null ? List.of() : superCall.argTypes.stream().map(converter::convert).toList(), + new TargetSuper(null), + superCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), + null, + superCall.name, false, false + ); } @Override public void visit(ExpressionReceiver expressionReceiver) { - // TODO What is this? - throw new NotImplementedException(); + result = converter.convert(expressionReceiver.expr); } @Override diff --git a/src/test/java/targetast/ASTToTargetTest.java b/src/test/java/targetast/ASTToTargetTest.java deleted file mode 100644 index 64d3368f6..000000000 --- a/src/test/java/targetast/ASTToTargetTest.java +++ /dev/null @@ -1,5 +0,0 @@ -package targetast; - -public class ASTToTargetTest { - -} diff --git a/src/test/java/targetast/ASTToTypedTargetAST.java b/src/test/java/targetast/ASTToTypedTargetAST.java index 4e5437cc3..687a1ff8a 100644 --- a/src/test/java/targetast/ASTToTypedTargetAST.java +++ b/src/test/java/targetast/ASTToTypedTargetAST.java @@ -1,5 +1,6 @@ package targetast; +import de.dhbwstuttgart.core.JavaTXCompiler; import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.syntaxtree.*; @@ -7,14 +8,14 @@ import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.target.generate.ASTToTargetAST; import de.dhbwstuttgart.target.tree.TargetClass; import de.dhbwstuttgart.typeinference.result.ResultSet; -import org.antlr.v4.runtime.Token; import org.junit.Test; -import java.lang.reflect.Modifier; +import java.nio.file.Path; import java.util.ArrayList; import java.util.HashSet; import java.util.List; -import java.util.Optional; + +import static org.junit.Assert.*; public class ASTToTypedTargetAST { @@ -23,10 +24,30 @@ public class ASTToTypedTargetAST { ClassOrInterface emptyClass = new ClassOrInterface(0, new JavaClassName("EmptyClass"), new ArrayList<>(), java.util.Optional.empty(), new ArrayList<>(), new ArrayList<>(), new GenericDeclarationList(new ArrayList<>(), new NullToken()), new RefType(new JavaClassName("Object"), new NullToken()), false, new ArrayList<>(), new NullToken()); ResultSet emptyResultSet = new ResultSet(new HashSet<>()); - TargetClass emptyTargetClass = new ASTToTargetAST(emptyResultSet).convert(emptyClass); + TargetClass emptyTargetClass = new ASTToTargetAST(List.of(emptyResultSet)).convert(emptyClass); assert emptyTargetClass.getName().equals("EmptyClass"); assert emptyTargetClass.methods().size() == 0; assert emptyTargetClass.fields().size() == 0; } + @Test + public void overloading() throws Exception { + var file = Path.of(System.getProperty("user.dir"), "/src/test/resources/bytecode/javFiles/Overloading.jav").toFile(); + var compiler = new JavaTXCompiler(file); + var resultSet = compiler.typeInference(); + 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 test1 = overloading.getDeclaredMethod("test", overloading); + test1.setAccessible(true); + var test2 = overloading.getDeclaredMethod("test", overloading2); + test2.setAccessible(true); + Object overloadingInstance = overloading.getDeclaredConstructor().newInstance(); + Object overloading2Instance = overloading2.getDeclaredConstructor().newInstance(); + assertEquals(test1.invoke(overloadingInstance, overloadingInstance), "Overloading"); + assertEquals(test2.invoke(overloadingInstance, overloading2Instance), "Overloading2"); + } } diff --git a/src/test/java/targetast/TestCodegen.java b/src/test/java/targetast/TestCodegen.java index 1806fb33f..b063ee825 100644 --- a/src/test/java/targetast/TestCodegen.java +++ b/src/test/java/targetast/TestCodegen.java @@ -21,7 +21,7 @@ public class TestCodegen { private static ByteArrayClassLoader loader = new ByteArrayClassLoader(); - private static Class generateClass(TargetClass clazz) throws IOException { + public static Class generateClass(TargetClass clazz) throws IOException { var codegen = new Codegen(clazz); var bytes = codegen.generate(); var path = Path.of(System.getProperty("user.dir"), "src/test/resources/target/");