From c22d12f6b00bad8ad626c6bb5451d90b724d8ac1 Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Thu, 17 Mar 2022 17:36:34 +0100 Subject: [PATCH 01/69] =?UTF-8?q?Hinzuf=C3=BCgen=20des=20Grundkonstrukts?= =?UTF-8?q?=20der=20Intermediate-Typen.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../intermediate/types/IntermediateExtendsWildcard.java | 4 ++++ .../intermediate/types/IntermediateGenericType.java | 4 ++++ .../intermediate/types/IntermediateRefType.java | 4 ++++ .../intermediate/types/IntermediateSuperWildcard.java | 4 ++++ .../dhbwstuttgart/intermediate/types/IntermediateType.java | 5 +++++ 5 files changed, 21 insertions(+) create mode 100644 src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateExtendsWildcard.java create mode 100644 src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java create mode 100644 src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java create mode 100644 src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateSuperWildcard.java create mode 100644 src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateExtendsWildcard.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateExtendsWildcard.java new file mode 100644 index 00000000..20190127 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateExtendsWildcard.java @@ -0,0 +1,4 @@ +package de.dhbwstuttgart.intermediate.types; + +public class IntermediateExtendsWildcard { +} diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java new file mode 100644 index 00000000..7f4df842 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java @@ -0,0 +1,4 @@ +package de.dhbwstuttgart.intermediate.types; + +public class IntermediateGenericType { +} diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java new file mode 100644 index 00000000..af3f9d05 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java @@ -0,0 +1,4 @@ +package de.dhbwstuttgart.intermediate.types; + +public class IntermediateRefType { +} diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateSuperWildcard.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateSuperWildcard.java new file mode 100644 index 00000000..d3cb6f8c --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateSuperWildcard.java @@ -0,0 +1,4 @@ +package de.dhbwstuttgart.intermediate.types; + +public class IntermediateSuperWildcard { +} diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java new file mode 100644 index 00000000..42df3d5d --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java @@ -0,0 +1,5 @@ +package de.dhbwstuttgart.intermediate.types; + +public interface IntermediateType { + +} From f457e7e4d0e97b95ef2b339db57a313240a7b48b Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Fri, 18 Mar 2022 09:09:33 +0100 Subject: [PATCH 02/69] =?UTF-8?q?Erste=20Implementierung=20des=20Intermedi?= =?UTF-8?q?ateType=20und=20unvollst=C3=A4ndige=20Implementierung=20von=20I?= =?UTF-8?q?ntermediateRefType.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../convert/ASTToIntermediate.java | 5 ++ .../types/IntermediateExtendsWildcard.java | 11 +++- .../types/IntermediateGenericType.java | 11 +++- .../types/IntermediateRefType.java | 66 ++++++++++++++++++- .../types/IntermediateSuperWildcard.java | 11 +++- .../intermediate/types/IntermediateType.java | 35 +++++++++- 6 files changed, 133 insertions(+), 6 deletions(-) create mode 100644 src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java diff --git a/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java b/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java new file mode 100644 index 00000000..0673cbe2 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java @@ -0,0 +1,5 @@ +package de.dhbwstuttgart.intermediate.convert; + +public class ASTToIntermediate { + //ToDo +} diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateExtendsWildcard.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateExtendsWildcard.java index 20190127..b4f57597 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateExtendsWildcard.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateExtendsWildcard.java @@ -1,4 +1,13 @@ package de.dhbwstuttgart.intermediate.types; -public class IntermediateExtendsWildcard { +import de.dhbwstuttgart.parser.scope.JavaClassName; + +/** + * //ToDo Beschreiben + * + * @since Studienarbeit Type Erasure + * @author etiennezink + */ +public final class IntermediateExtendsWildcard { + //ToDo } diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java index 7f4df842..8e176a49 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java @@ -1,4 +1,13 @@ package de.dhbwstuttgart.intermediate.types; -public class IntermediateGenericType { +import de.dhbwstuttgart.parser.scope.JavaClassName; + +/** + * //ToDo Beschreiben + * + * @since Studienarbeit Type Erasure + * @author etiennezink + */ +public final class IntermediateGenericType { + //ToDo } diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java index af3f9d05..84d66b1e 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java @@ -1,4 +1,68 @@ package de.dhbwstuttgart.intermediate.types; -public class IntermediateRefType { +import de.dhbwstuttgart.parser.scope.JavaClassName; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Represents a Java reference type. + * + * @since Studienarbeit Type Erasure + * @author etiennezink + */ +public final class IntermediateRefType extends IntermediateType{ + + private final List typParameters; + + public IntermediateRefType(JavaClassName className) { + this(className, new ArrayList<>()); + } + + public IntermediateRefType(JavaClassName className, List typParameters){ + super(className); + this.typParameters = Collections.unmodifiableList(typParameters); + } + + @Override + public String getClassSignature() { + //ToDo + return null; + } + + @Override + public String getClassDescriptor() { + //ToDo + return null; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof IntermediateRefType)) return false; + + IntermediateRefType intermediateRefType = (IntermediateRefType) o; + if(!getFullyQualifiedName().equals(intermediateRefType.getFullyQualifiedName())) return false; + + for(int index = 0; index < typParameters.size(); index++){ + if(!typParameters.get(index).equals(intermediateRefType.typParameters.get(index))) return false; + } + return true; + } + + @Override + public int hashCode() { + //ToDo korrekte Definition auf Basis von equals + return 0; + } + + public int getTypParameterSize(){ return typParameters.size(); } + + /** + * @param index + * @return the typ parameter at {@code index} or {@code null}, iff {@code |typ parameters| < index} + */ + public IntermediateType getTypParameter(int index) { + if(getTypParameterSize() < index) return null; + return typParameters.get(index); + } } diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateSuperWildcard.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateSuperWildcard.java index d3cb6f8c..1fe48ace 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateSuperWildcard.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateSuperWildcard.java @@ -1,4 +1,13 @@ package de.dhbwstuttgart.intermediate.types; -public class IntermediateSuperWildcard { +import de.dhbwstuttgart.parser.scope.JavaClassName; + +/** + * //ToDo Beschreiben + * + * @since Studienarbeit Type Erasure + * @author etiennezink + */ +public final class IntermediateSuperWildcard { + //ToDo } diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java index 42df3d5d..3e0725bc 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java @@ -1,5 +1,36 @@ package de.dhbwstuttgart.intermediate.types; -public interface IntermediateType { - +import de.dhbwstuttgart.core.IItemWithOffset; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import org.antlr.v4.runtime.Token; + +/** + * //ToDo Beschreiben + * + * @since Studienarbeit Type Erasure + * @author etiennezink + */ +public abstract class IntermediateType { + + private final JavaClassName className; + + public IntermediateType(JavaClassName className){ this.className = className; } + + @Override + public abstract boolean equals(Object o); + + @Override + public abstract int hashCode(); + + public abstract String getClassSignature(); + public abstract String getClassDescriptor(); + + @Override + public String toString() { return getFullyQualifiedName(); } + + public String getClassName() { + return className.getClassName(); + } + public String getPackageName() { return className.getPackageName(); } + public String getFullyQualifiedName() { return className.toString(); } } From 3d19d8d729267c3ea9f962b38f5af250898ecb9b Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Fri, 18 Mar 2022 12:53:06 +0100 Subject: [PATCH 03/69] =?UTF-8?q?Hinzuf=C3=BCgen=20der=20Klassenbeschreibu?= =?UTF-8?q?ng=20im=20JavaDoc=20f=C3=BCr=20IntermediateType.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dhbwstuttgart/intermediate/types/IntermediateType.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java index 3e0725bc..3c66558f 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java @@ -1,11 +1,11 @@ package de.dhbwstuttgart.intermediate.types; -import de.dhbwstuttgart.core.IItemWithOffset; import de.dhbwstuttgart.parser.scope.JavaClassName; -import org.antlr.v4.runtime.Token; /** - * //ToDo Beschreiben + * Base class for Java data types which is used as an intermediate representation after type resolution. + * This class and it's subtypes have to be immutable (e.g. no mutators) to ensure side effect freedom. + * Immutability and final subtypes are essential for future parallel processing. * * @since Studienarbeit Type Erasure * @author etiennezink From c681396061617debc43d2d335de9edaf3555b21c Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Sat, 19 Mar 2022 16:33:13 +0100 Subject: [PATCH 04/69] Implementierung und Tests von IntermediateRefType. --- .../types/IntermediateRefType.java | 46 ++++++++++++---- .../intermediate/types/IntermediateType.java | 1 - .../types/IntermediateRefTypeTest.java | 54 +++++++++++++++++++ 3 files changed, 91 insertions(+), 10 deletions(-) create mode 100644 src/test/java/intermediate/types/IntermediateRefTypeTest.java diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java index 84d66b1e..b8e9704a 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java @@ -15,6 +15,16 @@ public final class IntermediateRefType extends IntermediateType{ private final List typParameters; + /** + * Caches the hashCode after first computation. + */ + private int hashCode; + + /** + * Caches the classSignature after first computation. + */ + private String classSignature = ""; + public IntermediateRefType(JavaClassName className) { this(className, new ArrayList<>()); } @@ -26,14 +36,24 @@ public final class IntermediateRefType extends IntermediateType{ @Override public String getClassSignature() { - //ToDo - return null; - } + String signature = classSignature; + if (!signature.equals("")) return classSignature; - @Override - public String getClassDescriptor() { - //ToDo - return null; + if (getClassName().equals("void")) signature = "V"; + else { + signature += String.format("L%s", getFullyQualifiedName()); + if (getTypParameterSize() != 0){ + signature += "<"; + for (IntermediateType typParameter:typParameters) { + signature += String.format("L%s;", typParameter.getFullyQualifiedName()); + } + signature += ">"; + } + signature += ";"; + } + signature.replace('.','/'); + classSignature = signature; + return signature; } @Override @@ -51,8 +71,16 @@ public final class IntermediateRefType extends IntermediateType{ @Override public int hashCode() { - //ToDo korrekte Definition auf Basis von equals - return 0; + int prime = 31; + int result = hashCode; + if (result == 0){ + result += getFullyQualifiedName().hashCode(); + for (IntermediateType typeParameter:typParameters) { + result = prime * result + typeParameter.hashCode(); + } + hashCode = result; + } + return result; } public int getTypParameterSize(){ return typParameters.size(); } diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java index 3c66558f..ba0fd5e3 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java @@ -23,7 +23,6 @@ public abstract class IntermediateType { public abstract int hashCode(); public abstract String getClassSignature(); - public abstract String getClassDescriptor(); @Override public String toString() { return getFullyQualifiedName(); } diff --git a/src/test/java/intermediate/types/IntermediateRefTypeTest.java b/src/test/java/intermediate/types/IntermediateRefTypeTest.java new file mode 100644 index 00000000..3c795312 --- /dev/null +++ b/src/test/java/intermediate/types/IntermediateRefTypeTest.java @@ -0,0 +1,54 @@ +package intermediate.types; + +import de.dhbwstuttgart.intermediate.types.IntermediateRefType; +import de.dhbwstuttgart.parser.scope.JavaClassName; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.objectweb.asm.Type; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertEquals; + +public class IntermediateRefTypeTest { + + private static String integerSignature; + private static IntermediateRefType typeToTest_Integer; + + private static String listOfIntegerSignature; + private static IntermediateRefType typeToTest_ListofInteger; + + private static String voidSignature; + private static IntermediateRefType typeToTest_void; + + @BeforeClass + public static void StartUp(){ + integerSignature = "Ljava/lang/Integer;"; + typeToTest_Integer = new IntermediateRefType(new JavaClassName(Type.getInternalName(Integer.class))); + + listOfIntegerSignature = "Ljava/util/List;"; + typeToTest_ListofInteger = new IntermediateRefType( + new JavaClassName(Type.getInternalName(List.class)), + Arrays.asList(typeToTest_Integer)); + + voidSignature = "V"; + typeToTest_void = new IntermediateRefType(new JavaClassName("void")); + } + + @Test + public void SignatureTest_Integer(){ + assertEquals(integerSignature, typeToTest_Integer.getClassSignature()); + } + + @Test + public void SignatureTest_List(){ + assertEquals(listOfIntegerSignature, typeToTest_ListofInteger.getClassSignature()); + } + + @Test + public void SignatureTest_Void(){ + assertEquals(voidSignature, typeToTest_void.getClassSignature()); + } +} From eaec7f613ab1abb01e35fc2b043a052f821396fb Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Sat, 19 Mar 2022 17:22:23 +0100 Subject: [PATCH 05/69] =?UTF-8?q?Hinzuf=C3=BCgen=20von=20abstract=20getCla?= =?UTF-8?q?ssDescriptor=20in=20IntermediateType=20und=20Implementierung=20?= =?UTF-8?q?von=20IntermediateGenericType.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../types/IntermediateGenericType.java | 69 ++++++++++++++++++- .../types/IntermediateRefType.java | 9 ++- .../intermediate/types/IntermediateType.java | 1 + .../types/IntermediateRefTypeTest.java | 21 +++++- 4 files changed, 93 insertions(+), 7 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java index 8e176a49..6efc26b7 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java @@ -1,13 +1,76 @@ package de.dhbwstuttgart.intermediate.types; import de.dhbwstuttgart.parser.scope.JavaClassName; +import org.objectweb.asm.Type; /** - * //ToDo Beschreiben + * Represents a Java typ variable like {@code <T>} or {@code <T extends String>}. * * @since Studienarbeit Type Erasure * @author etiennezink */ -public final class IntermediateGenericType { - //ToDo +//ToDo besprechen ob so korrekt +//z.b. Verwendeung von getFullyQualifiedName und co. +public final class IntermediateGenericType extends IntermediateType { + + private final String genericName; + + /** + * Caches the hashCode after first computation. + */ + private int hashCode; + + /** + * Caches the classSignature after first computation. + */ + private String classSignature = ""; + + public IntermediateGenericType(String genericName){ + this(genericName, new JavaClassName(Type.getInternalName(Object.class))); + } + + public IntermediateGenericType(String genericName, JavaClassName className) { + super(className); + this.genericName = genericName; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof IntermediateGenericType)) return false; + + IntermediateGenericType intermediateGenericType = (IntermediateGenericType) o; + if(!getFullyQualifiedName().equals(intermediateGenericType.getFullyQualifiedName())) return false; + if(!genericName.equals(intermediateGenericType.getGenericName())) return false; + return true; + } + + @Override + public int hashCode() { + int prime = 31; + int result = hashCode; + if (result == 0){ + result += getFullyQualifiedName().hashCode(); + result = prime * result + genericName.hashCode(); + hashCode = result; + } + return result; + } + + @Override + public String getClassSignature() { + String signature = classSignature; + if (!signature.equals("")) return classSignature; + signature += String.format("T%s;", genericName); + classSignature = signature; + return signature; + } + + @Override + public String getClassDescriptor() { + return String.format("L%s;", getFullyQualifiedName()).replace('.','/'); + } + + public String getGenericName() { + return genericName; + } } diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java index b8e9704a..43db30df 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java @@ -42,7 +42,7 @@ public final class IntermediateRefType extends IntermediateType{ if (getClassName().equals("void")) signature = "V"; else { signature += String.format("L%s", getFullyQualifiedName()); - if (getTypParameterSize() != 0){ + if (typParameters.size() != 0){ signature += "<"; for (IntermediateType typParameter:typParameters) { signature += String.format("L%s;", typParameter.getFullyQualifiedName()); @@ -56,6 +56,11 @@ public final class IntermediateRefType extends IntermediateType{ return signature; } + @Override + public String getClassDescriptor() { + return getClassSignature().replaceAll("<.+>", ""); + } + @Override public boolean equals(Object o) { if (!(o instanceof IntermediateRefType)) return false; @@ -90,7 +95,7 @@ public final class IntermediateRefType extends IntermediateType{ * @return the typ parameter at {@code index} or {@code null}, iff {@code |typ parameters| < index} */ public IntermediateType getTypParameter(int index) { - if(getTypParameterSize() < index) return null; + if(typParameters.size() < index) return null; return typParameters.get(index); } } diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java index ba0fd5e3..3c66558f 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java @@ -23,6 +23,7 @@ public abstract class IntermediateType { public abstract int hashCode(); public abstract String getClassSignature(); + public abstract String getClassDescriptor(); @Override public String toString() { return getFullyQualifiedName(); } diff --git a/src/test/java/intermediate/types/IntermediateRefTypeTest.java b/src/test/java/intermediate/types/IntermediateRefTypeTest.java index 3c795312..d70287b2 100644 --- a/src/test/java/intermediate/types/IntermediateRefTypeTest.java +++ b/src/test/java/intermediate/types/IntermediateRefTypeTest.java @@ -15,25 +15,31 @@ import static org.junit.Assert.assertEquals; public class IntermediateRefTypeTest { private static String integerSignature; + private static String integerDescriptor; private static IntermediateRefType typeToTest_Integer; private static String listOfIntegerSignature; + private static String listOfIntegerDescriptor; private static IntermediateRefType typeToTest_ListofInteger; private static String voidSignature; + private static String voidDescriptor; private static IntermediateRefType typeToTest_void; @BeforeClass public static void StartUp(){ integerSignature = "Ljava/lang/Integer;"; + integerDescriptor = "Ljava/lang/Integer;"; typeToTest_Integer = new IntermediateRefType(new JavaClassName(Type.getInternalName(Integer.class))); listOfIntegerSignature = "Ljava/util/List;"; + listOfIntegerDescriptor = "Ljava/util/List;"; typeToTest_ListofInteger = new IntermediateRefType( new JavaClassName(Type.getInternalName(List.class)), Arrays.asList(typeToTest_Integer)); voidSignature = "V"; + voidDescriptor = "V"; typeToTest_void = new IntermediateRefType(new JavaClassName("void")); } @@ -43,12 +49,23 @@ public class IntermediateRefTypeTest { } @Test - public void SignatureTest_List(){ - assertEquals(listOfIntegerSignature, typeToTest_ListofInteger.getClassSignature()); + public void DescriptorTest_Integer(){ + assertEquals(integerDescriptor, typeToTest_Integer.getClassDescriptor()); } + @Test + public void SignatureTest_List(){ assertEquals(listOfIntegerSignature, typeToTest_ListofInteger.getClassSignature()); } + + @Test + public void DescriptorTest_List(){ assertEquals(listOfIntegerDescriptor, typeToTest_ListofInteger.getClassDescriptor()); } + @Test public void SignatureTest_Void(){ assertEquals(voidSignature, typeToTest_void.getClassSignature()); } + + @Test + public void DescriptorTest_Void(){ + assertEquals(voidDescriptor, typeToTest_void.getClassDescriptor()); + } } From c32a0cc2227a75f133de8914274db553720fe6c1 Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Sat, 19 Mar 2022 18:03:54 +0100 Subject: [PATCH 06/69] Refactoring access-Modifier von IntermediateType (Klassen-Name Methoden). Refactoring Signature- und Descriptor-Methoden und caching des Descriptors. --- .../types/IntermediateGenericType.java | 43 +++++++++++-------- .../types/IntermediateRefType.java | 25 +++++++---- .../intermediate/types/IntermediateType.java | 10 ++--- .../types/IntermediateRefTypeTest.java | 12 +++--- 4 files changed, 53 insertions(+), 37 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java index 6efc26b7..82a1b6fb 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java @@ -9,8 +9,6 @@ import org.objectweb.asm.Type; * @since Studienarbeit Type Erasure * @author etiennezink */ -//ToDo besprechen ob so korrekt -//z.b. Verwendeung von getFullyQualifiedName und co. public final class IntermediateGenericType extends IntermediateType { private final String genericName; @@ -21,9 +19,14 @@ public final class IntermediateGenericType extends IntermediateType { private int hashCode; /** - * Caches the classSignature after first computation. + * Caches the signature after first computation. */ - private String classSignature = ""; + private String signature = ""; + + /** + * Caches the descriptor after first computation. + */ + private String descriptor = ""; public IntermediateGenericType(String genericName){ this(genericName, new JavaClassName(Type.getInternalName(Object.class))); @@ -34,6 +37,24 @@ public final class IntermediateGenericType extends IntermediateType { this.genericName = genericName; } + @Override + public String getSignature() { + String signature = this.signature; + if (!signature.equals("")) return this.signature; + signature += String.format("T%s;", genericName); + this.signature = signature; + return signature; + } + + @Override + public String getDescriptor() { + String descriptor = this.descriptor; + if (!descriptor.equals("")) return this.descriptor; + descriptor = String.format("L%s;", getFullyQualifiedName()).replace('.','/'); + this.descriptor = descriptor; + return descriptor; + } + @Override public boolean equals(Object o) { if (!(o instanceof IntermediateGenericType)) return false; @@ -56,20 +77,6 @@ public final class IntermediateGenericType extends IntermediateType { return result; } - @Override - public String getClassSignature() { - String signature = classSignature; - if (!signature.equals("")) return classSignature; - signature += String.format("T%s;", genericName); - classSignature = signature; - return signature; - } - - @Override - public String getClassDescriptor() { - return String.format("L%s;", getFullyQualifiedName()).replace('.','/'); - } - public String getGenericName() { return genericName; } diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java index 43db30df..f8b908b9 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java @@ -21,9 +21,14 @@ public final class IntermediateRefType extends IntermediateType{ private int hashCode; /** - * Caches the classSignature after first computation. + * Caches the signature after first computation. */ - private String classSignature = ""; + private String signature = ""; + + /** + * Caches the descriptor after first computation. + */ + private String descriptor = ""; public IntermediateRefType(JavaClassName className) { this(className, new ArrayList<>()); @@ -35,9 +40,9 @@ public final class IntermediateRefType extends IntermediateType{ } @Override - public String getClassSignature() { - String signature = classSignature; - if (!signature.equals("")) return classSignature; + public String getSignature() { + String signature = this.signature; + if (!signature.equals("")) return this.signature; if (getClassName().equals("void")) signature = "V"; else { @@ -52,13 +57,17 @@ public final class IntermediateRefType extends IntermediateType{ signature += ";"; } signature.replace('.','/'); - classSignature = signature; + this.signature = signature; return signature; } @Override - public String getClassDescriptor() { - return getClassSignature().replaceAll("<.+>", ""); + public String getDescriptor() { + String descriptor = this.descriptor; + if (!descriptor.equals("")) return this.descriptor; + descriptor = getSignature().replaceAll("<.+>", ""); + this.descriptor = descriptor; + return descriptor; } @Override diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java index 3c66558f..b0cb8509 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java @@ -22,15 +22,15 @@ public abstract class IntermediateType { @Override public abstract int hashCode(); - public abstract String getClassSignature(); - public abstract String getClassDescriptor(); + public abstract String getSignature(); + public abstract String getDescriptor(); @Override public String toString() { return getFullyQualifiedName(); } - public String getClassName() { + protected String getClassName() { return className.getClassName(); } - public String getPackageName() { return className.getPackageName(); } - public String getFullyQualifiedName() { return className.toString(); } + protected String getPackageName() { return className.getPackageName(); } + protected String getFullyQualifiedName() { return className.toString(); } } diff --git a/src/test/java/intermediate/types/IntermediateRefTypeTest.java b/src/test/java/intermediate/types/IntermediateRefTypeTest.java index d70287b2..b9cfa6d0 100644 --- a/src/test/java/intermediate/types/IntermediateRefTypeTest.java +++ b/src/test/java/intermediate/types/IntermediateRefTypeTest.java @@ -45,27 +45,27 @@ public class IntermediateRefTypeTest { @Test public void SignatureTest_Integer(){ - assertEquals(integerSignature, typeToTest_Integer.getClassSignature()); + assertEquals(integerSignature, typeToTest_Integer.getSignature()); } @Test public void DescriptorTest_Integer(){ - assertEquals(integerDescriptor, typeToTest_Integer.getClassDescriptor()); + assertEquals(integerDescriptor, typeToTest_Integer.getDescriptor()); } @Test - public void SignatureTest_List(){ assertEquals(listOfIntegerSignature, typeToTest_ListofInteger.getClassSignature()); } + public void SignatureTest_List(){ assertEquals(listOfIntegerSignature, typeToTest_ListofInteger.getSignature()); } @Test - public void DescriptorTest_List(){ assertEquals(listOfIntegerDescriptor, typeToTest_ListofInteger.getClassDescriptor()); } + public void DescriptorTest_List(){ assertEquals(listOfIntegerDescriptor, typeToTest_ListofInteger.getDescriptor()); } @Test public void SignatureTest_Void(){ - assertEquals(voidSignature, typeToTest_void.getClassSignature()); + assertEquals(voidSignature, typeToTest_void.getSignature()); } @Test public void DescriptorTest_Void(){ - assertEquals(voidDescriptor, typeToTest_void.getClassDescriptor()); + assertEquals(voidDescriptor, typeToTest_void.getDescriptor()); } } From 2706c31beb41bb80593b525d53fab8735aca0ecd Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Sat, 19 Mar 2022 18:07:24 +0100 Subject: [PATCH 07/69] Kleine Anpassung von Kommentaren. --- .../intermediate/types/IntermediateGenericType.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java index 82a1b6fb..053cd0db 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java @@ -4,7 +4,8 @@ import de.dhbwstuttgart.parser.scope.JavaClassName; import org.objectweb.asm.Type; /** - * Represents a Java typ variable like {@code <T>} or {@code <T extends String>}. + * Represents a Java typ variable. + * E.g. {@code <T>} or {@code <T extends String>}. * * @since Studienarbeit Type Erasure * @author etiennezink From 36ef1e124ab0513b1d8e766849e3263feef4b957 Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Sat, 19 Mar 2022 18:12:46 +0100 Subject: [PATCH 08/69] =?UTF-8?q?=C3=84nderung=20von=20toSting():=20gibt?= =?UTF-8?q?=20nun=20getSignature()=20statt=20getFullyQualifiedName()=20zur?= =?UTF-8?q?=C3=BCck.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../de/dhbwstuttgart/intermediate/types/IntermediateType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java index b0cb8509..c8dae87e 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java @@ -26,7 +26,7 @@ public abstract class IntermediateType { public abstract String getDescriptor(); @Override - public String toString() { return getFullyQualifiedName(); } + public String toString() { return getSignature(); } protected String getClassName() { return className.getClassName(); From df4faebd925e014d7de61e1fb84ba5b1a6ed6570 Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Sat, 19 Mar 2022 18:16:50 +0100 Subject: [PATCH 09/69] =?UTF-8?q?Hinzuf=C3=BCgen=20der=20extends-Beziehung?= =?UTF-8?q?=20von=20IntermediateExtendsWildcard=20und=20IntermediateSuperW?= =?UTF-8?q?ildcard=20zu=20IntermediateType,=20ohne=20Implementierungen.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../types/IntermediateExtendsWildcard.java | 26 ++++++++- .../types/IntermediateGenericType.java | 36 ++++++------- .../types/IntermediateRefType.java | 54 +++++++++---------- .../types/IntermediateSuperWildcard.java | 26 ++++++++- 4 files changed, 95 insertions(+), 47 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateExtendsWildcard.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateExtendsWildcard.java index b4f57597..eda1eafd 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateExtendsWildcard.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateExtendsWildcard.java @@ -8,6 +8,30 @@ import de.dhbwstuttgart.parser.scope.JavaClassName; * @since Studienarbeit Type Erasure * @author etiennezink */ -public final class IntermediateExtendsWildcard { +public final class IntermediateExtendsWildcard extends IntermediateType { //ToDo + + public IntermediateExtendsWildcard(JavaClassName className) { + super(className); + } + + @Override + public boolean equals(Object o) { + return false; + } + + @Override + public int hashCode() { + return 0; + } + + @Override + public String getSignature() { + return null; + } + + @Override + public String getDescriptor() { + return null; + } } diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java index 053cd0db..9a36e566 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java @@ -38,24 +38,6 @@ public final class IntermediateGenericType extends IntermediateType { this.genericName = genericName; } - @Override - public String getSignature() { - String signature = this.signature; - if (!signature.equals("")) return this.signature; - signature += String.format("T%s;", genericName); - this.signature = signature; - return signature; - } - - @Override - public String getDescriptor() { - String descriptor = this.descriptor; - if (!descriptor.equals("")) return this.descriptor; - descriptor = String.format("L%s;", getFullyQualifiedName()).replace('.','/'); - this.descriptor = descriptor; - return descriptor; - } - @Override public boolean equals(Object o) { if (!(o instanceof IntermediateGenericType)) return false; @@ -78,6 +60,24 @@ public final class IntermediateGenericType extends IntermediateType { return result; } + @Override + public String getSignature() { + String signature = this.signature; + if (!signature.equals("")) return this.signature; + signature += String.format("T%s;", genericName); + this.signature = signature; + return signature; + } + + @Override + public String getDescriptor() { + String descriptor = this.descriptor; + if (!descriptor.equals("")) return this.descriptor; + descriptor = String.format("L%s;", getFullyQualifiedName()).replace('.','/'); + this.descriptor = descriptor; + return descriptor; + } + public String getGenericName() { return genericName; } diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java index f8b908b9..c121becb 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java @@ -39,6 +39,33 @@ public final class IntermediateRefType extends IntermediateType{ this.typParameters = Collections.unmodifiableList(typParameters); } + @Override + public boolean equals(Object o) { + if (!(o instanceof IntermediateRefType)) return false; + + IntermediateRefType intermediateRefType = (IntermediateRefType) o; + if(!getFullyQualifiedName().equals(intermediateRefType.getFullyQualifiedName())) return false; + + for(int index = 0; index < typParameters.size(); index++){ + if(!typParameters.get(index).equals(intermediateRefType.typParameters.get(index))) return false; + } + return true; + } + + @Override + public int hashCode() { + int prime = 31; + int result = hashCode; + if (result == 0){ + result += getFullyQualifiedName().hashCode(); + for (IntermediateType typeParameter:typParameters) { + result = prime * result + typeParameter.hashCode(); + } + hashCode = result; + } + return result; + } + @Override public String getSignature() { String signature = this.signature; @@ -70,33 +97,6 @@ public final class IntermediateRefType extends IntermediateType{ return descriptor; } - @Override - public boolean equals(Object o) { - if (!(o instanceof IntermediateRefType)) return false; - - IntermediateRefType intermediateRefType = (IntermediateRefType) o; - if(!getFullyQualifiedName().equals(intermediateRefType.getFullyQualifiedName())) return false; - - for(int index = 0; index < typParameters.size(); index++){ - if(!typParameters.get(index).equals(intermediateRefType.typParameters.get(index))) return false; - } - return true; - } - - @Override - public int hashCode() { - int prime = 31; - int result = hashCode; - if (result == 0){ - result += getFullyQualifiedName().hashCode(); - for (IntermediateType typeParameter:typParameters) { - result = prime * result + typeParameter.hashCode(); - } - hashCode = result; - } - return result; - } - public int getTypParameterSize(){ return typParameters.size(); } /** diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateSuperWildcard.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateSuperWildcard.java index 1fe48ace..42fdaf37 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateSuperWildcard.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateSuperWildcard.java @@ -8,6 +8,30 @@ import de.dhbwstuttgart.parser.scope.JavaClassName; * @since Studienarbeit Type Erasure * @author etiennezink */ -public final class IntermediateSuperWildcard { +public final class IntermediateSuperWildcard extends IntermediateType { //ToDo + + public IntermediateSuperWildcard(JavaClassName className) { + super(className); + } + + @Override + public boolean equals(Object o) { + return false; + } + + @Override + public int hashCode() { + return 0; + } + + @Override + public String getSignature() { + return null; + } + + @Override + public String getDescriptor() { + return null; + } } From be307e95a67466fa9e9a901e858c3eb814b80116 Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Sat, 19 Mar 2022 18:19:42 +0100 Subject: [PATCH 10/69] =?UTF-8?q?Hizuf=C3=BCgen=20von=20isParametrized=20z?= =?UTF-8?q?u=20IntermediateRefType.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dhbwstuttgart/intermediate/types/IntermediateRefType.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java index c121becb..0f44ec3e 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java @@ -97,6 +97,8 @@ public final class IntermediateRefType extends IntermediateType{ return descriptor; } + public boolean isParametrized() { return typParameters.size() > 0; } + public int getTypParameterSize(){ return typParameters.size(); } /** From 9baf89acc28616f77613d1935b6c376256b04af9 Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Sat, 19 Mar 2022 18:32:12 +0100 Subject: [PATCH 11/69] =?UTF-8?q?=C3=84nderung=20von=20hashCode()=20und=20?= =?UTF-8?q?equals(),=20in=20IntermediateGenericType=20und=20IntermediateRe?= =?UTF-8?q?fType,=20auf=20Basis=20von=20getSignature()=20und=20nicht=20meh?= =?UTF-8?q?r=20getFullyQualifiedName().?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../types/IntermediateGenericType.java | 16 ++++++++-------- .../intermediate/types/IntermediateRefType.java | 14 +++++++------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java index 9a36e566..f833d121 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java @@ -43,21 +43,21 @@ public final class IntermediateGenericType extends IntermediateType { if (!(o instanceof IntermediateGenericType)) return false; IntermediateGenericType intermediateGenericType = (IntermediateGenericType) o; - if(!getFullyQualifiedName().equals(intermediateGenericType.getFullyQualifiedName())) return false; - if(!genericName.equals(intermediateGenericType.getGenericName())) return false; + if(!getSignature().equals(intermediateGenericType.getSignature())) return false; + if(!genericName.equals(intermediateGenericType.genericName)) return false; return true; } @Override public int hashCode() { int prime = 31; - int result = hashCode; - if (result == 0){ - result += getFullyQualifiedName().hashCode(); - result = prime * result + genericName.hashCode(); - hashCode = result; + int hashCode = this.hashCode; + if (hashCode == 0){ + hashCode += getSignature().hashCode(); + hashCode = prime * hashCode + genericName.hashCode(); + this.hashCode = hashCode; } - return result; + return hashCode; } @Override diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java index 0f44ec3e..bba52531 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java @@ -44,7 +44,7 @@ public final class IntermediateRefType extends IntermediateType{ if (!(o instanceof IntermediateRefType)) return false; IntermediateRefType intermediateRefType = (IntermediateRefType) o; - if(!getFullyQualifiedName().equals(intermediateRefType.getFullyQualifiedName())) return false; + if(!getSignature().equals(intermediateRefType.getSignature())) return false; for(int index = 0; index < typParameters.size(); index++){ if(!typParameters.get(index).equals(intermediateRefType.typParameters.get(index))) return false; @@ -55,15 +55,15 @@ public final class IntermediateRefType extends IntermediateType{ @Override public int hashCode() { int prime = 31; - int result = hashCode; - if (result == 0){ - result += getFullyQualifiedName().hashCode(); + int hashCode = this.hashCode; + if (hashCode == 0){ + hashCode += getSignature().hashCode(); for (IntermediateType typeParameter:typParameters) { - result = prime * result + typeParameter.hashCode(); + hashCode = prime * hashCode + typeParameter.hashCode(); } - hashCode = result; + this.hashCode = hashCode; } - return result; + return hashCode; } @Override From 06b27dabd2726e03b891063f29a37c3df932c19d Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Sun, 20 Mar 2022 15:07:02 +0100 Subject: [PATCH 12/69] =?UTF-8?q?=C3=84nderung=20von=20hashCode()=20und=20?= =?UTF-8?q?equals()=20zur=C3=BCck=20zur=20Benutzung=20von=20getFullyQualif?= =?UTF-8?q?iedName(),=20da=20dies=20eindeutig=20ist=20im=20Gegensatz=20zu?= =?UTF-8?q?=20getSignature().?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../intermediate/types/IntermediateGenericType.java | 4 ++-- .../dhbwstuttgart/intermediate/types/IntermediateRefType.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java index f833d121..41da2502 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java @@ -43,7 +43,7 @@ public final class IntermediateGenericType extends IntermediateType { if (!(o instanceof IntermediateGenericType)) return false; IntermediateGenericType intermediateGenericType = (IntermediateGenericType) o; - if(!getSignature().equals(intermediateGenericType.getSignature())) return false; + if(!getFullyQualifiedName().equals(intermediateGenericType.getFullyQualifiedName())) return false; if(!genericName.equals(intermediateGenericType.genericName)) return false; return true; } @@ -53,7 +53,7 @@ public final class IntermediateGenericType extends IntermediateType { int prime = 31; int hashCode = this.hashCode; if (hashCode == 0){ - hashCode += getSignature().hashCode(); + hashCode += getFullyQualifiedName().hashCode(); hashCode = prime * hashCode + genericName.hashCode(); this.hashCode = hashCode; } diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java index bba52531..e42f5258 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java @@ -44,7 +44,7 @@ public final class IntermediateRefType extends IntermediateType{ if (!(o instanceof IntermediateRefType)) return false; IntermediateRefType intermediateRefType = (IntermediateRefType) o; - if(!getSignature().equals(intermediateRefType.getSignature())) return false; + if(!getFullyQualifiedName().equals(intermediateRefType.getFullyQualifiedName())) return false; for(int index = 0; index < typParameters.size(); index++){ if(!typParameters.get(index).equals(intermediateRefType.typParameters.get(index))) return false; @@ -57,7 +57,7 @@ public final class IntermediateRefType extends IntermediateType{ int prime = 31; int hashCode = this.hashCode; if (hashCode == 0){ - hashCode += getSignature().hashCode(); + hashCode += getFullyQualifiedName().hashCode(); for (IntermediateType typeParameter:typParameters) { hashCode = prime * hashCode + typeParameter.hashCode(); } From 55a75b04a06c3238094dda7ca42433671d9ce9cd Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Sun, 20 Mar 2022 16:08:38 +0100 Subject: [PATCH 13/69] =?UTF-8?q?Refactoring=20f=C3=BCr=20innere=20Typen,?= =?UTF-8?q?=20welche=20ausschlie=C3=9Flich=20einen=20Descriptor=20besitzen?= =?UTF-8?q?.=20Innere=20Typen=20sind=20dabei=20IntermediateRefType=20und?= =?UTF-8?q?=20IntermediateGenericType.=20Implementierung=20der=20Intermedi?= =?UTF-8?q?ateWildcard=20Typen=20und=20Hinzuf=C3=BCgen=20leerer=20Tests.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../types/IntermediateExtendsWildcard.java | 46 ++++++++++++++----- .../types/IntermediateGenericType.java | 15 +++--- .../types/IntermediateInnerType.java | 9 ++++ .../types/IntermediateRefType.java | 11 +++-- .../types/IntermediateSuperWildcard.java | 45 +++++++++++++----- .../intermediate/types/IntermediateType.java | 13 ------ .../types/IntermediateExtensWildcardTest.java | 11 +++++ .../types/IntermediateGenericTypeTest.java | 11 +++++ .../types/IntermediateSuperWildcardTest.java | 11 +++++ 9 files changed, 124 insertions(+), 48 deletions(-) create mode 100644 src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateInnerType.java create mode 100644 src/test/java/intermediate/types/IntermediateExtensWildcardTest.java create mode 100644 src/test/java/intermediate/types/IntermediateGenericTypeTest.java create mode 100644 src/test/java/intermediate/types/IntermediateSuperWildcardTest.java diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateExtendsWildcard.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateExtendsWildcard.java index eda1eafd..d1be0aeb 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateExtendsWildcard.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateExtendsWildcard.java @@ -3,35 +3,57 @@ package de.dhbwstuttgart.intermediate.types; import de.dhbwstuttgart.parser.scope.JavaClassName; /** - * //ToDo Beschreiben + * Represents a Java Wildcard with a extends-operator. + * E.g. {@code <? extends String>} * * @since Studienarbeit Type Erasure * @author etiennezink */ public final class IntermediateExtendsWildcard extends IntermediateType { - //ToDo - public IntermediateExtendsWildcard(JavaClassName className) { - super(className); + private final IntermediateInnerType innerType; + + /** + * Caches the hashCode after first computation. + */ + private int hashCode; + + /** + * Caches the signature after first computation. + */ + private String signature = ""; + + public IntermediateExtendsWildcard(IntermediateInnerType innerType) { + this.innerType = innerType; } @Override public boolean equals(Object o) { - return false; + if (!(o instanceof IntermediateExtendsWildcard)) return false; + + IntermediateExtendsWildcard intermediateExtendsWildcard = (IntermediateExtendsWildcard) o; + if(!innerType.equals(intermediateExtendsWildcard.innerType)) return false; + return true; } @Override public int hashCode() { - return 0; + int prime = 31; + int hashCode = this.hashCode; + if (hashCode == 0){ + hashCode += innerType.hashCode(); + hashCode = prime * hashCode + "extends".hashCode(); + this.hashCode = hashCode; + } + return hashCode; } @Override public String getSignature() { - return null; - } - - @Override - public String getDescriptor() { - return null; + String signature = this.signature; + if (!signature.equals("")) return this.signature; + signature = String.format("+%s", innerType.getSignature()); + this.signature = signature; + return signature; } } diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java index 41da2502..a222dc2c 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java @@ -10,9 +10,10 @@ import org.objectweb.asm.Type; * @since Studienarbeit Type Erasure * @author etiennezink */ -public final class IntermediateGenericType extends IntermediateType { +public final class IntermediateGenericType extends IntermediateInnerType { private final String genericName; + private final IntermediateInnerType innerType; /** * Caches the hashCode after first computation. @@ -30,11 +31,11 @@ public final class IntermediateGenericType extends IntermediateType { private String descriptor = ""; public IntermediateGenericType(String genericName){ - this(genericName, new JavaClassName(Type.getInternalName(Object.class))); + this(genericName, new IntermediateRefType(new JavaClassName(Type.getInternalName(Object.class)))); } - public IntermediateGenericType(String genericName, JavaClassName className) { - super(className); + public IntermediateGenericType(String genericName, IntermediateInnerType innerType) { + this.innerType = innerType; this.genericName = genericName; } @@ -43,7 +44,7 @@ public final class IntermediateGenericType extends IntermediateType { if (!(o instanceof IntermediateGenericType)) return false; IntermediateGenericType intermediateGenericType = (IntermediateGenericType) o; - if(!getFullyQualifiedName().equals(intermediateGenericType.getFullyQualifiedName())) return false; + if(!innerType.equals(intermediateGenericType.innerType)) return false; if(!genericName.equals(intermediateGenericType.genericName)) return false; return true; } @@ -53,7 +54,7 @@ public final class IntermediateGenericType extends IntermediateType { int prime = 31; int hashCode = this.hashCode; if (hashCode == 0){ - hashCode += getFullyQualifiedName().hashCode(); + hashCode += innerType.hashCode(); hashCode = prime * hashCode + genericName.hashCode(); this.hashCode = hashCode; } @@ -73,7 +74,7 @@ public final class IntermediateGenericType extends IntermediateType { public String getDescriptor() { String descriptor = this.descriptor; if (!descriptor.equals("")) return this.descriptor; - descriptor = String.format("L%s;", getFullyQualifiedName()).replace('.','/'); + descriptor = innerType.getDescriptor(); this.descriptor = descriptor; return descriptor; } diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateInnerType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateInnerType.java new file mode 100644 index 00000000..a83c974f --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateInnerType.java @@ -0,0 +1,9 @@ +package de.dhbwstuttgart.intermediate.types; + +/** + * Only Java types which can be used as an inner type, have a descriptor definition. + */ +public abstract class IntermediateInnerType extends IntermediateType { + + public abstract String getDescriptor(); +} diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java index e42f5258..81ef371a 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java @@ -11,9 +11,10 @@ import java.util.List; * @since Studienarbeit Type Erasure * @author etiennezink */ -public final class IntermediateRefType extends IntermediateType{ +public final class IntermediateRefType extends IntermediateInnerType{ private final List typParameters; + private final JavaClassName className; /** * Caches the hashCode after first computation. @@ -35,7 +36,7 @@ public final class IntermediateRefType extends IntermediateType{ } public IntermediateRefType(JavaClassName className, List typParameters){ - super(className); + this.className = className; this.typParameters = Collections.unmodifiableList(typParameters); } @@ -71,13 +72,13 @@ public final class IntermediateRefType extends IntermediateType{ String signature = this.signature; if (!signature.equals("")) return this.signature; - if (getClassName().equals("void")) signature = "V"; + if (className.getClassName().equals("void")) signature = "V"; else { signature += String.format("L%s", getFullyQualifiedName()); if (typParameters.size() != 0){ signature += "<"; for (IntermediateType typParameter:typParameters) { - signature += String.format("L%s;", typParameter.getFullyQualifiedName()); + signature += typParameter.getSignature(); } signature += ">"; } @@ -109,4 +110,6 @@ public final class IntermediateRefType extends IntermediateType{ if(typParameters.size() < index) return null; return typParameters.get(index); } + + private String getFullyQualifiedName(){ return className.toString(); } } diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateSuperWildcard.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateSuperWildcard.java index 42fdaf37..2e806828 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateSuperWildcard.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateSuperWildcard.java @@ -3,35 +3,56 @@ package de.dhbwstuttgart.intermediate.types; import de.dhbwstuttgart.parser.scope.JavaClassName; /** - * //ToDo Beschreiben + * Represents a Java Wildcard with a super-operator. + * E.g. {@code <? super String>} * * @since Studienarbeit Type Erasure * @author etiennezink */ public final class IntermediateSuperWildcard extends IntermediateType { - //ToDo + private final IntermediateInnerType innerType; - public IntermediateSuperWildcard(JavaClassName className) { - super(className); + /** + * Caches the hashCode after first computation. + */ + private int hashCode; + + /** + * Caches the signature after first computation. + */ + private String signature = ""; + + public IntermediateSuperWildcard(IntermediateInnerType innerType) { + this.innerType = innerType; } @Override public boolean equals(Object o) { - return false; + if (!(o instanceof IntermediateSuperWildcard)) return false; + + IntermediateSuperWildcard intermediateSuperWildcard = (IntermediateSuperWildcard) o; + if(!innerType.equals(intermediateSuperWildcard.innerType)) return false; + return true; } @Override public int hashCode() { - return 0; + int prime = 31; + int hashCode = this.hashCode; + if (hashCode == 0){ + hashCode += innerType.hashCode(); + hashCode = prime * hashCode + "super".hashCode(); + this.hashCode = hashCode; + } + return hashCode; } @Override public String getSignature() { - return null; - } - - @Override - public String getDescriptor() { - return null; + String signature = this.signature; + if (!signature.equals("")) return this.signature; + signature = String.format("-%s", innerType.getSignature()); + this.signature = signature; + return signature; } } diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java index c8dae87e..3edaf9b0 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java @@ -1,7 +1,5 @@ package de.dhbwstuttgart.intermediate.types; -import de.dhbwstuttgart.parser.scope.JavaClassName; - /** * Base class for Java data types which is used as an intermediate representation after type resolution. * This class and it's subtypes have to be immutable (e.g. no mutators) to ensure side effect freedom. @@ -12,10 +10,6 @@ import de.dhbwstuttgart.parser.scope.JavaClassName; */ public abstract class IntermediateType { - private final JavaClassName className; - - public IntermediateType(JavaClassName className){ this.className = className; } - @Override public abstract boolean equals(Object o); @@ -23,14 +17,7 @@ public abstract class IntermediateType { public abstract int hashCode(); public abstract String getSignature(); - public abstract String getDescriptor(); @Override public String toString() { return getSignature(); } - - protected String getClassName() { - return className.getClassName(); - } - protected String getPackageName() { return className.getPackageName(); } - protected String getFullyQualifiedName() { return className.toString(); } } diff --git a/src/test/java/intermediate/types/IntermediateExtensWildcardTest.java b/src/test/java/intermediate/types/IntermediateExtensWildcardTest.java new file mode 100644 index 00000000..d82e7baf --- /dev/null +++ b/src/test/java/intermediate/types/IntermediateExtensWildcardTest.java @@ -0,0 +1,11 @@ +package intermediate.types; + +import org.junit.Assert; +import org.junit.Test; + +public class IntermediateExtensWildcardTest { + @Test + public void ToDo(){ + Assert.fail(); + } +} diff --git a/src/test/java/intermediate/types/IntermediateGenericTypeTest.java b/src/test/java/intermediate/types/IntermediateGenericTypeTest.java new file mode 100644 index 00000000..c7dbed45 --- /dev/null +++ b/src/test/java/intermediate/types/IntermediateGenericTypeTest.java @@ -0,0 +1,11 @@ +package intermediate.types; + +import org.junit.Assert; +import org.junit.Test; + +public class IntermediateGenericTypeTest { + @Test + public void ToDo(){ + Assert.fail(); + } +} diff --git a/src/test/java/intermediate/types/IntermediateSuperWildcardTest.java b/src/test/java/intermediate/types/IntermediateSuperWildcardTest.java new file mode 100644 index 00000000..7ba44c31 --- /dev/null +++ b/src/test/java/intermediate/types/IntermediateSuperWildcardTest.java @@ -0,0 +1,11 @@ +package intermediate.types; + +import org.junit.Assert; +import org.junit.Test; + +public class IntermediateSuperWildcardTest { + @Test + public void ToDo(){ + Assert.fail(); + } +} From 8b58259fe0f83d74a089ca7faf38076dc9bc5b71 Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Sun, 20 Mar 2022 16:34:01 +0100 Subject: [PATCH 14/69] =?UTF-8?q?Hinzuf=C3=BCgen=20von=20Test=20zu=20Inter?= =?UTF-8?q?mediateRefTypeTest=20und=20IntermediateGenericTypeTest.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../types/IntermediateGenericTypeTest.java | 56 +++++++++++++++++-- .../types/IntermediateRefTypeTest.java | 8 +-- 2 files changed, 56 insertions(+), 8 deletions(-) diff --git a/src/test/java/intermediate/types/IntermediateGenericTypeTest.java b/src/test/java/intermediate/types/IntermediateGenericTypeTest.java index c7dbed45..3663faae 100644 --- a/src/test/java/intermediate/types/IntermediateGenericTypeTest.java +++ b/src/test/java/intermediate/types/IntermediateGenericTypeTest.java @@ -1,11 +1,59 @@ package intermediate.types; -import org.junit.Assert; +import de.dhbwstuttgart.intermediate.types.IntermediateGenericType; +import de.dhbwstuttgart.intermediate.types.IntermediateRefType; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import org.junit.BeforeClass; import org.junit.Test; +import org.objectweb.asm.Type; + +import static org.junit.Assert.assertEquals; public class IntermediateGenericTypeTest { - @Test - public void ToDo(){ - Assert.fail(); + + private static String tSignature; + private static String tDescriptor; + private static IntermediateGenericType t; + + private static String sExtendsStringSignature; + private static String sExtendsStringDescriptor; + private static IntermediateGenericType sExtendsString; + + private static String rExtendsSSignature; + private static String rExtendsSDescriptor; + private static IntermediateGenericType rExtendsS; + + @BeforeClass + public static void StartUp(){ + tSignature = "TT;"; + tDescriptor = "Ljava/lang/Object;"; + t = new IntermediateGenericType("T"); + + sExtendsStringSignature = "TS;"; + sExtendsStringDescriptor = "Ljava/lang/String;"; + sExtendsString = new IntermediateGenericType("S", + new IntermediateRefType(new JavaClassName(Type.getInternalName(String.class)))); + + rExtendsSSignature = "TR;"; + rExtendsSDescriptor = sExtendsStringDescriptor; + rExtendsS = new IntermediateGenericType("R", sExtendsString); } + + @Test + public void SignatureTest_T(){ assertEquals(tSignature, t.getSignature()); } + + @Test + public void DescriptorTest_T(){ assertEquals(tDescriptor, t.getDescriptor()); } + + @Test + public void SignatureTest_TExtendsString(){ assertEquals(sExtendsStringSignature, sExtendsString.getSignature()); } + + @Test + public void DescriptorTest_TExtendsString(){ assertEquals(sExtendsStringDescriptor, sExtendsString.getDescriptor()); } + + @Test + public void SignatureTest_TExtendsS(){ assertEquals(rExtendsSSignature, rExtendsS.getSignature()); } + + @Test + public void DescriptorTest_TExtendsS(){ assertEquals(rExtendsSDescriptor, rExtendsS.getDescriptor()); } } diff --git a/src/test/java/intermediate/types/IntermediateRefTypeTest.java b/src/test/java/intermediate/types/IntermediateRefTypeTest.java index b9cfa6d0..b03a988e 100644 --- a/src/test/java/intermediate/types/IntermediateRefTypeTest.java +++ b/src/test/java/intermediate/types/IntermediateRefTypeTest.java @@ -20,7 +20,7 @@ public class IntermediateRefTypeTest { private static String listOfIntegerSignature; private static String listOfIntegerDescriptor; - private static IntermediateRefType typeToTest_ListofInteger; + private static IntermediateRefType typeToTest_ListOfInteger; private static String voidSignature; private static String voidDescriptor; @@ -34,7 +34,7 @@ public class IntermediateRefTypeTest { listOfIntegerSignature = "Ljava/util/List;"; listOfIntegerDescriptor = "Ljava/util/List;"; - typeToTest_ListofInteger = new IntermediateRefType( + typeToTest_ListOfInteger = new IntermediateRefType( new JavaClassName(Type.getInternalName(List.class)), Arrays.asList(typeToTest_Integer)); @@ -54,10 +54,10 @@ public class IntermediateRefTypeTest { } @Test - public void SignatureTest_List(){ assertEquals(listOfIntegerSignature, typeToTest_ListofInteger.getSignature()); } + public void SignatureTest_List(){ assertEquals(listOfIntegerSignature, typeToTest_ListOfInteger.getSignature()); } @Test - public void DescriptorTest_List(){ assertEquals(listOfIntegerDescriptor, typeToTest_ListofInteger.getDescriptor()); } + public void DescriptorTest_List(){ assertEquals(listOfIntegerDescriptor, typeToTest_ListOfInteger.getDescriptor()); } @Test public void SignatureTest_Void(){ From f1f028f0b92214b423bd69a5811758823e2b4ff7 Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Sun, 20 Mar 2022 16:42:12 +0100 Subject: [PATCH 15/69] =?UTF-8?q?Hinzuf=C3=BCgen=20von=20equals()=20und=20?= =?UTF-8?q?hashCode()=20Tests=20zu=20IntermediateRefTypeTest=20und=20Inter?= =?UTF-8?q?mediateGenericTypeTest.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../types/IntermediateInnerType.java | 1 - .../types/IntermediateGenericTypeTest.java | 17 +++++++++++++++++ .../types/IntermediateRefTypeTest.java | 19 +++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateInnerType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateInnerType.java index a83c974f..f10fe157 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateInnerType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateInnerType.java @@ -4,6 +4,5 @@ package de.dhbwstuttgart.intermediate.types; * Only Java types which can be used as an inner type, have a descriptor definition. */ public abstract class IntermediateInnerType extends IntermediateType { - public abstract String getDescriptor(); } diff --git a/src/test/java/intermediate/types/IntermediateGenericTypeTest.java b/src/test/java/intermediate/types/IntermediateGenericTypeTest.java index 3663faae..3c711c4e 100644 --- a/src/test/java/intermediate/types/IntermediateGenericTypeTest.java +++ b/src/test/java/intermediate/types/IntermediateGenericTypeTest.java @@ -8,6 +8,7 @@ import org.junit.Test; import org.objectweb.asm.Type; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; public class IntermediateGenericTypeTest { @@ -23,6 +24,8 @@ public class IntermediateGenericTypeTest { private static String rExtendsSDescriptor; private static IntermediateGenericType rExtendsS; + private static IntermediateGenericType rSame; + @BeforeClass public static void StartUp(){ tSignature = "TT;"; @@ -37,6 +40,8 @@ public class IntermediateGenericTypeTest { rExtendsSSignature = "TR;"; rExtendsSDescriptor = sExtendsStringDescriptor; rExtendsS = new IntermediateGenericType("R", sExtendsString); + + rSame = new IntermediateGenericType("R", sExtendsString); } @Test @@ -56,4 +61,16 @@ public class IntermediateGenericTypeTest { @Test public void DescriptorTest_TExtendsS(){ assertEquals(rExtendsSDescriptor, rExtendsS.getDescriptor()); } + + @Test + public void HashCodeTest_Succeed() { assertEquals(rSame.hashCode(), rExtendsS.hashCode());} + + @Test + public void HashCodeTest_Fail() { assertNotEquals(rSame.hashCode(), t.hashCode()); } + + @Test + public void EqualsTest_Succeed() { assertEquals(rSame, rExtendsS); } + + @Test + public void EqualsTest_Fail() { assertNotEquals(rSame, t); } } diff --git a/src/test/java/intermediate/types/IntermediateRefTypeTest.java b/src/test/java/intermediate/types/IntermediateRefTypeTest.java index b03a988e..bc287a78 100644 --- a/src/test/java/intermediate/types/IntermediateRefTypeTest.java +++ b/src/test/java/intermediate/types/IntermediateRefTypeTest.java @@ -11,6 +11,7 @@ import java.util.Arrays; import java.util.List; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; public class IntermediateRefTypeTest { @@ -26,6 +27,8 @@ public class IntermediateRefTypeTest { private static String voidDescriptor; private static IntermediateRefType typeToTest_void; + private static IntermediateRefType typeToTest_ListOfIntegerSame; + @BeforeClass public static void StartUp(){ integerSignature = "Ljava/lang/Integer;"; @@ -41,6 +44,10 @@ public class IntermediateRefTypeTest { voidSignature = "V"; voidDescriptor = "V"; typeToTest_void = new IntermediateRefType(new JavaClassName("void")); + + typeToTest_ListOfIntegerSame = new IntermediateRefType( + new JavaClassName(Type.getInternalName(List.class)), + Arrays.asList(typeToTest_Integer)); } @Test @@ -68,4 +75,16 @@ public class IntermediateRefTypeTest { public void DescriptorTest_Void(){ assertEquals(voidDescriptor, typeToTest_void.getDescriptor()); } + + @Test + public void HashCodeTest_Succeed() { assertEquals(typeToTest_ListOfIntegerSame.hashCode(), typeToTest_ListOfInteger.hashCode());} + + @Test + public void HashCodeTest_Fail() { assertNotEquals(typeToTest_ListOfIntegerSame.hashCode(), typeToTest_Integer.hashCode()); } + + @Test + public void EqualsTest_Succeed() { assertEquals(typeToTest_ListOfIntegerSame, typeToTest_ListOfInteger); } + + @Test + public void EqualsTest_Fail() { assertNotEquals(typeToTest_ListOfIntegerSame, typeToTest_Integer); } } From 0207c7d1b0f57da02be6fadd1b6c217928bbadc1 Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Sun, 20 Mar 2022 16:59:24 +0100 Subject: [PATCH 16/69] =?UTF-8?q?Verbesserung=20typParameter=20von=20Inter?= =?UTF-8?q?mediateRefType:=20K=C3=B6nnen=20IntermediateInnerType=20sein!?= =?UTF-8?q?=20Nicht=20nur=20IntermediateRefType=20wie=20zuvor.=20Hizuf?= =?UTF-8?q?=C3=BCgen=20entsprechender=20Tests.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../intermediate/types/IntermediateRefType.java | 4 ++-- .../types/IntermediateGenericTypeTest.java | 9 +++++++-- .../types/IntermediateRefTypeTest.java | 17 +++++++++++++++++ 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java index 81ef371a..d82bbb71 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java @@ -13,7 +13,7 @@ import java.util.List; */ public final class IntermediateRefType extends IntermediateInnerType{ - private final List typParameters; + private final List typParameters; private final JavaClassName className; /** @@ -35,7 +35,7 @@ public final class IntermediateRefType extends IntermediateInnerType{ this(className, new ArrayList<>()); } - public IntermediateRefType(JavaClassName className, List typParameters){ + public IntermediateRefType(JavaClassName className, List typParameters){ this.className = className; this.typParameters = Collections.unmodifiableList(typParameters); } diff --git a/src/test/java/intermediate/types/IntermediateGenericTypeTest.java b/src/test/java/intermediate/types/IntermediateGenericTypeTest.java index 3c711c4e..5ab67f3e 100644 --- a/src/test/java/intermediate/types/IntermediateGenericTypeTest.java +++ b/src/test/java/intermediate/types/IntermediateGenericTypeTest.java @@ -7,6 +7,10 @@ import org.junit.BeforeClass; import org.junit.Test; import org.objectweb.asm.Type; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; @@ -33,9 +37,10 @@ public class IntermediateGenericTypeTest { t = new IntermediateGenericType("T"); sExtendsStringSignature = "TS;"; - sExtendsStringDescriptor = "Ljava/lang/String;"; + sExtendsStringDescriptor = "Ljava/util/List;"; sExtendsString = new IntermediateGenericType("S", - new IntermediateRefType(new JavaClassName(Type.getInternalName(String.class)))); + new IntermediateRefType(new JavaClassName(Type.getInternalName(List.class)), + Arrays.asList(new IntermediateRefType(new JavaClassName(Type.getInternalName(Integer.class)))))); rExtendsSSignature = "TR;"; rExtendsSDescriptor = sExtendsStringDescriptor; diff --git a/src/test/java/intermediate/types/IntermediateRefTypeTest.java b/src/test/java/intermediate/types/IntermediateRefTypeTest.java index bc287a78..fdcca7e2 100644 --- a/src/test/java/intermediate/types/IntermediateRefTypeTest.java +++ b/src/test/java/intermediate/types/IntermediateRefTypeTest.java @@ -1,5 +1,6 @@ package intermediate.types; +import de.dhbwstuttgart.intermediate.types.IntermediateGenericType; import de.dhbwstuttgart.intermediate.types.IntermediateRefType; import de.dhbwstuttgart.parser.scope.JavaClassName; @@ -23,6 +24,10 @@ public class IntermediateRefTypeTest { private static String listOfIntegerDescriptor; private static IntermediateRefType typeToTest_ListOfInteger; + private static String listOfTSignature; + private static String listOfTDescriptor; + private static IntermediateRefType typeToTest_ListOfT; + private static String voidSignature; private static String voidDescriptor; private static IntermediateRefType typeToTest_void; @@ -41,6 +46,12 @@ public class IntermediateRefTypeTest { new JavaClassName(Type.getInternalName(List.class)), Arrays.asList(typeToTest_Integer)); + listOfTSignature = "Ljava/util/List;"; + listOfTDescriptor = "Ljava/util/List;"; + typeToTest_ListOfT = new IntermediateRefType( + new JavaClassName(Type.getInternalName(List.class)), + Arrays.asList(new IntermediateGenericType("T"))); + voidSignature = "V"; voidDescriptor = "V"; typeToTest_void = new IntermediateRefType(new JavaClassName("void")); @@ -66,6 +77,12 @@ public class IntermediateRefTypeTest { @Test public void DescriptorTest_List(){ assertEquals(listOfIntegerDescriptor, typeToTest_ListOfInteger.getDescriptor()); } + @Test + public void SignatureTest_ListT(){ assertEquals(listOfTSignature, typeToTest_ListOfT.getSignature()); } + + @Test + public void DescriptorTest_ListT(){ assertEquals(listOfTDescriptor, typeToTest_ListOfT.getDescriptor()); } + @Test public void SignatureTest_Void(){ assertEquals(voidSignature, typeToTest_void.getSignature()); From 0d84e8361fb25d7f8440bf28e822474e54a0cbd7 Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Sun, 20 Mar 2022 20:38:54 +0100 Subject: [PATCH 17/69] =?UTF-8?q?Hinzuf=C3=BCgen=20von=20IntermediateWildc?= =?UTF-8?q?ard=20und=20dessen=20Tests.=20Hinzuf=C3=BCgen=20der=20Tests=20f?= =?UTF-8?q?=C3=BCr=20IntermediateSuperWildcard=20und=20IntermediateExtends?= =?UTF-8?q?Wildcard.=20Verbesserung=20von=20IntermediateRefType:=20typPara?= =?UTF-8?q?meter=20k=C3=B6nnen=20IntermediateType=20sein=20und=20nicht=20n?= =?UTF-8?q?ur=20IntermediateInnerType.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../types/IntermediateExtendsWildcard.java | 2 - .../types/IntermediateRefType.java | 4 +- .../types/IntermediateSuperWildcard.java | 2 - .../types/IntermediateWildcard.java | 33 +++++++++++ .../types/IntermediateExtensWildcardTest.java | 59 +++++++++++++++++-- .../types/IntermediateGenericTypeTest.java | 1 - .../types/IntermediateSuperWildcardTest.java | 59 +++++++++++++++++-- .../types/IntermediateWildcardTest.java | 57 ++++++++++++++++++ 8 files changed, 202 insertions(+), 15 deletions(-) create mode 100644 src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateWildcard.java create mode 100644 src/test/java/intermediate/types/IntermediateWildcardTest.java diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateExtendsWildcard.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateExtendsWildcard.java index d1be0aeb..0bfde0ec 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateExtendsWildcard.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateExtendsWildcard.java @@ -1,7 +1,5 @@ package de.dhbwstuttgart.intermediate.types; -import de.dhbwstuttgart.parser.scope.JavaClassName; - /** * Represents a Java Wildcard with a extends-operator. * E.g. {@code <? extends String>} diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java index d82bbb71..8c3c541f 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java @@ -13,7 +13,7 @@ import java.util.List; */ public final class IntermediateRefType extends IntermediateInnerType{ - private final List typParameters; + private final List typParameters; private final JavaClassName className; /** @@ -35,7 +35,7 @@ public final class IntermediateRefType extends IntermediateInnerType{ this(className, new ArrayList<>()); } - public IntermediateRefType(JavaClassName className, List typParameters){ + public IntermediateRefType(JavaClassName className, List typParameters){ this.className = className; this.typParameters = Collections.unmodifiableList(typParameters); } diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateSuperWildcard.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateSuperWildcard.java index 2e806828..33b8cf80 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateSuperWildcard.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateSuperWildcard.java @@ -1,7 +1,5 @@ package de.dhbwstuttgart.intermediate.types; -import de.dhbwstuttgart.parser.scope.JavaClassName; - /** * Represents a Java Wildcard with a super-operator. * E.g. {@code <? super String>} diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateWildcard.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateWildcard.java new file mode 100644 index 00000000..28972776 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateWildcard.java @@ -0,0 +1,33 @@ +package de.dhbwstuttgart.intermediate.types; + +/** + * Represents a Java wildcard {@code <?>}. + * + * @since Studienarbeit Type Erasure + * @author etiennezink + */ +public class IntermediateWildcard extends IntermediateType{ + + /** + * Caches the hashCode after first computation. + */ + private int hashCode; + + @Override + public boolean equals(Object o) { return o instanceof IntermediateWildcard; } + + @Override + public int hashCode() { + int prime = 31; + int hashCode = this.hashCode; + if (hashCode == 0){ + hashCode += "wildcard".hashCode(); + hashCode = prime * hashCode + "*".hashCode(); + this.hashCode = hashCode; + } + return hashCode; + } + + @Override + public String getSignature() { return "*"; } +} diff --git a/src/test/java/intermediate/types/IntermediateExtensWildcardTest.java b/src/test/java/intermediate/types/IntermediateExtensWildcardTest.java index d82e7baf..f097310a 100644 --- a/src/test/java/intermediate/types/IntermediateExtensWildcardTest.java +++ b/src/test/java/intermediate/types/IntermediateExtensWildcardTest.java @@ -1,11 +1,62 @@ package intermediate.types; -import org.junit.Assert; +import de.dhbwstuttgart.intermediate.types.IntermediateExtendsWildcard; +import de.dhbwstuttgart.intermediate.types.IntermediateGenericType; +import de.dhbwstuttgart.intermediate.types.IntermediateRefType; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import org.junit.BeforeClass; import org.junit.Test; +import org.objectweb.asm.Type; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; public class IntermediateExtensWildcardTest { - @Test - public void ToDo(){ - Assert.fail(); + + private static String integerWildcardSignature; + private static IntermediateRefType integerWildcard; + + private static String tWildcardSignature; + private static IntermediateRefType tWildcard; + + private static IntermediateRefType tWildcardSame; + + @BeforeClass + public static void StartUp(){ + + integerWildcardSignature = "Ljava/util/List<+Ljava/lang/Integer;>;"; + integerWildcard = new IntermediateRefType( + new JavaClassName(Type.getInternalName(List.class)), + Arrays.asList(new IntermediateExtendsWildcard(new IntermediateRefType(new JavaClassName(Type.getInternalName(Integer.class)))))); + + tWildcardSignature = "Ljava/util/List<+TT;>;"; + tWildcard = new IntermediateRefType( + new JavaClassName(Type.getInternalName(List.class)), + Arrays.asList(new IntermediateExtendsWildcard(new IntermediateGenericType("T")))); + + tWildcardSame = new IntermediateRefType( + new JavaClassName(Type.getInternalName(List.class)), + Arrays.asList(new IntermediateExtendsWildcard(new IntermediateGenericType("T")))); } + + @Test + public void SignatureTest_Integer(){ assertEquals(integerWildcardSignature, integerWildcard.getSignature()); } + + @Test + public void SignatureTest_T(){ assertEquals(tWildcardSignature, tWildcard.getSignature()); } + + @Test + public void HashCodeTest_Succeed() { assertEquals(tWildcardSame.hashCode(), tWildcard.hashCode());} + + @Test + public void HashCodeTest_Fail() { assertNotEquals(tWildcardSame.hashCode(), integerWildcard.hashCode()); } + + @Test + public void EqualsTest_Succeed() { assertEquals(tWildcardSame, tWildcard); } + + @Test + public void EqualsTest_Fail() { assertNotEquals(tWildcardSame, integerWildcard); } } diff --git a/src/test/java/intermediate/types/IntermediateGenericTypeTest.java b/src/test/java/intermediate/types/IntermediateGenericTypeTest.java index 5ab67f3e..f680e5c3 100644 --- a/src/test/java/intermediate/types/IntermediateGenericTypeTest.java +++ b/src/test/java/intermediate/types/IntermediateGenericTypeTest.java @@ -8,7 +8,6 @@ import org.junit.Test; import org.objectweb.asm.Type; import java.util.Arrays; -import java.util.Collections; import java.util.List; import static org.junit.Assert.assertEquals; diff --git a/src/test/java/intermediate/types/IntermediateSuperWildcardTest.java b/src/test/java/intermediate/types/IntermediateSuperWildcardTest.java index 7ba44c31..4571ddf5 100644 --- a/src/test/java/intermediate/types/IntermediateSuperWildcardTest.java +++ b/src/test/java/intermediate/types/IntermediateSuperWildcardTest.java @@ -1,11 +1,62 @@ package intermediate.types; -import org.junit.Assert; +import de.dhbwstuttgart.intermediate.types.IntermediateGenericType; +import de.dhbwstuttgart.intermediate.types.IntermediateRefType; +import de.dhbwstuttgart.intermediate.types.IntermediateSuperWildcard; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import org.junit.BeforeClass; import org.junit.Test; +import org.objectweb.asm.Type; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; public class IntermediateSuperWildcardTest { - @Test - public void ToDo(){ - Assert.fail(); + + private static String integerWildcardSignature; + private static IntermediateRefType integerWildcard; + + private static String tWildcardSignature; + private static IntermediateRefType tWildcard; + + private static IntermediateRefType tWildcardSame; + + @BeforeClass + public static void StartUp(){ + + integerWildcardSignature = "Ljava/util/List<-Ljava/lang/Integer;>;"; + integerWildcard = new IntermediateRefType( + new JavaClassName(Type.getInternalName(List.class)), + Arrays.asList(new IntermediateSuperWildcard(new IntermediateRefType(new JavaClassName(Type.getInternalName(Integer.class)))))); + + tWildcardSignature = "Ljava/util/List<-TT;>;"; + tWildcard = new IntermediateRefType( + new JavaClassName(Type.getInternalName(List.class)), + Arrays.asList(new IntermediateSuperWildcard(new IntermediateGenericType("T")))); + + tWildcardSame = new IntermediateRefType( + new JavaClassName(Type.getInternalName(List.class)), + Arrays.asList(new IntermediateSuperWildcard(new IntermediateGenericType("T")))); } + + @Test + public void SignatureTest_Integer(){ assertEquals(integerWildcardSignature, integerWildcard.getSignature()); } + + @Test + public void SignatureTest_T(){ assertEquals(tWildcardSignature, tWildcard.getSignature()); } + + @Test + public void HashCodeTest_Succeed() { assertEquals(tWildcardSame.hashCode(), tWildcard.hashCode());} + + @Test + public void HashCodeTest_Fail() { assertNotEquals(tWildcardSame.hashCode(), integerWildcard.hashCode()); } + + @Test + public void EqualsTest_Succeed() { assertEquals(tWildcardSame, tWildcard); } + + @Test + public void EqualsTest_Fail() { assertNotEquals(tWildcardSame, integerWildcard); } } diff --git a/src/test/java/intermediate/types/IntermediateWildcardTest.java b/src/test/java/intermediate/types/IntermediateWildcardTest.java new file mode 100644 index 00000000..b804d9e9 --- /dev/null +++ b/src/test/java/intermediate/types/IntermediateWildcardTest.java @@ -0,0 +1,57 @@ +package intermediate.types; + +import de.dhbwstuttgart.intermediate.types.IntermediateExtendsWildcard; +import de.dhbwstuttgart.intermediate.types.IntermediateGenericType; +import de.dhbwstuttgart.intermediate.types.IntermediateRefType; +import de.dhbwstuttgart.intermediate.types.IntermediateWildcard; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import org.junit.BeforeClass; +import org.junit.Test; +import org.objectweb.asm.Type; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +public class IntermediateWildcardTest { + + private static String wildcardSignature; + private static IntermediateRefType wildcard; + + private static IntermediateRefType wildcardSame; + private static IntermediateRefType tWildcard; + + @BeforeClass + public static void StartUp(){ + + wildcardSignature = "Ljava/util/List<*>;"; + wildcard = new IntermediateRefType( + new JavaClassName(Type.getInternalName(List.class)), + Arrays.asList(new IntermediateWildcard())); + + wildcardSame = new IntermediateRefType( + new JavaClassName(Type.getInternalName(List.class)), + Arrays.asList(new IntermediateWildcard())); + + tWildcard = new IntermediateRefType( + new JavaClassName(Type.getInternalName(List.class)), + Arrays.asList(new IntermediateExtendsWildcard(new IntermediateGenericType("T")))); + } + + @Test + public void SignatureTest_Wildcard(){ assertEquals(wildcardSignature, wildcard.getSignature()); } + + @Test + public void HashCodeTest_Succeed() { assertEquals(wildcardSame.hashCode(), wildcard.hashCode());} + + @Test + public void HashCodeTest_Fail() { assertNotEquals(wildcardSame.hashCode(), tWildcard.hashCode()); } + + @Test + public void EqualsTest_Succeed() { assertEquals(wildcardSame, wildcard); } + + @Test + public void EqualsTest_Fail() { assertNotEquals(wildcardSame, tWildcard); } +} From ac1e0340c3516fd6a1880b40fbd3519cffdeab3b Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Sun, 20 Mar 2022 22:25:55 +0100 Subject: [PATCH 18/69] =?UTF-8?q?Hinzuf=C3=BCgen=20von=20FunN=20zur=20Gene?= =?UTF-8?q?rierung=20von=20echten=20Funktionstypen.=20FunN=20ist=20Subtyp?= =?UTF-8?q?=20von=20IntermediateRefType.=20Hinzuf=C3=BCgen=20erster=20FunN?= =?UTF-8?q?Tests.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../intermediate/generation/FunN.java | 69 +++++++++++++++++++ .../types/IntermediateRefType.java | 30 ++++---- .../types/IntermediateWildcard.java | 2 +- .../intermediate/generation/FunNTest.java | 35 ++++++++++ 4 files changed, 120 insertions(+), 16 deletions(-) create mode 100644 src/main/java/de/dhbwstuttgart/intermediate/generation/FunN.java create mode 100644 src/test/java/intermediate/generation/FunNTest.java diff --git a/src/main/java/de/dhbwstuttgart/intermediate/generation/FunN.java b/src/main/java/de/dhbwstuttgart/intermediate/generation/FunN.java new file mode 100644 index 00000000..fc55efcb --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/intermediate/generation/FunN.java @@ -0,0 +1,69 @@ +package de.dhbwstuttgart.intermediate.generation; + +import de.dhbwstuttgart.intermediate.types.IntermediateRefType; +import de.dhbwstuttgart.intermediate.types.IntermediateType; +import de.dhbwstuttgart.parser.scope.JavaClassName; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Class which represents a function type. + * Offers different methods to generate or interact with this real function type. + * + * @since Studienarbeit Type Erasure + * @author etiennezink + */ +public final class FunN extends IntermediateRefType { + + /** + * Caches the bytecode after first computation. + */ + private byte[] bytecode; + + /** + * Caches the superBytecode after first computation. + */ + private byte[] superBytecode; + + public FunN(List typArguments, IntermediateType returnType) { + super(new JavaClassName( + String.format("Fun%d$$%s%s", + typArguments.size(), + typArguments + .stream() + .map(IntermediateType::getSignature) + .collect(Collectors.joining()), + returnType.getSignature()) + .replace('/', '$') + .replace(";", "$_$")), + Stream.concat(typArguments.stream(), Stream.of(returnType)).collect(Collectors.toList())); + } + + /** + * @return the bytecode for the super FunN type + */ + public byte[] getSuperBytecode(){ + byte[] superBytecode = this.superBytecode; + if (superBytecode == null){ + //ToDo + this.superBytecode = superBytecode; + } + return superBytecode; + } + + /** + * Generates the bytecode for this FunN type. + * Make sure to generate the bytecode for the super FunN as well. + * @return the bytecode for this explicit FunN type + */ + public byte[] getBytecode(){ + byte[] bytecode = this.bytecode; + if (bytecode == null){ + //ToDo + this.bytecode = bytecode; + } + return bytecode; + } +} diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java index 8c3c541f..eea0ff80 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java @@ -11,9 +11,9 @@ import java.util.List; * @since Studienarbeit Type Erasure * @author etiennezink */ -public final class IntermediateRefType extends IntermediateInnerType{ +public class IntermediateRefType extends IntermediateInnerType{ - private final List typParameters; + private final List typArguments; private final JavaClassName className; /** @@ -35,9 +35,9 @@ public final class IntermediateRefType extends IntermediateInnerType{ this(className, new ArrayList<>()); } - public IntermediateRefType(JavaClassName className, List typParameters){ + public IntermediateRefType(JavaClassName className, List typArguments){ this.className = className; - this.typParameters = Collections.unmodifiableList(typParameters); + this.typArguments = Collections.unmodifiableList(typArguments); } @Override @@ -47,8 +47,8 @@ public final class IntermediateRefType extends IntermediateInnerType{ IntermediateRefType intermediateRefType = (IntermediateRefType) o; if(!getFullyQualifiedName().equals(intermediateRefType.getFullyQualifiedName())) return false; - for(int index = 0; index < typParameters.size(); index++){ - if(!typParameters.get(index).equals(intermediateRefType.typParameters.get(index))) return false; + for(int index = 0; index < typArguments.size(); index++){ + if(!typArguments.get(index).equals(intermediateRefType.typArguments.get(index))) return false; } return true; } @@ -59,8 +59,8 @@ public final class IntermediateRefType extends IntermediateInnerType{ int hashCode = this.hashCode; if (hashCode == 0){ hashCode += getFullyQualifiedName().hashCode(); - for (IntermediateType typeParameter:typParameters) { - hashCode = prime * hashCode + typeParameter.hashCode(); + for (IntermediateType typeArgument: typArguments) { + hashCode = prime * hashCode + typeArgument.hashCode(); } this.hashCode = hashCode; } @@ -75,10 +75,10 @@ public final class IntermediateRefType extends IntermediateInnerType{ if (className.getClassName().equals("void")) signature = "V"; else { signature += String.format("L%s", getFullyQualifiedName()); - if (typParameters.size() != 0){ + if (typArguments.size() != 0){ signature += "<"; - for (IntermediateType typParameter:typParameters) { - signature += typParameter.getSignature(); + for (IntermediateType typArgument: typArguments) { + signature += typArgument.getSignature(); } signature += ">"; } @@ -98,17 +98,17 @@ public final class IntermediateRefType extends IntermediateInnerType{ return descriptor; } - public boolean isParametrized() { return typParameters.size() > 0; } + public boolean isParametrized() { return typArguments.size() > 0; } - public int getTypParameterSize(){ return typParameters.size(); } + public int getTypParameterSize(){ return typArguments.size(); } /** * @param index * @return the typ parameter at {@code index} or {@code null}, iff {@code |typ parameters| < index} */ public IntermediateType getTypParameter(int index) { - if(typParameters.size() < index) return null; - return typParameters.get(index); + if(typArguments.size() < index) return null; + return typArguments.get(index); } private String getFullyQualifiedName(){ return className.toString(); } diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateWildcard.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateWildcard.java index 28972776..92020d10 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateWildcard.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateWildcard.java @@ -6,7 +6,7 @@ package de.dhbwstuttgart.intermediate.types; * @since Studienarbeit Type Erasure * @author etiennezink */ -public class IntermediateWildcard extends IntermediateType{ +public final class IntermediateWildcard extends IntermediateType{ /** * Caches the hashCode after first computation. diff --git a/src/test/java/intermediate/generation/FunNTest.java b/src/test/java/intermediate/generation/FunNTest.java new file mode 100644 index 00000000..c244ae5a --- /dev/null +++ b/src/test/java/intermediate/generation/FunNTest.java @@ -0,0 +1,35 @@ +package intermediate.generation; + +import de.dhbwstuttgart.intermediate.generation.FunN; +import de.dhbwstuttgart.intermediate.types.IntermediateRefType; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import org.junit.BeforeClass; +import org.junit.Test; +import org.objectweb.asm.Type; + +import java.util.Arrays; + +import static org.junit.Assert.assertEquals; + +public class FunNTest { + private static String fun1IntIntSignature; + private static String fun1IntIntDescriptor; + private static FunN fun1IntInt; + + //ToDo mehr Tests und Bytecode Tests + + @BeforeClass + public static void SetUp(){ + IntermediateRefType integer = new IntermediateRefType(new JavaClassName(Type.getInternalName(Integer.class))); + + fun1IntIntSignature = "LFun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$;"; + fun1IntIntDescriptor = "LFun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$;"; + fun1IntInt = new FunN(Arrays.asList(integer), integer); + } + + @Test + public void SignatureTest_Fun1IntegerInteger(){ assertEquals(fun1IntIntSignature, fun1IntInt.getSignature()); } + + @Test + public void DescriptorTest_Fun1IntegerInteger(){ assertEquals(fun1IntIntDescriptor, fun1IntInt.getDescriptor()); } +} From 918a2cc04dce8861cdc549a672ded0a5997689d7 Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Mon, 21 Mar 2022 08:42:50 +0100 Subject: [PATCH 19/69] =?UTF-8?q?Implementierung=20in=20FunN=20von=20getSu?= =?UTF-8?q?perBytecode()=20und=20Hinzuf=C3=BCgen=20entsprechender=20Test.?= =?UTF-8?q?=20Umbenennung=20in=20IntermediateRefType:=20getTypParameter()?= =?UTF-8?q?=20->=20getTypArgument()=20und=20getTypParameterSize()=20->=20g?= =?UTF-8?q?etTypArgumentSize().?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../intermediate/generation/FunN.java | 48 +++++++++++++++-- .../types/IntermediateRefType.java | 12 ++--- .../intermediate/generation/FunNTest.java | 54 +++++++++++++++++++ 3 files changed, 103 insertions(+), 11 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/intermediate/generation/FunN.java b/src/main/java/de/dhbwstuttgart/intermediate/generation/FunN.java index fc55efcb..0312de3a 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/generation/FunN.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/generation/FunN.java @@ -1,13 +1,20 @@ package de.dhbwstuttgart.intermediate.generation; +import de.dhbwstuttgart.intermediate.types.IntermediateGenericType; import de.dhbwstuttgart.intermediate.types.IntermediateRefType; import de.dhbwstuttgart.intermediate.types.IntermediateType; import de.dhbwstuttgart.parser.scope.JavaClassName; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Type; +import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; +import static org.objectweb.asm.Opcodes.*; + /** * Class which represents a function type. * Offers different methods to generate or interact with this real function type. @@ -17,16 +24,23 @@ import java.util.stream.Stream; */ public final class FunN extends IntermediateRefType { - /** - * Caches the bytecode after first computation. - */ - private byte[] bytecode; + private final String superFunNName; + private final String argumentGenericBase = "T"; + private final String returnGeneric = "R"; + private final String methodName = "apply"; /** * Caches the superBytecode after first computation. */ private byte[] superBytecode; + /** + * Caches the bytecode after first computation. + */ + private byte[] bytecode; + + public FunN(IntermediateType returnType){ this(Collections.emptyList(), returnType); } + public FunN(List typArguments, IntermediateType returnType) { super(new JavaClassName( String.format("Fun%d$$%s%s", @@ -39,6 +53,7 @@ public final class FunN extends IntermediateRefType { .replace('/', '$') .replace(";", "$_$")), Stream.concat(typArguments.stream(), Stream.of(returnType)).collect(Collectors.toList())); + superFunNName = String.format("Fun%d$$", typArguments.size()); } /** @@ -47,7 +62,30 @@ public final class FunN extends IntermediateRefType { public byte[] getSuperBytecode(){ byte[] superBytecode = this.superBytecode; if (superBytecode == null){ - //ToDo + String superType = Type.getInternalName(Object.class).replace('.','/'); + String objectSignature = new IntermediateRefType(new JavaClassName(Type.getInternalName(Object.class))).getSignature(); + + String superFunNClassSignature = "<"; + String superFunNMethodSignature = "("; + String superFunNMethodDescriptor = "("; + + //currentParameter < getTypArgumentSize() because the return type is stored in the typArguments as well + for (int currentParameter = 1; currentParameter < getTypArgumentSize(); currentParameter++){ + superFunNClassSignature += String.format("%s%d:%s",argumentGenericBase, currentParameter, objectSignature); + superFunNMethodSignature += new IntermediateGenericType(argumentGenericBase + currentParameter).getSignature(); + superFunNMethodDescriptor += objectSignature; + } + superFunNClassSignature += String.format("%s:%s>%s", returnGeneric, objectSignature, objectSignature); + superFunNMethodSignature += String.format(")%s", new IntermediateGenericType(returnGeneric).getSignature()); + superFunNMethodDescriptor += String.format(")%s", objectSignature); + + ClassWriter classWriter = new ClassWriter(0); + MethodVisitor methodVisitor; + classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, superFunNName, superFunNClassSignature, superType, null); + methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, methodName, superFunNMethodDescriptor, superFunNMethodSignature , null); + methodVisitor.visitEnd(); + classWriter.visitEnd(); + superBytecode = classWriter.toByteArray(); this.superBytecode = superBytecode; } return superBytecode; diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java index eea0ff80..be32f860 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java @@ -31,9 +31,7 @@ public class IntermediateRefType extends IntermediateInnerType{ */ private String descriptor = ""; - public IntermediateRefType(JavaClassName className) { - this(className, new ArrayList<>()); - } + public IntermediateRefType(JavaClassName className) { this(className, Collections.emptyList()); } public IntermediateRefType(JavaClassName className, List typArguments){ this.className = className; @@ -100,16 +98,18 @@ public class IntermediateRefType extends IntermediateInnerType{ public boolean isParametrized() { return typArguments.size() > 0; } - public int getTypParameterSize(){ return typArguments.size(); } + public int getTypArgumentSize(){ return typArguments.size(); } /** * @param index * @return the typ parameter at {@code index} or {@code null}, iff {@code |typ parameters| < index} */ - public IntermediateType getTypParameter(int index) { + public IntermediateType getTypArgument(int index) { if(typArguments.size() < index) return null; return typArguments.get(index); } - private String getFullyQualifiedName(){ return className.toString(); } + public String getClassName(){ return className.getClassName(); } + public String getPackageName(){ return className.getPackageName(); } + public String getFullyQualifiedName(){ return className.toString(); } } diff --git a/src/test/java/intermediate/generation/FunNTest.java b/src/test/java/intermediate/generation/FunNTest.java index c244ae5a..dba3f2a6 100644 --- a/src/test/java/intermediate/generation/FunNTest.java +++ b/src/test/java/intermediate/generation/FunNTest.java @@ -1,30 +1,45 @@ package intermediate.generation; import de.dhbwstuttgart.intermediate.generation.FunN; +import de.dhbwstuttgart.intermediate.types.IntermediateGenericType; import de.dhbwstuttgart.intermediate.types.IntermediateRefType; import de.dhbwstuttgart.parser.scope.JavaClassName; import org.junit.BeforeClass; import org.junit.Test; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Type; import java.util.Arrays; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import static org.objectweb.asm.Opcodes.*; public class FunNTest { + + private static FunN fun0T; + private static String fun1IntIntSignature; private static String fun1IntIntDescriptor; private static FunN fun1IntInt; + private static FunN fun2IntIntString; + //ToDo mehr Tests und Bytecode Tests @BeforeClass public static void SetUp(){ IntermediateRefType integer = new IntermediateRefType(new JavaClassName(Type.getInternalName(Integer.class))); + IntermediateRefType string = new IntermediateRefType(new JavaClassName(Type.getInternalName(String.class))); + + fun0T = new FunN(new IntermediateGenericType("T")); fun1IntIntSignature = "LFun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$;"; fun1IntIntDescriptor = "LFun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$;"; fun1IntInt = new FunN(Arrays.asList(integer), integer); + + fun2IntIntString = new FunN(Arrays.asList(integer, integer), string); } @Test @@ -32,4 +47,43 @@ public class FunNTest { @Test public void DescriptorTest_Fun1IntegerInteger(){ assertEquals(fun1IntIntDescriptor, fun1IntInt.getDescriptor()); } + + @Test + public void BytecodeTest_Super0(){ assertArrayEquals(generatedASMFun0(), fun0T.getSuperBytecode()) ;} + + @Test + public void BytecodeTest_Super1(){ assertArrayEquals(generatedASMFun1(), fun1IntInt.getSuperBytecode()) ;} + + @Test + public void BytecodeTest_Super2(){ assertArrayEquals(generatedASMFun2(), fun2IntIntString.getSuperBytecode()) ;} + + private byte[] generatedASMFun0() { + ClassWriter classWriter = new ClassWriter(0); + MethodVisitor methodVisitor; + classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "Fun0$$", "Ljava/lang/Object;", "java/lang/Object", null); + methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, "apply", "()Ljava/lang/Object;", "()TR;", null); + methodVisitor.visitEnd(); + classWriter.visitEnd(); + return classWriter.toByteArray(); + } + + private byte[] generatedASMFun1() { + ClassWriter classWriter = new ClassWriter(0); + MethodVisitor methodVisitor; + classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "Fun1$$", "Ljava/lang/Object;", "java/lang/Object", null); + methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, "apply", "(Ljava/lang/Object;)Ljava/lang/Object;", "(TT1;)TR;", null); + methodVisitor.visitEnd(); + classWriter.visitEnd(); + return classWriter.toByteArray(); + } + + private byte[] generatedASMFun2() { + ClassWriter classWriter = new ClassWriter(0); + MethodVisitor methodVisitor; + classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "Fun2$$", "Ljava/lang/Object;", "java/lang/Object", null); + methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, "apply", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", "(TT1;TT2;)TR;", null); + methodVisitor.visitEnd(); + classWriter.visitEnd(); + return classWriter.toByteArray(); + } } From 6381d0917416691a54be6b0bd24fa0d157d5fab9 Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Mon, 21 Mar 2022 11:29:37 +0100 Subject: [PATCH 20/69] =?UTF-8?q?Implementierung=20von=20getBytecode()=20i?= =?UTF-8?q?n=20FunN=20und=20Hinzuf=C3=BCgen=20entsprechender=20Tests.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../intermediate/generation/FunN.java | 45 +++++++++++++++---- .../intermediate/generation/FunNTest.java | 32 ++++++++++++- 2 files changed, 66 insertions(+), 11 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/intermediate/generation/FunN.java b/src/main/java/de/dhbwstuttgart/intermediate/generation/FunN.java index 0312de3a..1d60f46a 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/generation/FunN.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/generation/FunN.java @@ -1,6 +1,7 @@ package de.dhbwstuttgart.intermediate.generation; import de.dhbwstuttgart.intermediate.types.IntermediateGenericType; +import de.dhbwstuttgart.intermediate.types.IntermediateInnerType; import de.dhbwstuttgart.intermediate.types.IntermediateRefType; import de.dhbwstuttgart.intermediate.types.IntermediateType; import de.dhbwstuttgart.parser.scope.JavaClassName; @@ -24,10 +25,18 @@ import static org.objectweb.asm.Opcodes.*; */ public final class FunN extends IntermediateRefType { - private final String superFunNName; private final String argumentGenericBase = "T"; private final String returnGeneric = "R"; private final String methodName = "apply"; + private final int bytecodeVersion = V1_8; + + private final String objectSuperType = Type.getInternalName(Object.class).replace('.','/'); + private final String objectSignature = new IntermediateRefType(new JavaClassName(Type.getInternalName(Object.class))).getSignature(); + + /** + * Represents the super interface of this specialized function. + */ + private final IntermediateRefType superFunN; /** * Caches the superBytecode after first computation. @@ -39,9 +48,10 @@ public final class FunN extends IntermediateRefType { */ private byte[] bytecode; - public FunN(IntermediateType returnType){ this(Collections.emptyList(), returnType); } + public FunN(IntermediateInnerType returnType){ this(Collections.emptyList(), returnType); } - public FunN(List typArguments, IntermediateType returnType) { + public FunN(List typArguments, IntermediateInnerType returnType) { + //using stream-API for single line processing of relevant data in the super()-call super(new JavaClassName( String.format("Fun%d$$%s%s", typArguments.size(), @@ -53,7 +63,8 @@ public final class FunN extends IntermediateRefType { .replace('/', '$') .replace(";", "$_$")), Stream.concat(typArguments.stream(), Stream.of(returnType)).collect(Collectors.toList())); - superFunNName = String.format("Fun%d$$", typArguments.size()); + superFunN = new IntermediateRefType(new JavaClassName(String.format("Fun%d$$", typArguments.size())), + Stream.concat(typArguments.stream(), Stream.of(returnType)).collect(Collectors.toList())); } /** @@ -62,9 +73,6 @@ public final class FunN extends IntermediateRefType { public byte[] getSuperBytecode(){ byte[] superBytecode = this.superBytecode; if (superBytecode == null){ - String superType = Type.getInternalName(Object.class).replace('.','/'); - String objectSignature = new IntermediateRefType(new JavaClassName(Type.getInternalName(Object.class))).getSignature(); - String superFunNClassSignature = "<"; String superFunNMethodSignature = "("; String superFunNMethodDescriptor = "("; @@ -81,7 +89,7 @@ public final class FunN extends IntermediateRefType { ClassWriter classWriter = new ClassWriter(0); MethodVisitor methodVisitor; - classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, superFunNName, superFunNClassSignature, superType, null); + classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, superFunN.getClassName(), superFunNClassSignature, objectSuperType, null); methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, methodName, superFunNMethodDescriptor, superFunNMethodSignature , null); methodVisitor.visitEnd(); classWriter.visitEnd(); @@ -99,7 +107,26 @@ public final class FunN extends IntermediateRefType { public byte[] getBytecode(){ byte[] bytecode = this.bytecode; if (bytecode == null){ - //ToDo + String funNClassSignature = objectSignature + superFunN.getSignature(); + boolean containsGeneric = false; + + String genericSignature = "<"; + for (int currentTypArgumentIndex = 0; currentTypArgumentIndex < getTypArgumentSize(); currentTypArgumentIndex++) { + IntermediateType typArgument = getTypArgument(currentTypArgumentIndex); + if (typArgument == null) continue; + if (typArgument instanceof IntermediateGenericType){ + IntermediateGenericType generic = (IntermediateGenericType) typArgument; + genericSignature += String.format("%s:%s", generic.getGenericName(), generic.getDescriptor()); + containsGeneric = true; + } + } + genericSignature += ">"; + if (containsGeneric) funNClassSignature = genericSignature + funNClassSignature; + + ClassWriter classWriter = new ClassWriter(0); + classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, getClassName(), funNClassSignature, objectSuperType, new String[]{superFunN.getClassName()}); + classWriter.visitEnd(); + bytecode = classWriter.toByteArray(); this.bytecode = bytecode; } return bytecode; diff --git a/src/test/java/intermediate/generation/FunNTest.java b/src/test/java/intermediate/generation/FunNTest.java index dba3f2a6..d94595cd 100644 --- a/src/test/java/intermediate/generation/FunNTest.java +++ b/src/test/java/intermediate/generation/FunNTest.java @@ -26,8 +26,6 @@ public class FunNTest { private static FunN fun2IntIntString; - //ToDo mehr Tests und Bytecode Tests - @BeforeClass public static void SetUp(){ IntermediateRefType integer = new IntermediateRefType(new JavaClassName(Type.getInternalName(Integer.class))); @@ -51,12 +49,21 @@ public class FunNTest { @Test public void BytecodeTest_Super0(){ assertArrayEquals(generatedASMFun0(), fun0T.getSuperBytecode()) ;} + @Test + public void BytecodeTest_Fun0T(){ assertArrayEquals(generatedASMFun0T(), fun0T.getBytecode()) ;} + @Test public void BytecodeTest_Super1(){ assertArrayEquals(generatedASMFun1(), fun1IntInt.getSuperBytecode()) ;} + @Test + public void BytecodeTest_Fun1IntInt(){ assertArrayEquals(generatedASMFun1IntInt(), fun1IntInt.getBytecode()) ;} + @Test public void BytecodeTest_Super2(){ assertArrayEquals(generatedASMFun2(), fun2IntIntString.getSuperBytecode()) ;} + @Test + public void BytecodeTest_Fun2IntIntString(){ assertArrayEquals(generatedASMFun2IntIntString(), fun2IntIntString.getBytecode()) ;} + private byte[] generatedASMFun0() { ClassWriter classWriter = new ClassWriter(0); MethodVisitor methodVisitor; @@ -67,6 +74,13 @@ public class FunNTest { return classWriter.toByteArray(); } + private byte[] generatedASMFun0T() { + ClassWriter classWriter = new ClassWriter(0); + classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "Fun0$$TT$_$", "Ljava/lang/Object;LFun0$$;", "java/lang/Object", new String[]{"Fun0$$"}); + classWriter.visitEnd(); + return classWriter.toByteArray(); + } + private byte[] generatedASMFun1() { ClassWriter classWriter = new ClassWriter(0); MethodVisitor methodVisitor; @@ -77,6 +91,13 @@ public class FunNTest { return classWriter.toByteArray(); } + private byte[] generatedASMFun1IntInt() { + ClassWriter classWriter = new ClassWriter(0); + classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "Fun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$", "Ljava/lang/Object;LFun1$$;", "java/lang/Object", new String[]{"Fun1$$"}); + classWriter.visitEnd(); + return classWriter.toByteArray(); + } + private byte[] generatedASMFun2() { ClassWriter classWriter = new ClassWriter(0); MethodVisitor methodVisitor; @@ -86,4 +107,11 @@ public class FunNTest { classWriter.visitEnd(); return classWriter.toByteArray(); } + + private byte[] generatedASMFun2IntIntString() { + ClassWriter classWriter = new ClassWriter(0); + classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "Fun2$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$Ljava$lang$String$_$", "Ljava/lang/Object;LFun2$$;", "java/lang/Object", new String[]{"Fun2$$"}); + classWriter.visitEnd(); + return classWriter.toByteArray(); + } } From 21adeb7f26a4b16aa83dd57b3a57e33f35429883 Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Mon, 21 Mar 2022 17:15:03 +0100 Subject: [PATCH 21/69] Implementierung der von convert(..) in ASTToIntermediate. --- .../convert/ASTToIntermediate.java | 47 ++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java b/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java index 0673cbe2..f918c777 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java @@ -1,5 +1,50 @@ package de.dhbwstuttgart.intermediate.convert; +import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.intermediate.types.*; +import de.dhbwstuttgart.syntaxtree.type.*; + +import java.util.stream.Collectors; + public class ASTToIntermediate { - //ToDo + + public IntermediateRefType convert(RefType originalType){ + return new IntermediateRefType(originalType.getName(), + originalType + .getParaList() + .stream() + .map(this::convert) + .collect(Collectors.toList())); + } + + + //ToDo abklären: darf hier kein stehen? da hier kein Typparameter existiert + public IntermediateGenericType convert(GenericRefType originalType){ + //no typ argument for e.g. is present in the definition of GenericRefType + return new IntermediateGenericType(originalType.getParsedName()); + } + + public IntermediateSuperWildcard convert(SuperWildcardType originalType){ + IntermediateType innerType = convert(originalType.getInnerType()); + //throws RuntimeException, because only IntermediateInnerType (no wildcards) are allowed as inner types of wildcards + if (!(innerType instanceof IntermediateInnerType)) throw new RuntimeException("False inner type!"); + return new IntermediateSuperWildcard((IntermediateInnerType) innerType); + } + + public IntermediateExtendsWildcard convert(ExtendsWildcardType originalType){ + IntermediateType innerType = convert(originalType.getInnerType()); + //throws RuntimeException because only IntermediateInnerType (no wildcards) are allowed as inner types of wildcards + if (!(innerType instanceof IntermediateInnerType)) throw new RuntimeException("False inner type!"); + return new IntermediateExtendsWildcard((IntermediateInnerType) innerType); + } + + public IntermediateWildcard convert(){ + //thows RuntimeException because in the AST is no typ defined which represents a normal wildcard + throw new NotImplementedException("There is no conversion defined for this type."); + } + + public IntermediateRefType convert(RefTypeOrTPHOrWildcardOrGeneric originalType){ + //default implementation which shouldn't be called because of polymorphism + throw new NotImplementedException("There is no conversion defined for this type."); + } } From dc9a54be3b74dee160a7917af547bff6d086f168 Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Tue, 22 Mar 2022 20:42:16 +0100 Subject: [PATCH 22/69] =?UTF-8?q?Hinzuf=C3=BCgen=20der=20ersten=20Einbezie?= =?UTF-8?q?hung=20der=20API=20zur=20Generierung=20der=20spezialisierten=20?= =?UTF-8?q?FunN=20Typen,=20ohne=20Tests.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bytecode/BytecodeGenMethod.java | 20 ++++++++++++++++++- .../bytecode/descriptor/TypeToDescriptor.java | 4 ++++ .../bytecode/signature/TypeToSignature.java | 4 ++++ .../convert/ASTToIntermediate.java | 14 +++++++++++++ .../intermediate/generation/FunN.java | 17 ++++++++++++++++ 5 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index 0565d933..02a07fb8 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -13,10 +13,14 @@ import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.stream.Collectors; import de.dhbwstuttgart.bytecode.utilities.*; import de.dhbwstuttgart.environment.DirectoryClassLoader; import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.intermediate.convert.ASTToIntermediate; +import de.dhbwstuttgart.intermediate.generation.FunN; +import de.dhbwstuttgart.intermediate.types.IntermediateInnerType; import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.syntaxtree.statement.*; import de.dhbwstuttgart.syntaxtree.statement.BinaryExpr.Operator; @@ -814,7 +818,21 @@ public class BytecodeGenMethod implements StatementVisitor { } else if(!helper.isInCurrPkg(clazz)){ if(clazz.contains(CONSTANTS.$$)) { mDesc = helper.getDescriptorOfApplyMethod(methCallType); - helper.generateBCForFunN(mDesc); + //ToDo Etienne: check if it works + //helper.generateBCForFunN(mDesc); + ASTToIntermediate converter = new ASTToIntermediate(); + IntermediateInnerType returnType = converter.convert(methodCall.receiver.getType()); + List arguments = methodCall + .arglist + .getArguments() + .stream() + .map(TypableStatement::getType) + .map(converter::convert) + .collect(Collectors.toList());//ToDo + FunN f = new FunN(arguments, returnType); + FunN.writeClassFile(f.getSuperClassName(), f.getSuperBytecode(), path); + FunN.writeClassFile(f.getClassName(), f.getBytecode(), path); + //ToDo Etienne End // mDesc = helper.generateBCForFunN(methCallType,typesOfParams); }else { try { diff --git a/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java b/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java index aa3db5b1..613f672e 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java @@ -1,6 +1,7 @@ package de.dhbwstuttgart.bytecode.descriptor; import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.intermediate.convert.ASTToIntermediate; import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; import de.dhbwstuttgart.syntaxtree.type.GenericRefType; import de.dhbwstuttgart.syntaxtree.type.RefType; @@ -12,6 +13,9 @@ public class TypeToDescriptor implements TypeVisitor{ @Override public String visit(RefType refType) { + //ToDo Etienne: check if it works + if (refType.getName().toString().matches("Fun\\d+\\$\\$")) return new ASTToIntermediate().convert(refType).getDescriptor(); + return refType.getName().toString().replace(".", "/"); // String t = refType.getName().toString().replace(".", "/"); // return t.equals("Fun1")?(t+"$$"):t; diff --git a/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java b/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java index c8306f02..347d0d08 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java @@ -6,6 +6,7 @@ import java.util.List; import java.util.Optional; import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericsGeneratorResult; +import de.dhbwstuttgart.intermediate.convert.ASTToIntermediate; import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; import de.dhbwstuttgart.syntaxtree.type.GenericRefType; import de.dhbwstuttgart.syntaxtree.type.RefType; @@ -29,6 +30,9 @@ public class TypeToSignature implements TypeVisitor { public String visit(RefType refType) { if(refType.getName().toString().equals("void")) return "V"; + //ToDo Etienne: check if it works + if (refType.getName().toString().matches("Fun\\d+\\$\\$")) return new ASTToIntermediate().convert(refType).getSignature(); + // return refType.toString().replace(".", "/"); String params = ""; if(refType.getParaList().size()>0){ diff --git a/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java b/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java index f918c777..4e9ef6dc 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java @@ -1,14 +1,28 @@ package de.dhbwstuttgart.intermediate.convert; import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.intermediate.generation.FunN; import de.dhbwstuttgart.intermediate.types.*; import de.dhbwstuttgart.syntaxtree.type.*; +import java.util.List; import java.util.stream.Collectors; public class ASTToIntermediate { public IntermediateRefType convert(RefType originalType){ + //ToDo Etienne: check if it works + if (originalType.getName().toString().matches("Fun\\d+\\$\\$")){ + ASTToIntermediate converter = new ASTToIntermediate(); + List parameters = originalType.getParaList(); + IntermediateInnerType returnType = convert(parameters.get(parameters.size() - 1)); + parameters.remove(parameters.size() - 1); + return new FunN(parameters + .stream() + .map(this::convert) + .collect(Collectors.toList()), returnType); + } + return new IntermediateRefType(originalType.getName(), originalType .getParaList() diff --git a/src/main/java/de/dhbwstuttgart/intermediate/generation/FunN.java b/src/main/java/de/dhbwstuttgart/intermediate/generation/FunN.java index 1d60f46a..fc8119a0 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/generation/FunN.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/generation/FunN.java @@ -1,5 +1,6 @@ package de.dhbwstuttgart.intermediate.generation; +import de.dhbwstuttgart.bytecode.utilities.CONSTANTS; import de.dhbwstuttgart.intermediate.types.IntermediateGenericType; import de.dhbwstuttgart.intermediate.types.IntermediateInnerType; import de.dhbwstuttgart.intermediate.types.IntermediateRefType; @@ -9,6 +10,8 @@ import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Type; +import java.io.File; +import java.io.FileOutputStream; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -67,6 +70,8 @@ public final class FunN extends IntermediateRefType { Stream.concat(typArguments.stream(), Stream.of(returnType)).collect(Collectors.toList())); } + public String getSuperClassName() { return superFunN.getClassName(); } + /** * @return the bytecode for the super FunN type */ @@ -131,4 +136,16 @@ public final class FunN extends IntermediateRefType { } return bytecode; } + + //ToDo Etienne: Auslagern in andere Klasse; + public static boolean writeClassFile(String className, byte[] bytecode, File directory) { + try (FileOutputStream output = new FileOutputStream(new File(directory , className + CONSTANTS.EXTENSIONCLASS))){ + output.write(bytecode); + output.flush(); + return true; + } catch (Exception e) { + e.printStackTrace(); + } + return false; + } } From 15c05e5cba77b0bbdc6cf18c32e5cf5443cf03a0 Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Wed, 23 Mar 2022 16:12:25 +0100 Subject: [PATCH 23/69] =?UTF-8?q?Verbesserung=20der=20Konvertierung=20und?= =?UTF-8?q?=20der=20Bytecodegenerierung=20f=C3=BCr=20FunN=20Typen.=20Beinh?= =?UTF-8?q?altet=20noch=20Fehler!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bytecode/BytecodeGenMethod.java | 14 ++++++++-- .../convert/ASTToIntermediate.java | 26 ++++++++++++++++--- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index 02a07fb8..dfc63d4c 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -820,16 +820,26 @@ public class BytecodeGenMethod implements StatementVisitor { mDesc = helper.getDescriptorOfApplyMethod(methCallType); //ToDo Etienne: check if it works //helper.generateBCForFunN(mDesc); + FunN f; ASTToIntermediate converter = new ASTToIntermediate(); - IntermediateInnerType returnType = converter.convert(methodCall.receiver.getType()); + IntermediateInnerType returnType = (IntermediateInnerType) converter.convert(methodCall.receiver.getType()); + if(methodCall + .arglist + .getArguments().size() > 0){ List arguments = methodCall .arglist .getArguments() .stream() .map(TypableStatement::getType) .map(converter::convert) + .filter(t -> t instanceof IntermediateInnerType) + .map(t -> (IntermediateInnerType) t) .collect(Collectors.toList());//ToDo - FunN f = new FunN(arguments, returnType); + f = new FunN(arguments, returnType); + } else { + f = new FunN(returnType); + } + FunN.writeClassFile(f.getSuperClassName(), f.getSuperBytecode(), path); FunN.writeClassFile(f.getClassName(), f.getBytecode(), path); //ToDo Etienne End diff --git a/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java b/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java index 4e9ef6dc..b9cb47b5 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java @@ -3,7 +3,9 @@ package de.dhbwstuttgart.intermediate.convert; import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.intermediate.generation.FunN; import de.dhbwstuttgart.intermediate.types.*; +import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.syntaxtree.type.*; +import org.objectweb.asm.Type; import java.util.List; import java.util.stream.Collectors; @@ -12,14 +14,19 @@ public class ASTToIntermediate { public IntermediateRefType convert(RefType originalType){ //ToDo Etienne: check if it works + System.out.println(originalType.getName()); + System.out.println(originalType.getParaList().size()); + if (originalType.getName().toString().matches("Fun\\d+\\$\\$")){ ASTToIntermediate converter = new ASTToIntermediate(); List parameters = originalType.getParaList(); - IntermediateInnerType returnType = convert(parameters.get(parameters.size() - 1)); + IntermediateInnerType returnType = (IntermediateInnerType) convert(parameters.get(parameters.size() - 1)); parameters.remove(parameters.size() - 1); return new FunN(parameters .stream() .map(this::convert) + .filter(t -> t instanceof IntermediateInnerType) + .map(t -> (IntermediateInnerType) t) .collect(Collectors.toList()), returnType); } @@ -52,13 +59,24 @@ public class ASTToIntermediate { return new IntermediateExtendsWildcard((IntermediateInnerType) innerType); } + /* public IntermediateWildcard convert(){ //thows RuntimeException because in the AST is no typ defined which represents a normal wildcard throw new NotImplementedException("There is no conversion defined for this type."); } + */ - public IntermediateRefType convert(RefTypeOrTPHOrWildcardOrGeneric originalType){ - //default implementation which shouldn't be called because of polymorphism - throw new NotImplementedException("There is no conversion defined for this type."); + //ToDo Etienne: check if it works + public IntermediateRefType convert(TypePlaceholder originalType){ + return new IntermediateRefType(new JavaClassName(Type.getInternalName(Object.class))); + } + + public IntermediateType convert(RefTypeOrTPHOrWildcardOrGeneric originalType){ + if (originalType instanceof RefType) return convert((RefType) originalType); + if (originalType instanceof GenericRefType) return convert((GenericRefType) originalType); + if (originalType instanceof SuperWildcardType) return convert((SuperWildcardType) originalType); + if (originalType instanceof ExtendsWildcardType) return convert((ExtendsWildcardType) originalType); + if (originalType instanceof TypePlaceholder) return convert((TypePlaceholder) originalType); + throw new NotImplementedException("There is no conversion defined for this type." + originalType.getClass().getName()); } } From bcf56e6bdd4fff5c2afc75e3df8355a13b381c21 Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Thu, 24 Mar 2022 10:38:12 +0100 Subject: [PATCH 24/69] Verbesserung der Generierung von FunN-Typen. Lambda Expressions noch fehlerhaft. --- .../java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java | 8 +++++--- .../bytecode/descriptor/DescriptorToString.java | 1 + .../de/dhbwstuttgart/bytecode/utilities/Resolver.java | 5 +++++ .../intermediate/convert/ASTToIntermediate.java | 2 ++ 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index dfc63d4c..0bff4d5f 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -592,11 +592,12 @@ public class BytecodeGenMethod implements StatementVisitor { public void visit(LambdaExpression lambdaExpression) { this.lamCounter++; + //ToDo Etienne: umbauen String typeErasure = createDescriptorWithTypeErasure(lambdaExpression); ByteCodeForFunNGenerator.generateBCForFunN(lambdaExpression, typeErasure,path); - - + + //ToDo Etienne: umbauen Lambda lam = new Lambda(lambdaExpression); String lamDesc = lam.accept(new DescriptorToString(resultSet)); // Call site, which, when invoked, returns an instance of the functional @@ -822,7 +823,7 @@ public class BytecodeGenMethod implements StatementVisitor { //helper.generateBCForFunN(mDesc); FunN f; ASTToIntermediate converter = new ASTToIntermediate(); - IntermediateInnerType returnType = (IntermediateInnerType) converter.convert(methodCall.receiver.getType()); + IntermediateInnerType returnType = (IntermediateInnerType) converter.convert(resolver.resolve(methodCall.receiver.getType())); if(methodCall .arglist .getArguments().size() > 0){ @@ -831,6 +832,7 @@ public class BytecodeGenMethod implements StatementVisitor { .getArguments() .stream() .map(TypableStatement::getType) + .map(resolver::resolve) .map(converter::convert) .filter(t -> t instanceof IntermediateInnerType) .map(t -> (IntermediateInnerType) t) diff --git a/src/main/java/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java b/src/main/java/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java index 90064863..c272c12f 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java @@ -153,6 +153,7 @@ public class DescriptorToString implements DescriptorVisitor, CONSTANTS { return desc; } + //ToDo Etienne: ändern @Override public String visit(Lambda lambdaExpression) { String desc = "("; diff --git a/src/main/java/de/dhbwstuttgart/bytecode/utilities/Resolver.java b/src/main/java/de/dhbwstuttgart/bytecode/utilities/Resolver.java index f581b374..684fdd4b 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/utilities/Resolver.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/utilities/Resolver.java @@ -25,4 +25,9 @@ public class Resolver { public String getResolvedType(RefTypeOrTPHOrWildcardOrGeneric type) { return resultSet.resolveType(type).resolvedType.acceptTV(new TypeToDescriptor()); } + + //ToDo Etienne: Check ob benötigt + public RefTypeOrTPHOrWildcardOrGeneric resolve(RefTypeOrTPHOrWildcardOrGeneric type) { + return resultSet.resolveType(type).resolvedType; + } } diff --git a/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java b/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java index b9cb47b5..9e5a6932 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java @@ -1,5 +1,6 @@ package de.dhbwstuttgart.intermediate.convert; +import de.dhbwstuttgart.bytecode.utilities.Resolver; import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.intermediate.generation.FunN; import de.dhbwstuttgart.intermediate.types.*; @@ -18,6 +19,7 @@ public class ASTToIntermediate { System.out.println(originalType.getParaList().size()); if (originalType.getName().toString().matches("Fun\\d+\\$\\$")){ + if(originalType.getParaList().size() == 0) throw new RuntimeException("Incorrect FunN Type: No params are defined!"); ASTToIntermediate converter = new ASTToIntermediate(); List parameters = originalType.getParaList(); IntermediateInnerType returnType = (IntermediateInnerType) convert(parameters.get(parameters.size() - 1)); From 4522aeff36a9d575c331fd3e36b2665c3981b83a Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Mon, 28 Mar 2022 10:47:49 +0200 Subject: [PATCH 25/69] =?UTF-8?q?Verbesserung=20der=20Bytecodegenerierung?= =?UTF-8?q?=20f=C3=BCr=20FunN=20Typen.=20Immernoch=20in=20drei=20Tests=20f?= =?UTF-8?q?ehlerhaft.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bytecode/BytecodeGenMethod.java | 35 ++++++++++++------- .../bytecode/descriptor/TypeToDescriptor.java | 5 ++- .../bytecode/signature/TypeToSignature.java | 3 +- .../convert/ASTToIntermediate.java | 8 ++--- .../intermediate/generation/FunN.java | 5 +-- .../types/IntermediateRefType.java | 2 +- 6 files changed, 36 insertions(+), 22 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index 0bff4d5f..d0b6fda6 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -592,12 +592,26 @@ public class BytecodeGenMethod implements StatementVisitor { public void visit(LambdaExpression lambdaExpression) { this.lamCounter++; - //ToDo Etienne: umbauen String typeErasure = createDescriptorWithTypeErasure(lambdaExpression); - - ByteCodeForFunNGenerator.generateBCForFunN(lambdaExpression, typeErasure,path); - + //ByteCodeForFunNGenerator.generateBCForFunN(lambdaExpression, typeErasure,path); //old //ToDo Etienne: umbauen + FunN f; + //ToDo refactor with code for FunN underneath + ASTToIntermediate converter = new ASTToIntermediate(); + IntermediateInnerType returnType = (IntermediateInnerType) converter.convert(lambdaExpression.getReturnType()); + List arguments = lambdaExpression.params + .getFormalparalist() + .stream() + .map(FormalParameter::getType) + .map(resolver::resolve) + .map(converter::convert) + .filter(t -> t instanceof IntermediateInnerType) + .map(t -> (IntermediateInnerType) t) + .collect(Collectors.toList());//ToDo + f = new FunN(arguments, returnType); + FunN.writeClassFile(f.getSuperClassName(), f.getSuperBytecode(), path); + FunN.writeClassFile(f.getClassName(), f.getBytecode(), path); + //ToDo Etienne: umbauen end Lambda lam = new Lambda(lambdaExpression); String lamDesc = lam.accept(new DescriptorToString(resultSet)); // Call site, which, when invoked, returns an instance of the functional @@ -819,14 +833,12 @@ public class BytecodeGenMethod implements StatementVisitor { } else if(!helper.isInCurrPkg(clazz)){ if(clazz.contains(CONSTANTS.$$)) { mDesc = helper.getDescriptorOfApplyMethod(methCallType); + //helper.generateBCForFunN(mDesc); //old //ToDo Etienne: check if it works - //helper.generateBCForFunN(mDesc); FunN f; ASTToIntermediate converter = new ASTToIntermediate(); - IntermediateInnerType returnType = (IntermediateInnerType) converter.convert(resolver.resolve(methodCall.receiver.getType())); - if(methodCall - .arglist - .getArguments().size() > 0){ + //Fehler + IntermediateInnerType returnType = (IntermediateInnerType) converter.convert(resolver.resolve(methodCall.getType())); List arguments = methodCall .arglist .getArguments() @@ -837,10 +849,7 @@ public class BytecodeGenMethod implements StatementVisitor { .filter(t -> t instanceof IntermediateInnerType) .map(t -> (IntermediateInnerType) t) .collect(Collectors.toList());//ToDo - f = new FunN(arguments, returnType); - } else { - f = new FunN(returnType); - } + f = new FunN(arguments, returnType); FunN.writeClassFile(f.getSuperClassName(), f.getSuperBytecode(), path); FunN.writeClassFile(f.getClassName(), f.getBytecode(), path); diff --git a/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java b/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java index 613f672e..0b8d1346 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java @@ -14,7 +14,10 @@ public class TypeToDescriptor implements TypeVisitor{ @Override public String visit(RefType refType) { //ToDo Etienne: check if it works - if (refType.getName().toString().matches("Fun\\d+\\$\\$")) return new ASTToIntermediate().convert(refType).getDescriptor(); + if (refType.getName().toString().matches("Fun\\d+\\$\\$")){ + String descriptor = new ASTToIntermediate().convert(refType).getDescriptor(); + return descriptor.substring(1, descriptor.length() - 1); + } return refType.getName().toString().replace(".", "/"); // String t = refType.getName().toString().replace(".", "/"); diff --git a/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java b/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java index 347d0d08..e9fc63f9 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java @@ -31,7 +31,8 @@ public class TypeToSignature implements TypeVisitor { if(refType.getName().toString().equals("void")) return "V"; //ToDo Etienne: check if it works - if (refType.getName().toString().matches("Fun\\d+\\$\\$")) return new ASTToIntermediate().convert(refType).getSignature(); + if (refType.getName().toString().matches("Fun\\d+\\$\\$")) + return new ASTToIntermediate().convert(refType).getSignature(); // return refType.toString().replace(".", "/"); String params = ""; diff --git a/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java b/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java index 9e5a6932..a386dd50 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java @@ -1,6 +1,5 @@ package de.dhbwstuttgart.intermediate.convert; -import de.dhbwstuttgart.bytecode.utilities.Resolver; import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.intermediate.generation.FunN; import de.dhbwstuttgart.intermediate.types.*; @@ -19,13 +18,13 @@ public class ASTToIntermediate { System.out.println(originalType.getParaList().size()); if (originalType.getName().toString().matches("Fun\\d+\\$\\$")){ - if(originalType.getParaList().size() == 0) throw new RuntimeException("Incorrect FunN Type: No params are defined!"); - ASTToIntermediate converter = new ASTToIntermediate(); + if(originalType.getParaList().size() == 0) + throw new RuntimeException("Incorrect FunN Type: No params are defined!"); List parameters = originalType.getParaList(); IntermediateInnerType returnType = (IntermediateInnerType) convert(parameters.get(parameters.size() - 1)); - parameters.remove(parameters.size() - 1); return new FunN(parameters .stream() + .limit((parameters.size() - 1) > 0 ? (parameters.size() - 1) : 0) .map(this::convert) .filter(t -> t instanceof IntermediateInnerType) .map(t -> (IntermediateInnerType) t) @@ -70,6 +69,7 @@ public class ASTToIntermediate { //ToDo Etienne: check if it works public IntermediateRefType convert(TypePlaceholder originalType){ + //ToDo zu Generic nachher return new IntermediateRefType(new JavaClassName(Type.getInternalName(Object.class))); } diff --git a/src/main/java/de/dhbwstuttgart/intermediate/generation/FunN.java b/src/main/java/de/dhbwstuttgart/intermediate/generation/FunN.java index fc8119a0..11b1ccc8 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/generation/FunN.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/generation/FunN.java @@ -60,9 +60,9 @@ public final class FunN extends IntermediateRefType { typArguments.size(), typArguments .stream() - .map(IntermediateType::getSignature) + .map(IntermediateInnerType::getDescriptor) .collect(Collectors.joining()), - returnType.getSignature()) + returnType.getDescriptor()) .replace('/', '$') .replace(";", "$_$")), Stream.concat(typArguments.stream(), Stream.of(returnType)).collect(Collectors.toList())); @@ -138,6 +138,7 @@ public final class FunN extends IntermediateRefType { } //ToDo Etienne: Auslagern in andere Klasse; + @Deprecated public static boolean writeClassFile(String className, byte[] bytecode, File directory) { try (FileOutputStream output = new FileOutputStream(new File(directory , className + CONSTANTS.EXTENSIONCLASS))){ output.write(bytecode); diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java index be32f860..91be08c0 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java @@ -82,7 +82,7 @@ public class IntermediateRefType extends IntermediateInnerType{ } signature += ";"; } - signature.replace('.','/'); + signature = signature.replace('.','/'); this.signature = signature; return signature; } From fedf33a006d51be1ec868fb0e9278806897ede65 Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Mon, 28 Mar 2022 11:56:14 +0200 Subject: [PATCH 26/69] =?UTF-8?q?Alle=20Tests=20der=20Bytecode-Generierung?= =?UTF-8?q?=20sind=20nun=20auf=20gr=C3=BCn=20mit=20den=20Spezialisierungen?= =?UTF-8?q?=20der=20FunN=20Typen.=20Bytecode=20muss=20noch=20manuell=20?= =?UTF-8?q?=C3=BCberpr=C3=BCft=20werden,=20ob=20=C3=BCberall=20korrekt!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bytecode/BytecodeGenMethod.java | 3 ++- .../bytecode/descriptor/TypeToDescriptor.java | 2 +- .../intermediate/convert/ASTToIntermediate.java | 17 +++-------------- 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index d0b6fda6..208c93be 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -598,7 +598,8 @@ public class BytecodeGenMethod implements StatementVisitor { FunN f; //ToDo refactor with code for FunN underneath ASTToIntermediate converter = new ASTToIntermediate(); - IntermediateInnerType returnType = (IntermediateInnerType) converter.convert(lambdaExpression.getReturnType()); + //Fehler in return Typ + IntermediateInnerType returnType = (IntermediateInnerType) converter.convert(resolver.resolve(lambdaExpression.getReturnType())); List arguments = lambdaExpression.params .getFormalparalist() .stream() diff --git a/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java b/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java index 0b8d1346..c54f6fc9 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java @@ -14,7 +14,7 @@ public class TypeToDescriptor implements TypeVisitor{ @Override public String visit(RefType refType) { //ToDo Etienne: check if it works - if (refType.getName().toString().matches("Fun\\d+\\$\\$")){ + if (refType.getName().toString().matches("Fun\\d+\\$\\$")) { String descriptor = new ASTToIntermediate().convert(refType).getDescriptor(); return descriptor.substring(1, descriptor.length() - 1); } diff --git a/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java b/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java index a386dd50..20ea14cc 100644 --- a/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java +++ b/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java @@ -3,9 +3,7 @@ package de.dhbwstuttgart.intermediate.convert; import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.intermediate.generation.FunN; import de.dhbwstuttgart.intermediate.types.*; -import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.syntaxtree.type.*; -import org.objectweb.asm.Type; import java.util.List; import java.util.stream.Collectors; @@ -39,8 +37,6 @@ public class ASTToIntermediate { .collect(Collectors.toList())); } - - //ToDo abklären: darf hier kein stehen? da hier kein Typparameter existiert public IntermediateGenericType convert(GenericRefType originalType){ //no typ argument for e.g. is present in the definition of GenericRefType return new IntermediateGenericType(originalType.getParsedName()); @@ -60,17 +56,10 @@ public class ASTToIntermediate { return new IntermediateExtendsWildcard((IntermediateInnerType) innerType); } - /* - public IntermediateWildcard convert(){ - //thows RuntimeException because in the AST is no typ defined which represents a normal wildcard - throw new NotImplementedException("There is no conversion defined for this type."); - } - */ - //ToDo Etienne: check if it works - public IntermediateRefType convert(TypePlaceholder originalType){ - //ToDo zu Generic nachher - return new IntermediateRefType(new JavaClassName(Type.getInternalName(Object.class))); + public IntermediateGenericType convert(TypePlaceholder originalType){ + //ToDo muss zu einem Generic werden + return new IntermediateGenericType(originalType.getName()); } public IntermediateType convert(RefTypeOrTPHOrWildcardOrGeneric originalType){ From 0e363cfae345524a290d8fafccc6554436c00b6e Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Mon, 28 Mar 2022 22:34:07 +0200 Subject: [PATCH 27/69] =?UTF-8?q?L=C3=B6chen=20des=20Intermediate-Packages?= =?UTF-8?q?=20und=20Erstellung=20einer=20Utility-Klasse=20zur=20FunN=20Byt?= =?UTF-8?q?ecodegenerierung.=20=C3=9Cbertragung=20der=20Funktionalit=C3=A4?= =?UTF-8?q?t=20zur=20Generierung=20von=20FunN=20auf=20FunNGenerator.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bytecode/BytecodeGenMethod.java | 46 ++++-- .../bytecode/descriptor/TypeToDescriptor.java | 17 +- .../bytecode/funN/FunNGenerator.java | 136 ++++++++++++++++ .../bytecode/funN/FunNUtilities.java | 34 ++++ .../bytecode/signature/TypeToSignature.java | 10 +- .../convert/ASTToIntermediate.java | 73 --------- .../intermediate/generation/FunN.java | 152 ------------------ .../types/IntermediateExtendsWildcard.java | 57 ------- .../types/IntermediateGenericType.java | 85 ---------- .../types/IntermediateInnerType.java | 8 - .../types/IntermediateRefType.java | 115 ------------- .../types/IntermediateSuperWildcard.java | 56 ------- .../intermediate/types/IntermediateType.java | 23 --- .../types/IntermediateWildcard.java | 33 ---- .../intermediate/generation/FunNTest.java | 117 -------------- .../types/IntermediateExtensWildcardTest.java | 62 ------- .../types/IntermediateGenericTypeTest.java | 80 --------- .../types/IntermediateRefTypeTest.java | 107 ------------ .../types/IntermediateSuperWildcardTest.java | 62 ------- .../types/IntermediateWildcardTest.java | 57 ------- 20 files changed, 219 insertions(+), 1111 deletions(-) create mode 100644 src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java create mode 100644 src/main/java/de/dhbwstuttgart/bytecode/funN/FunNUtilities.java delete mode 100644 src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java delete mode 100644 src/main/java/de/dhbwstuttgart/intermediate/generation/FunN.java delete mode 100644 src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateExtendsWildcard.java delete mode 100644 src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java delete mode 100644 src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateInnerType.java delete mode 100644 src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java delete mode 100644 src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateSuperWildcard.java delete mode 100644 src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java delete mode 100644 src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateWildcard.java delete mode 100644 src/test/java/intermediate/generation/FunNTest.java delete mode 100644 src/test/java/intermediate/types/IntermediateExtensWildcardTest.java delete mode 100644 src/test/java/intermediate/types/IntermediateGenericTypeTest.java delete mode 100644 src/test/java/intermediate/types/IntermediateRefTypeTest.java delete mode 100644 src/test/java/intermediate/types/IntermediateSuperWildcardTest.java delete mode 100644 src/test/java/intermediate/types/IntermediateWildcardTest.java diff --git a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index 208c93be..526eaa7a 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -15,12 +15,11 @@ import java.util.LinkedList; import java.util.List; import java.util.stream.Collectors; +import de.dhbwstuttgart.bytecode.funN.FunNGenerator; +import de.dhbwstuttgart.bytecode.funN.FunNUtilities; import de.dhbwstuttgart.bytecode.utilities.*; import de.dhbwstuttgart.environment.DirectoryClassLoader; import de.dhbwstuttgart.exceptions.NotImplementedException; -import de.dhbwstuttgart.intermediate.convert.ASTToIntermediate; -import de.dhbwstuttgart.intermediate.generation.FunN; -import de.dhbwstuttgart.intermediate.types.IntermediateInnerType; import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.syntaxtree.statement.*; import de.dhbwstuttgart.syntaxtree.statement.BinaryExpr.Operator; @@ -595,8 +594,9 @@ public class BytecodeGenMethod implements StatementVisitor { String typeErasure = createDescriptorWithTypeErasure(lambdaExpression); //ByteCodeForFunNGenerator.generateBCForFunN(lambdaExpression, typeErasure,path); //old //ToDo Etienne: umbauen + //ToDo Refactor + /* FunN f; - //ToDo refactor with code for FunN underneath ASTToIntermediate converter = new ASTToIntermediate(); //Fehler in return Typ IntermediateInnerType returnType = (IntermediateInnerType) converter.convert(resolver.resolve(lambdaExpression.getReturnType())); @@ -612,6 +612,22 @@ public class BytecodeGenMethod implements StatementVisitor { f = new FunN(arguments, returnType); FunN.writeClassFile(f.getSuperClassName(), f.getSuperBytecode(), path); FunN.writeClassFile(f.getClassName(), f.getBytecode(), path); + */ + ///* + RefTypeOrTPHOrWildcardOrGeneric returnType = resolver.resolve(lambdaExpression.getReturnType()); + List argumentTypes = lambdaExpression + .params + .getFormalparalist() + .stream() + .map(FormalParameter::getType) + .map(resolver::resolve) + .collect(Collectors.toList()); + FunNUtilities funNUtilities = FunNGenerator.getInstance(); + byte[] superBytecode = funNUtilities.generateSuperBytecode(argumentTypes.size()); + byte[] specializedBytecode = funNUtilities.generateSpecializedBytecode(argumentTypes, returnType); + FunNUtilities.writeClassFile(funNUtilities.getSuperClassName(argumentTypes.size()), superBytecode, path); + FunNUtilities.writeClassFile(funNUtilities.getSpecializedClassName(argumentTypes, returnType), specializedBytecode, path); + //*/ //ToDo Etienne: umbauen end Lambda lam = new Lambda(lambdaExpression); String lamDesc = lam.accept(new DescriptorToString(resultSet)); @@ -835,16 +851,14 @@ public class BytecodeGenMethod implements StatementVisitor { if(clazz.contains(CONSTANTS.$$)) { mDesc = helper.getDescriptorOfApplyMethod(methCallType); //helper.generateBCForFunN(mDesc); //old - //ToDo Etienne: check if it works + //ToDo Etienne: Refactor + /* FunN f; ASTToIntermediate converter = new ASTToIntermediate(); - //Fehler IntermediateInnerType returnType = (IntermediateInnerType) converter.convert(resolver.resolve(methodCall.getType())); List arguments = methodCall - .arglist - .getArguments() + .argTypes .stream() - .map(TypableStatement::getType) .map(resolver::resolve) .map(converter::convert) .filter(t -> t instanceof IntermediateInnerType) @@ -854,6 +868,20 @@ public class BytecodeGenMethod implements StatementVisitor { FunN.writeClassFile(f.getSuperClassName(), f.getSuperBytecode(), path); FunN.writeClassFile(f.getClassName(), f.getBytecode(), path); + */ + ///* + RefTypeOrTPHOrWildcardOrGeneric returnType = resolver.resolve(methodCall.getType()); + List argumentTypes = methodCall + .argTypes + .stream() + .map(resolver::resolve) + .collect(Collectors.toList()); + FunNUtilities funNUtilities = FunNGenerator.getInstance(); + byte[] superBytecode = funNUtilities.generateSuperBytecode(argumentTypes.size()); + byte[] specializedBytecode = funNUtilities.generateSpecializedBytecode(argumentTypes, returnType); + FunNUtilities.writeClassFile(funNUtilities.getSuperClassName(argumentTypes.size()), superBytecode, path); + FunNUtilities.writeClassFile(funNUtilities.getSpecializedClassName(argumentTypes, returnType), specializedBytecode, path); + //*/ //ToDo Etienne End // mDesc = helper.generateBCForFunN(methCallType,typesOfParams); }else { diff --git a/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java b/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java index c54f6fc9..dd4f62a2 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java @@ -1,22 +1,17 @@ package de.dhbwstuttgart.bytecode.descriptor; -import de.dhbwstuttgart.exceptions.NotImplementedException; -import de.dhbwstuttgart.intermediate.convert.ASTToIntermediate; -import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; -import de.dhbwstuttgart.syntaxtree.type.GenericRefType; -import de.dhbwstuttgart.syntaxtree.type.RefType; -import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType; -import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; -import de.dhbwstuttgart.syntaxtree.type.TypeVisitor; +import de.dhbwstuttgart.bytecode.funN.FunNGenerator; +import de.dhbwstuttgart.bytecode.funN.FunNUtilities; +import de.dhbwstuttgart.syntaxtree.type.*; public class TypeToDescriptor implements TypeVisitor{ @Override public String visit(RefType refType) { //ToDo Etienne: check if it works - if (refType.getName().toString().matches("Fun\\d+\\$\\$")) { - String descriptor = new ASTToIntermediate().convert(refType).getDescriptor(); - return descriptor.substring(1, descriptor.length() - 1); + if (refType.getName().toString().matches("Fun\\d+\\$\\$") && refType.getParaList().size() > 0) { + FunNUtilities funNUtilities = FunNGenerator.getInstance(); + return funNUtilities.getSpecializedDescriptor(funNUtilities.getArguments(refType.getParaList()), funNUtilities.getReturnType(refType.getParaList())); } return refType.getName().toString().replace(".", "/"); diff --git a/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java b/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java new file mode 100644 index 00000000..c9eae6b0 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java @@ -0,0 +1,136 @@ +package de.dhbwstuttgart.bytecode.funN; + +import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor; +import de.dhbwstuttgart.bytecode.signature.TypeToSignature; +import de.dhbwstuttgart.bytecode.utilities.CONSTANTS; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Type; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.List; +import java.util.stream.Collectors; + +import static org.objectweb.asm.Opcodes.*; + +//ToDo Kommentieren +public class FunNGenerator implements FunNUtilities{ + + private static FunNGenerator funNGenerator = new FunNGenerator(); + + public static FunNGenerator getInstance(){ + return funNGenerator; + } + + private final String argumentGenericBase = "T"; + private final String returnGeneric = "R"; + private final String methodName = "apply"; + private final int bytecodeVersion = V1_8; + + private final String objectSuperType = Type.getInternalName(Object.class).replace('.','/'); + private final RefType objectRefType = new RefType(new JavaClassName(objectSuperType), null); + private final String objectSignature = applySignature(objectRefType); + + private static String applyDescriptor(RefTypeOrTPHOrWildcardOrGeneric a) { return a.acceptTV(new TypeToDescriptor()); } + private static String applySignature(RefTypeOrTPHOrWildcardOrGeneric a) { return a.acceptTV(new TypeToSignature()); } + + @Override + public byte[] generateSuperBytecode(int numberArguments) { + StringBuilder superFunNClassSignature = new StringBuilder("<"); + StringBuilder superFunNMethodSignature = new StringBuilder("("); + StringBuilder superFunNMethodDescriptor = new StringBuilder("("); + + for (int currentParameter = 1; currentParameter <= numberArguments; currentParameter++){ + superFunNClassSignature.append(String.format("%s%d:%s",argumentGenericBase, currentParameter, objectSignature)); + superFunNMethodSignature.append(applySignature( new GenericRefType(argumentGenericBase + currentParameter, null))); + superFunNMethodDescriptor.append(objectSignature); + } + superFunNClassSignature.append(String.format("%s:%s>%s", returnGeneric, objectSignature, objectSignature)); + superFunNMethodSignature.append(String.format(")%s", applySignature(new GenericRefType(returnGeneric, null)))); + superFunNMethodDescriptor.append(String.format(")%s", objectSignature)); + + ClassWriter classWriter = new ClassWriter(0); + MethodVisitor methodVisitor; + classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, getSuperClassName(numberArguments), superFunNClassSignature.toString(), objectSuperType, null); + methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, methodName, superFunNMethodDescriptor.toString(), superFunNMethodSignature.toString(), null); + methodVisitor.visitEnd(); + classWriter.visitEnd(); + return classWriter.toByteArray(); + } + + @Override + public String getSuperClassName(int numberArguments) { + return String.format("Fun%d$$", numberArguments); + } + + @Override + public byte[] generateSpecializedBytecode(List argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType) { + StringBuilder funNClassSignature = new StringBuilder(objectSignature + applySignature(new RefType(new JavaClassName(getSuperClassName(argumentTypes.size())), null))); + boolean containsGeneric = false; + + String genericSignature = "<"; + for (int currentTypArgumentIndex = 0; currentTypArgumentIndex < argumentTypes.size(); currentTypArgumentIndex++) { + RefTypeOrTPHOrWildcardOrGeneric typArgument = argumentTypes.get(currentTypArgumentIndex); + if (typArgument == null) continue; + if (typArgument instanceof GenericRefType){ + GenericRefType generic = (GenericRefType) typArgument; + genericSignature += String.format("%s:%s", generic.getParsedName(), applyDescriptor(generic)); + containsGeneric = true; + } + } + genericSignature += ">"; + if (containsGeneric) funNClassSignature.insert(0, genericSignature); + + ClassWriter classWriter = new ClassWriter(0); + classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, getSpecializedClassName(argumentTypes, returnType), funNClassSignature.toString(), objectSuperType, new String[]{getSuperClassName(argumentTypes.size())}); + classWriter.visitEnd(); + return classWriter.toByteArray(); + } + + @Override + public String getSpecializedClassName(List argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType) { + if (returnType instanceof TypePlaceholder) returnType = objectRefType; + return String.format("Fun%d$$%s%s", + argumentTypes.size(), + argumentTypes + .stream() + .map(r -> r instanceof TypePlaceholder ? objectRefType : r) + .map(FunNGenerator::applyDescriptor) + .map(d -> String.format("L%s;", d)) + .collect(Collectors.joining()), + applyDescriptor(returnType)) + .replace('/', '$') + .replace(";", "$_$"); + } + + @Override + public String getSpecializedDescriptor(List argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType) { + return applyDescriptor(new RefType(new JavaClassName(getSpecializedClassName(argumentTypes, returnType)), null)); + } + + @Override + public String getSpecializedSignature(List argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType) { + return applySignature(new RefType(new JavaClassName(getSpecializedClassName(argumentTypes, returnType)), null)); + } + + @Override + public List getArguments(List list) { + return list + .stream() + .limit(Math.max(0, list.size() - 1)) + .collect(Collectors.toList()); + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric getReturnType(List list) { + if(list.size() == 0) + throw new IndexOutOfBoundsException(); + return list.get(list.size() - 1); + } +} diff --git a/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNUtilities.java b/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNUtilities.java new file mode 100644 index 00000000..d545723b --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNUtilities.java @@ -0,0 +1,34 @@ +package de.dhbwstuttgart.bytecode.funN; + +import de.dhbwstuttgart.bytecode.utilities.CONSTANTS; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.List; + +public interface FunNUtilities { + + byte[] generateSuperBytecode(int numberArguments); + String getSuperClassName(int numberArguments); + + byte[] generateSpecializedBytecode(List argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType); + String getSpecializedClassName(List argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType); + String getSpecializedDescriptor(List argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType); + String getSpecializedSignature(List argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType); + + List getArguments(List list); + RefTypeOrTPHOrWildcardOrGeneric getReturnType(List list); + + @Deprecated + public static boolean writeClassFile(String className, byte[] bytecode, File directory) { + try (FileOutputStream output = new FileOutputStream(new File(directory , className + CONSTANTS.EXTENSIONCLASS))){ + output.write(bytecode); + output.flush(); + return true; + } catch (Exception e) { + e.printStackTrace(); + } + return false; + } +} diff --git a/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java b/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java index e9fc63f9..53b39b3a 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java @@ -5,8 +5,9 @@ import java.util.Iterator; import java.util.List; import java.util.Optional; +import de.dhbwstuttgart.bytecode.funN.FunNGenerator; +import de.dhbwstuttgart.bytecode.funN.FunNUtilities; import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericsGeneratorResult; -import de.dhbwstuttgart.intermediate.convert.ASTToIntermediate; import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; import de.dhbwstuttgart.syntaxtree.type.GenericRefType; import de.dhbwstuttgart.syntaxtree.type.RefType; @@ -31,9 +32,10 @@ public class TypeToSignature implements TypeVisitor { if(refType.getName().toString().equals("void")) return "V"; //ToDo Etienne: check if it works - if (refType.getName().toString().matches("Fun\\d+\\$\\$")) - return new ASTToIntermediate().convert(refType).getSignature(); - + if (refType.getName().toString().matches("Fun\\d+\\$\\$") && refType.getParaList().size() > 0){ + FunNUtilities funNUtilities = FunNGenerator.getInstance(); + return funNUtilities.getSpecializedSignature(funNUtilities.getArguments(refType.getParaList()), funNUtilities.getReturnType(refType.getParaList())); + } // return refType.toString().replace(".", "/"); String params = ""; if(refType.getParaList().size()>0){ diff --git a/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java b/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java deleted file mode 100644 index 20ea14cc..00000000 --- a/src/main/java/de/dhbwstuttgart/intermediate/convert/ASTToIntermediate.java +++ /dev/null @@ -1,73 +0,0 @@ -package de.dhbwstuttgart.intermediate.convert; - -import de.dhbwstuttgart.exceptions.NotImplementedException; -import de.dhbwstuttgart.intermediate.generation.FunN; -import de.dhbwstuttgart.intermediate.types.*; -import de.dhbwstuttgart.syntaxtree.type.*; - -import java.util.List; -import java.util.stream.Collectors; - -public class ASTToIntermediate { - - public IntermediateRefType convert(RefType originalType){ - //ToDo Etienne: check if it works - System.out.println(originalType.getName()); - System.out.println(originalType.getParaList().size()); - - if (originalType.getName().toString().matches("Fun\\d+\\$\\$")){ - if(originalType.getParaList().size() == 0) - throw new RuntimeException("Incorrect FunN Type: No params are defined!"); - List parameters = originalType.getParaList(); - IntermediateInnerType returnType = (IntermediateInnerType) convert(parameters.get(parameters.size() - 1)); - return new FunN(parameters - .stream() - .limit((parameters.size() - 1) > 0 ? (parameters.size() - 1) : 0) - .map(this::convert) - .filter(t -> t instanceof IntermediateInnerType) - .map(t -> (IntermediateInnerType) t) - .collect(Collectors.toList()), returnType); - } - - return new IntermediateRefType(originalType.getName(), - originalType - .getParaList() - .stream() - .map(this::convert) - .collect(Collectors.toList())); - } - - public IntermediateGenericType convert(GenericRefType originalType){ - //no typ argument for e.g. is present in the definition of GenericRefType - return new IntermediateGenericType(originalType.getParsedName()); - } - - public IntermediateSuperWildcard convert(SuperWildcardType originalType){ - IntermediateType innerType = convert(originalType.getInnerType()); - //throws RuntimeException, because only IntermediateInnerType (no wildcards) are allowed as inner types of wildcards - if (!(innerType instanceof IntermediateInnerType)) throw new RuntimeException("False inner type!"); - return new IntermediateSuperWildcard((IntermediateInnerType) innerType); - } - - public IntermediateExtendsWildcard convert(ExtendsWildcardType originalType){ - IntermediateType innerType = convert(originalType.getInnerType()); - //throws RuntimeException because only IntermediateInnerType (no wildcards) are allowed as inner types of wildcards - if (!(innerType instanceof IntermediateInnerType)) throw new RuntimeException("False inner type!"); - return new IntermediateExtendsWildcard((IntermediateInnerType) innerType); - } - - //ToDo Etienne: check if it works - public IntermediateGenericType convert(TypePlaceholder originalType){ - //ToDo muss zu einem Generic werden - return new IntermediateGenericType(originalType.getName()); - } - - public IntermediateType convert(RefTypeOrTPHOrWildcardOrGeneric originalType){ - if (originalType instanceof RefType) return convert((RefType) originalType); - if (originalType instanceof GenericRefType) return convert((GenericRefType) originalType); - if (originalType instanceof SuperWildcardType) return convert((SuperWildcardType) originalType); - if (originalType instanceof ExtendsWildcardType) return convert((ExtendsWildcardType) originalType); - if (originalType instanceof TypePlaceholder) return convert((TypePlaceholder) originalType); - throw new NotImplementedException("There is no conversion defined for this type." + originalType.getClass().getName()); - } -} diff --git a/src/main/java/de/dhbwstuttgart/intermediate/generation/FunN.java b/src/main/java/de/dhbwstuttgart/intermediate/generation/FunN.java deleted file mode 100644 index 11b1ccc8..00000000 --- a/src/main/java/de/dhbwstuttgart/intermediate/generation/FunN.java +++ /dev/null @@ -1,152 +0,0 @@ -package de.dhbwstuttgart.intermediate.generation; - -import de.dhbwstuttgart.bytecode.utilities.CONSTANTS; -import de.dhbwstuttgart.intermediate.types.IntermediateGenericType; -import de.dhbwstuttgart.intermediate.types.IntermediateInnerType; -import de.dhbwstuttgart.intermediate.types.IntermediateRefType; -import de.dhbwstuttgart.intermediate.types.IntermediateType; -import de.dhbwstuttgart.parser.scope.JavaClassName; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Type; - -import java.io.File; -import java.io.FileOutputStream; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static org.objectweb.asm.Opcodes.*; - -/** - * Class which represents a function type. - * Offers different methods to generate or interact with this real function type. - * - * @since Studienarbeit Type Erasure - * @author etiennezink - */ -public final class FunN extends IntermediateRefType { - - private final String argumentGenericBase = "T"; - private final String returnGeneric = "R"; - private final String methodName = "apply"; - private final int bytecodeVersion = V1_8; - - private final String objectSuperType = Type.getInternalName(Object.class).replace('.','/'); - private final String objectSignature = new IntermediateRefType(new JavaClassName(Type.getInternalName(Object.class))).getSignature(); - - /** - * Represents the super interface of this specialized function. - */ - private final IntermediateRefType superFunN; - - /** - * Caches the superBytecode after first computation. - */ - private byte[] superBytecode; - - /** - * Caches the bytecode after first computation. - */ - private byte[] bytecode; - - public FunN(IntermediateInnerType returnType){ this(Collections.emptyList(), returnType); } - - public FunN(List typArguments, IntermediateInnerType returnType) { - //using stream-API for single line processing of relevant data in the super()-call - super(new JavaClassName( - String.format("Fun%d$$%s%s", - typArguments.size(), - typArguments - .stream() - .map(IntermediateInnerType::getDescriptor) - .collect(Collectors.joining()), - returnType.getDescriptor()) - .replace('/', '$') - .replace(";", "$_$")), - Stream.concat(typArguments.stream(), Stream.of(returnType)).collect(Collectors.toList())); - superFunN = new IntermediateRefType(new JavaClassName(String.format("Fun%d$$", typArguments.size())), - Stream.concat(typArguments.stream(), Stream.of(returnType)).collect(Collectors.toList())); - } - - public String getSuperClassName() { return superFunN.getClassName(); } - - /** - * @return the bytecode for the super FunN type - */ - public byte[] getSuperBytecode(){ - byte[] superBytecode = this.superBytecode; - if (superBytecode == null){ - String superFunNClassSignature = "<"; - String superFunNMethodSignature = "("; - String superFunNMethodDescriptor = "("; - - //currentParameter < getTypArgumentSize() because the return type is stored in the typArguments as well - for (int currentParameter = 1; currentParameter < getTypArgumentSize(); currentParameter++){ - superFunNClassSignature += String.format("%s%d:%s",argumentGenericBase, currentParameter, objectSignature); - superFunNMethodSignature += new IntermediateGenericType(argumentGenericBase + currentParameter).getSignature(); - superFunNMethodDescriptor += objectSignature; - } - superFunNClassSignature += String.format("%s:%s>%s", returnGeneric, objectSignature, objectSignature); - superFunNMethodSignature += String.format(")%s", new IntermediateGenericType(returnGeneric).getSignature()); - superFunNMethodDescriptor += String.format(")%s", objectSignature); - - ClassWriter classWriter = new ClassWriter(0); - MethodVisitor methodVisitor; - classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, superFunN.getClassName(), superFunNClassSignature, objectSuperType, null); - methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, methodName, superFunNMethodDescriptor, superFunNMethodSignature , null); - methodVisitor.visitEnd(); - classWriter.visitEnd(); - superBytecode = classWriter.toByteArray(); - this.superBytecode = superBytecode; - } - return superBytecode; - } - - /** - * Generates the bytecode for this FunN type. - * Make sure to generate the bytecode for the super FunN as well. - * @return the bytecode for this explicit FunN type - */ - public byte[] getBytecode(){ - byte[] bytecode = this.bytecode; - if (bytecode == null){ - String funNClassSignature = objectSignature + superFunN.getSignature(); - boolean containsGeneric = false; - - String genericSignature = "<"; - for (int currentTypArgumentIndex = 0; currentTypArgumentIndex < getTypArgumentSize(); currentTypArgumentIndex++) { - IntermediateType typArgument = getTypArgument(currentTypArgumentIndex); - if (typArgument == null) continue; - if (typArgument instanceof IntermediateGenericType){ - IntermediateGenericType generic = (IntermediateGenericType) typArgument; - genericSignature += String.format("%s:%s", generic.getGenericName(), generic.getDescriptor()); - containsGeneric = true; - } - } - genericSignature += ">"; - if (containsGeneric) funNClassSignature = genericSignature + funNClassSignature; - - ClassWriter classWriter = new ClassWriter(0); - classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, getClassName(), funNClassSignature, objectSuperType, new String[]{superFunN.getClassName()}); - classWriter.visitEnd(); - bytecode = classWriter.toByteArray(); - this.bytecode = bytecode; - } - return bytecode; - } - - //ToDo Etienne: Auslagern in andere Klasse; - @Deprecated - public static boolean writeClassFile(String className, byte[] bytecode, File directory) { - try (FileOutputStream output = new FileOutputStream(new File(directory , className + CONSTANTS.EXTENSIONCLASS))){ - output.write(bytecode); - output.flush(); - return true; - } catch (Exception e) { - e.printStackTrace(); - } - return false; - } -} diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateExtendsWildcard.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateExtendsWildcard.java deleted file mode 100644 index 0bfde0ec..00000000 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateExtendsWildcard.java +++ /dev/null @@ -1,57 +0,0 @@ -package de.dhbwstuttgart.intermediate.types; - -/** - * Represents a Java Wildcard with a extends-operator. - * E.g. {@code <? extends String>} - * - * @since Studienarbeit Type Erasure - * @author etiennezink - */ -public final class IntermediateExtendsWildcard extends IntermediateType { - - private final IntermediateInnerType innerType; - - /** - * Caches the hashCode after first computation. - */ - private int hashCode; - - /** - * Caches the signature after first computation. - */ - private String signature = ""; - - public IntermediateExtendsWildcard(IntermediateInnerType innerType) { - this.innerType = innerType; - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof IntermediateExtendsWildcard)) return false; - - IntermediateExtendsWildcard intermediateExtendsWildcard = (IntermediateExtendsWildcard) o; - if(!innerType.equals(intermediateExtendsWildcard.innerType)) return false; - return true; - } - - @Override - public int hashCode() { - int prime = 31; - int hashCode = this.hashCode; - if (hashCode == 0){ - hashCode += innerType.hashCode(); - hashCode = prime * hashCode + "extends".hashCode(); - this.hashCode = hashCode; - } - return hashCode; - } - - @Override - public String getSignature() { - String signature = this.signature; - if (!signature.equals("")) return this.signature; - signature = String.format("+%s", innerType.getSignature()); - this.signature = signature; - return signature; - } -} diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java deleted file mode 100644 index a222dc2c..00000000 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateGenericType.java +++ /dev/null @@ -1,85 +0,0 @@ -package de.dhbwstuttgart.intermediate.types; - -import de.dhbwstuttgart.parser.scope.JavaClassName; -import org.objectweb.asm.Type; - -/** - * Represents a Java typ variable. - * E.g. {@code <T>} or {@code <T extends String>}. - * - * @since Studienarbeit Type Erasure - * @author etiennezink - */ -public final class IntermediateGenericType extends IntermediateInnerType { - - private final String genericName; - private final IntermediateInnerType innerType; - - /** - * Caches the hashCode after first computation. - */ - private int hashCode; - - /** - * Caches the signature after first computation. - */ - private String signature = ""; - - /** - * Caches the descriptor after first computation. - */ - private String descriptor = ""; - - public IntermediateGenericType(String genericName){ - this(genericName, new IntermediateRefType(new JavaClassName(Type.getInternalName(Object.class)))); - } - - public IntermediateGenericType(String genericName, IntermediateInnerType innerType) { - this.innerType = innerType; - this.genericName = genericName; - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof IntermediateGenericType)) return false; - - IntermediateGenericType intermediateGenericType = (IntermediateGenericType) o; - if(!innerType.equals(intermediateGenericType.innerType)) return false; - if(!genericName.equals(intermediateGenericType.genericName)) return false; - return true; - } - - @Override - public int hashCode() { - int prime = 31; - int hashCode = this.hashCode; - if (hashCode == 0){ - hashCode += innerType.hashCode(); - hashCode = prime * hashCode + genericName.hashCode(); - this.hashCode = hashCode; - } - return hashCode; - } - - @Override - public String getSignature() { - String signature = this.signature; - if (!signature.equals("")) return this.signature; - signature += String.format("T%s;", genericName); - this.signature = signature; - return signature; - } - - @Override - public String getDescriptor() { - String descriptor = this.descriptor; - if (!descriptor.equals("")) return this.descriptor; - descriptor = innerType.getDescriptor(); - this.descriptor = descriptor; - return descriptor; - } - - public String getGenericName() { - return genericName; - } -} diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateInnerType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateInnerType.java deleted file mode 100644 index f10fe157..00000000 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateInnerType.java +++ /dev/null @@ -1,8 +0,0 @@ -package de.dhbwstuttgart.intermediate.types; - -/** - * Only Java types which can be used as an inner type, have a descriptor definition. - */ -public abstract class IntermediateInnerType extends IntermediateType { - public abstract String getDescriptor(); -} diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java deleted file mode 100644 index 91be08c0..00000000 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateRefType.java +++ /dev/null @@ -1,115 +0,0 @@ -package de.dhbwstuttgart.intermediate.types; - -import de.dhbwstuttgart.parser.scope.JavaClassName; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * Represents a Java reference type. - * - * @since Studienarbeit Type Erasure - * @author etiennezink - */ -public class IntermediateRefType extends IntermediateInnerType{ - - private final List typArguments; - private final JavaClassName className; - - /** - * Caches the hashCode after first computation. - */ - private int hashCode; - - /** - * Caches the signature after first computation. - */ - private String signature = ""; - - /** - * Caches the descriptor after first computation. - */ - private String descriptor = ""; - - public IntermediateRefType(JavaClassName className) { this(className, Collections.emptyList()); } - - public IntermediateRefType(JavaClassName className, List typArguments){ - this.className = className; - this.typArguments = Collections.unmodifiableList(typArguments); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof IntermediateRefType)) return false; - - IntermediateRefType intermediateRefType = (IntermediateRefType) o; - if(!getFullyQualifiedName().equals(intermediateRefType.getFullyQualifiedName())) return false; - - for(int index = 0; index < typArguments.size(); index++){ - if(!typArguments.get(index).equals(intermediateRefType.typArguments.get(index))) return false; - } - return true; - } - - @Override - public int hashCode() { - int prime = 31; - int hashCode = this.hashCode; - if (hashCode == 0){ - hashCode += getFullyQualifiedName().hashCode(); - for (IntermediateType typeArgument: typArguments) { - hashCode = prime * hashCode + typeArgument.hashCode(); - } - this.hashCode = hashCode; - } - return hashCode; - } - - @Override - public String getSignature() { - String signature = this.signature; - if (!signature.equals("")) return this.signature; - - if (className.getClassName().equals("void")) signature = "V"; - else { - signature += String.format("L%s", getFullyQualifiedName()); - if (typArguments.size() != 0){ - signature += "<"; - for (IntermediateType typArgument: typArguments) { - signature += typArgument.getSignature(); - } - signature += ">"; - } - signature += ";"; - } - signature = signature.replace('.','/'); - this.signature = signature; - return signature; - } - - @Override - public String getDescriptor() { - String descriptor = this.descriptor; - if (!descriptor.equals("")) return this.descriptor; - descriptor = getSignature().replaceAll("<.+>", ""); - this.descriptor = descriptor; - return descriptor; - } - - public boolean isParametrized() { return typArguments.size() > 0; } - - public int getTypArgumentSize(){ return typArguments.size(); } - - /** - * @param index - * @return the typ parameter at {@code index} or {@code null}, iff {@code |typ parameters| < index} - */ - public IntermediateType getTypArgument(int index) { - if(typArguments.size() < index) return null; - return typArguments.get(index); - } - - public String getClassName(){ return className.getClassName(); } - public String getPackageName(){ return className.getPackageName(); } - public String getFullyQualifiedName(){ return className.toString(); } -} diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateSuperWildcard.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateSuperWildcard.java deleted file mode 100644 index 33b8cf80..00000000 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateSuperWildcard.java +++ /dev/null @@ -1,56 +0,0 @@ -package de.dhbwstuttgart.intermediate.types; - -/** - * Represents a Java Wildcard with a super-operator. - * E.g. {@code <? super String>} - * - * @since Studienarbeit Type Erasure - * @author etiennezink - */ -public final class IntermediateSuperWildcard extends IntermediateType { - private final IntermediateInnerType innerType; - - /** - * Caches the hashCode after first computation. - */ - private int hashCode; - - /** - * Caches the signature after first computation. - */ - private String signature = ""; - - public IntermediateSuperWildcard(IntermediateInnerType innerType) { - this.innerType = innerType; - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof IntermediateSuperWildcard)) return false; - - IntermediateSuperWildcard intermediateSuperWildcard = (IntermediateSuperWildcard) o; - if(!innerType.equals(intermediateSuperWildcard.innerType)) return false; - return true; - } - - @Override - public int hashCode() { - int prime = 31; - int hashCode = this.hashCode; - if (hashCode == 0){ - hashCode += innerType.hashCode(); - hashCode = prime * hashCode + "super".hashCode(); - this.hashCode = hashCode; - } - return hashCode; - } - - @Override - public String getSignature() { - String signature = this.signature; - if (!signature.equals("")) return this.signature; - signature = String.format("-%s", innerType.getSignature()); - this.signature = signature; - return signature; - } -} diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java deleted file mode 100644 index 3edaf9b0..00000000 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateType.java +++ /dev/null @@ -1,23 +0,0 @@ -package de.dhbwstuttgart.intermediate.types; - -/** - * Base class for Java data types which is used as an intermediate representation after type resolution. - * This class and it's subtypes have to be immutable (e.g. no mutators) to ensure side effect freedom. - * Immutability and final subtypes are essential for future parallel processing. - * - * @since Studienarbeit Type Erasure - * @author etiennezink - */ -public abstract class IntermediateType { - - @Override - public abstract boolean equals(Object o); - - @Override - public abstract int hashCode(); - - public abstract String getSignature(); - - @Override - public String toString() { return getSignature(); } -} diff --git a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateWildcard.java b/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateWildcard.java deleted file mode 100644 index 92020d10..00000000 --- a/src/main/java/de/dhbwstuttgart/intermediate/types/IntermediateWildcard.java +++ /dev/null @@ -1,33 +0,0 @@ -package de.dhbwstuttgart.intermediate.types; - -/** - * Represents a Java wildcard {@code <?>}. - * - * @since Studienarbeit Type Erasure - * @author etiennezink - */ -public final class IntermediateWildcard extends IntermediateType{ - - /** - * Caches the hashCode after first computation. - */ - private int hashCode; - - @Override - public boolean equals(Object o) { return o instanceof IntermediateWildcard; } - - @Override - public int hashCode() { - int prime = 31; - int hashCode = this.hashCode; - if (hashCode == 0){ - hashCode += "wildcard".hashCode(); - hashCode = prime * hashCode + "*".hashCode(); - this.hashCode = hashCode; - } - return hashCode; - } - - @Override - public String getSignature() { return "*"; } -} diff --git a/src/test/java/intermediate/generation/FunNTest.java b/src/test/java/intermediate/generation/FunNTest.java deleted file mode 100644 index d94595cd..00000000 --- a/src/test/java/intermediate/generation/FunNTest.java +++ /dev/null @@ -1,117 +0,0 @@ -package intermediate.generation; - -import de.dhbwstuttgart.intermediate.generation.FunN; -import de.dhbwstuttgart.intermediate.types.IntermediateGenericType; -import de.dhbwstuttgart.intermediate.types.IntermediateRefType; -import de.dhbwstuttgart.parser.scope.JavaClassName; -import org.junit.BeforeClass; -import org.junit.Test; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Type; - -import java.util.Arrays; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.objectweb.asm.Opcodes.*; - -public class FunNTest { - - private static FunN fun0T; - - private static String fun1IntIntSignature; - private static String fun1IntIntDescriptor; - private static FunN fun1IntInt; - - private static FunN fun2IntIntString; - - @BeforeClass - public static void SetUp(){ - IntermediateRefType integer = new IntermediateRefType(new JavaClassName(Type.getInternalName(Integer.class))); - IntermediateRefType string = new IntermediateRefType(new JavaClassName(Type.getInternalName(String.class))); - - fun0T = new FunN(new IntermediateGenericType("T")); - - fun1IntIntSignature = "LFun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$;"; - fun1IntIntDescriptor = "LFun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$;"; - fun1IntInt = new FunN(Arrays.asList(integer), integer); - - fun2IntIntString = new FunN(Arrays.asList(integer, integer), string); - } - - @Test - public void SignatureTest_Fun1IntegerInteger(){ assertEquals(fun1IntIntSignature, fun1IntInt.getSignature()); } - - @Test - public void DescriptorTest_Fun1IntegerInteger(){ assertEquals(fun1IntIntDescriptor, fun1IntInt.getDescriptor()); } - - @Test - public void BytecodeTest_Super0(){ assertArrayEquals(generatedASMFun0(), fun0T.getSuperBytecode()) ;} - - @Test - public void BytecodeTest_Fun0T(){ assertArrayEquals(generatedASMFun0T(), fun0T.getBytecode()) ;} - - @Test - public void BytecodeTest_Super1(){ assertArrayEquals(generatedASMFun1(), fun1IntInt.getSuperBytecode()) ;} - - @Test - public void BytecodeTest_Fun1IntInt(){ assertArrayEquals(generatedASMFun1IntInt(), fun1IntInt.getBytecode()) ;} - - @Test - public void BytecodeTest_Super2(){ assertArrayEquals(generatedASMFun2(), fun2IntIntString.getSuperBytecode()) ;} - - @Test - public void BytecodeTest_Fun2IntIntString(){ assertArrayEquals(generatedASMFun2IntIntString(), fun2IntIntString.getBytecode()) ;} - - private byte[] generatedASMFun0() { - ClassWriter classWriter = new ClassWriter(0); - MethodVisitor methodVisitor; - classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "Fun0$$", "Ljava/lang/Object;", "java/lang/Object", null); - methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, "apply", "()Ljava/lang/Object;", "()TR;", null); - methodVisitor.visitEnd(); - classWriter.visitEnd(); - return classWriter.toByteArray(); - } - - private byte[] generatedASMFun0T() { - ClassWriter classWriter = new ClassWriter(0); - classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "Fun0$$TT$_$", "Ljava/lang/Object;LFun0$$;", "java/lang/Object", new String[]{"Fun0$$"}); - classWriter.visitEnd(); - return classWriter.toByteArray(); - } - - private byte[] generatedASMFun1() { - ClassWriter classWriter = new ClassWriter(0); - MethodVisitor methodVisitor; - classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "Fun1$$", "Ljava/lang/Object;", "java/lang/Object", null); - methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, "apply", "(Ljava/lang/Object;)Ljava/lang/Object;", "(TT1;)TR;", null); - methodVisitor.visitEnd(); - classWriter.visitEnd(); - return classWriter.toByteArray(); - } - - private byte[] generatedASMFun1IntInt() { - ClassWriter classWriter = new ClassWriter(0); - classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "Fun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$", "Ljava/lang/Object;LFun1$$;", "java/lang/Object", new String[]{"Fun1$$"}); - classWriter.visitEnd(); - return classWriter.toByteArray(); - } - - private byte[] generatedASMFun2() { - ClassWriter classWriter = new ClassWriter(0); - MethodVisitor methodVisitor; - classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "Fun2$$", "Ljava/lang/Object;", "java/lang/Object", null); - methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, "apply", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", "(TT1;TT2;)TR;", null); - methodVisitor.visitEnd(); - classWriter.visitEnd(); - return classWriter.toByteArray(); - } - - private byte[] generatedASMFun2IntIntString() { - ClassWriter classWriter = new ClassWriter(0); - classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "Fun2$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$Ljava$lang$String$_$", "Ljava/lang/Object;LFun2$$;", "java/lang/Object", new String[]{"Fun2$$"}); - classWriter.visitEnd(); - return classWriter.toByteArray(); - } -} diff --git a/src/test/java/intermediate/types/IntermediateExtensWildcardTest.java b/src/test/java/intermediate/types/IntermediateExtensWildcardTest.java deleted file mode 100644 index f097310a..00000000 --- a/src/test/java/intermediate/types/IntermediateExtensWildcardTest.java +++ /dev/null @@ -1,62 +0,0 @@ -package intermediate.types; - -import de.dhbwstuttgart.intermediate.types.IntermediateExtendsWildcard; -import de.dhbwstuttgart.intermediate.types.IntermediateGenericType; -import de.dhbwstuttgart.intermediate.types.IntermediateRefType; -import de.dhbwstuttgart.parser.scope.JavaClassName; -import org.junit.BeforeClass; -import org.junit.Test; -import org.objectweb.asm.Type; - -import java.util.Arrays; -import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; - -public class IntermediateExtensWildcardTest { - - private static String integerWildcardSignature; - private static IntermediateRefType integerWildcard; - - private static String tWildcardSignature; - private static IntermediateRefType tWildcard; - - private static IntermediateRefType tWildcardSame; - - @BeforeClass - public static void StartUp(){ - - integerWildcardSignature = "Ljava/util/List<+Ljava/lang/Integer;>;"; - integerWildcard = new IntermediateRefType( - new JavaClassName(Type.getInternalName(List.class)), - Arrays.asList(new IntermediateExtendsWildcard(new IntermediateRefType(new JavaClassName(Type.getInternalName(Integer.class)))))); - - tWildcardSignature = "Ljava/util/List<+TT;>;"; - tWildcard = new IntermediateRefType( - new JavaClassName(Type.getInternalName(List.class)), - Arrays.asList(new IntermediateExtendsWildcard(new IntermediateGenericType("T")))); - - tWildcardSame = new IntermediateRefType( - new JavaClassName(Type.getInternalName(List.class)), - Arrays.asList(new IntermediateExtendsWildcard(new IntermediateGenericType("T")))); - } - - @Test - public void SignatureTest_Integer(){ assertEquals(integerWildcardSignature, integerWildcard.getSignature()); } - - @Test - public void SignatureTest_T(){ assertEquals(tWildcardSignature, tWildcard.getSignature()); } - - @Test - public void HashCodeTest_Succeed() { assertEquals(tWildcardSame.hashCode(), tWildcard.hashCode());} - - @Test - public void HashCodeTest_Fail() { assertNotEquals(tWildcardSame.hashCode(), integerWildcard.hashCode()); } - - @Test - public void EqualsTest_Succeed() { assertEquals(tWildcardSame, tWildcard); } - - @Test - public void EqualsTest_Fail() { assertNotEquals(tWildcardSame, integerWildcard); } -} diff --git a/src/test/java/intermediate/types/IntermediateGenericTypeTest.java b/src/test/java/intermediate/types/IntermediateGenericTypeTest.java deleted file mode 100644 index f680e5c3..00000000 --- a/src/test/java/intermediate/types/IntermediateGenericTypeTest.java +++ /dev/null @@ -1,80 +0,0 @@ -package intermediate.types; - -import de.dhbwstuttgart.intermediate.types.IntermediateGenericType; -import de.dhbwstuttgart.intermediate.types.IntermediateRefType; -import de.dhbwstuttgart.parser.scope.JavaClassName; -import org.junit.BeforeClass; -import org.junit.Test; -import org.objectweb.asm.Type; - -import java.util.Arrays; -import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; - -public class IntermediateGenericTypeTest { - - private static String tSignature; - private static String tDescriptor; - private static IntermediateGenericType t; - - private static String sExtendsStringSignature; - private static String sExtendsStringDescriptor; - private static IntermediateGenericType sExtendsString; - - private static String rExtendsSSignature; - private static String rExtendsSDescriptor; - private static IntermediateGenericType rExtendsS; - - private static IntermediateGenericType rSame; - - @BeforeClass - public static void StartUp(){ - tSignature = "TT;"; - tDescriptor = "Ljava/lang/Object;"; - t = new IntermediateGenericType("T"); - - sExtendsStringSignature = "TS;"; - sExtendsStringDescriptor = "Ljava/util/List;"; - sExtendsString = new IntermediateGenericType("S", - new IntermediateRefType(new JavaClassName(Type.getInternalName(List.class)), - Arrays.asList(new IntermediateRefType(new JavaClassName(Type.getInternalName(Integer.class)))))); - - rExtendsSSignature = "TR;"; - rExtendsSDescriptor = sExtendsStringDescriptor; - rExtendsS = new IntermediateGenericType("R", sExtendsString); - - rSame = new IntermediateGenericType("R", sExtendsString); - } - - @Test - public void SignatureTest_T(){ assertEquals(tSignature, t.getSignature()); } - - @Test - public void DescriptorTest_T(){ assertEquals(tDescriptor, t.getDescriptor()); } - - @Test - public void SignatureTest_TExtendsString(){ assertEquals(sExtendsStringSignature, sExtendsString.getSignature()); } - - @Test - public void DescriptorTest_TExtendsString(){ assertEquals(sExtendsStringDescriptor, sExtendsString.getDescriptor()); } - - @Test - public void SignatureTest_TExtendsS(){ assertEquals(rExtendsSSignature, rExtendsS.getSignature()); } - - @Test - public void DescriptorTest_TExtendsS(){ assertEquals(rExtendsSDescriptor, rExtendsS.getDescriptor()); } - - @Test - public void HashCodeTest_Succeed() { assertEquals(rSame.hashCode(), rExtendsS.hashCode());} - - @Test - public void HashCodeTest_Fail() { assertNotEquals(rSame.hashCode(), t.hashCode()); } - - @Test - public void EqualsTest_Succeed() { assertEquals(rSame, rExtendsS); } - - @Test - public void EqualsTest_Fail() { assertNotEquals(rSame, t); } -} diff --git a/src/test/java/intermediate/types/IntermediateRefTypeTest.java b/src/test/java/intermediate/types/IntermediateRefTypeTest.java deleted file mode 100644 index fdcca7e2..00000000 --- a/src/test/java/intermediate/types/IntermediateRefTypeTest.java +++ /dev/null @@ -1,107 +0,0 @@ -package intermediate.types; - -import de.dhbwstuttgart.intermediate.types.IntermediateGenericType; -import de.dhbwstuttgart.intermediate.types.IntermediateRefType; -import de.dhbwstuttgart.parser.scope.JavaClassName; - -import org.junit.BeforeClass; -import org.junit.Test; -import org.objectweb.asm.Type; - -import java.util.Arrays; -import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; - -public class IntermediateRefTypeTest { - - private static String integerSignature; - private static String integerDescriptor; - private static IntermediateRefType typeToTest_Integer; - - private static String listOfIntegerSignature; - private static String listOfIntegerDescriptor; - private static IntermediateRefType typeToTest_ListOfInteger; - - private static String listOfTSignature; - private static String listOfTDescriptor; - private static IntermediateRefType typeToTest_ListOfT; - - private static String voidSignature; - private static String voidDescriptor; - private static IntermediateRefType typeToTest_void; - - private static IntermediateRefType typeToTest_ListOfIntegerSame; - - @BeforeClass - public static void StartUp(){ - integerSignature = "Ljava/lang/Integer;"; - integerDescriptor = "Ljava/lang/Integer;"; - typeToTest_Integer = new IntermediateRefType(new JavaClassName(Type.getInternalName(Integer.class))); - - listOfIntegerSignature = "Ljava/util/List;"; - listOfIntegerDescriptor = "Ljava/util/List;"; - typeToTest_ListOfInteger = new IntermediateRefType( - new JavaClassName(Type.getInternalName(List.class)), - Arrays.asList(typeToTest_Integer)); - - listOfTSignature = "Ljava/util/List;"; - listOfTDescriptor = "Ljava/util/List;"; - typeToTest_ListOfT = new IntermediateRefType( - new JavaClassName(Type.getInternalName(List.class)), - Arrays.asList(new IntermediateGenericType("T"))); - - voidSignature = "V"; - voidDescriptor = "V"; - typeToTest_void = new IntermediateRefType(new JavaClassName("void")); - - typeToTest_ListOfIntegerSame = new IntermediateRefType( - new JavaClassName(Type.getInternalName(List.class)), - Arrays.asList(typeToTest_Integer)); - } - - @Test - public void SignatureTest_Integer(){ - assertEquals(integerSignature, typeToTest_Integer.getSignature()); - } - - @Test - public void DescriptorTest_Integer(){ - assertEquals(integerDescriptor, typeToTest_Integer.getDescriptor()); - } - - @Test - public void SignatureTest_List(){ assertEquals(listOfIntegerSignature, typeToTest_ListOfInteger.getSignature()); } - - @Test - public void DescriptorTest_List(){ assertEquals(listOfIntegerDescriptor, typeToTest_ListOfInteger.getDescriptor()); } - - @Test - public void SignatureTest_ListT(){ assertEquals(listOfTSignature, typeToTest_ListOfT.getSignature()); } - - @Test - public void DescriptorTest_ListT(){ assertEquals(listOfTDescriptor, typeToTest_ListOfT.getDescriptor()); } - - @Test - public void SignatureTest_Void(){ - assertEquals(voidSignature, typeToTest_void.getSignature()); - } - - @Test - public void DescriptorTest_Void(){ - assertEquals(voidDescriptor, typeToTest_void.getDescriptor()); - } - - @Test - public void HashCodeTest_Succeed() { assertEquals(typeToTest_ListOfIntegerSame.hashCode(), typeToTest_ListOfInteger.hashCode());} - - @Test - public void HashCodeTest_Fail() { assertNotEquals(typeToTest_ListOfIntegerSame.hashCode(), typeToTest_Integer.hashCode()); } - - @Test - public void EqualsTest_Succeed() { assertEquals(typeToTest_ListOfIntegerSame, typeToTest_ListOfInteger); } - - @Test - public void EqualsTest_Fail() { assertNotEquals(typeToTest_ListOfIntegerSame, typeToTest_Integer); } -} diff --git a/src/test/java/intermediate/types/IntermediateSuperWildcardTest.java b/src/test/java/intermediate/types/IntermediateSuperWildcardTest.java deleted file mode 100644 index 4571ddf5..00000000 --- a/src/test/java/intermediate/types/IntermediateSuperWildcardTest.java +++ /dev/null @@ -1,62 +0,0 @@ -package intermediate.types; - -import de.dhbwstuttgart.intermediate.types.IntermediateGenericType; -import de.dhbwstuttgart.intermediate.types.IntermediateRefType; -import de.dhbwstuttgart.intermediate.types.IntermediateSuperWildcard; -import de.dhbwstuttgart.parser.scope.JavaClassName; -import org.junit.BeforeClass; -import org.junit.Test; -import org.objectweb.asm.Type; - -import java.util.Arrays; -import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; - -public class IntermediateSuperWildcardTest { - - private static String integerWildcardSignature; - private static IntermediateRefType integerWildcard; - - private static String tWildcardSignature; - private static IntermediateRefType tWildcard; - - private static IntermediateRefType tWildcardSame; - - @BeforeClass - public static void StartUp(){ - - integerWildcardSignature = "Ljava/util/List<-Ljava/lang/Integer;>;"; - integerWildcard = new IntermediateRefType( - new JavaClassName(Type.getInternalName(List.class)), - Arrays.asList(new IntermediateSuperWildcard(new IntermediateRefType(new JavaClassName(Type.getInternalName(Integer.class)))))); - - tWildcardSignature = "Ljava/util/List<-TT;>;"; - tWildcard = new IntermediateRefType( - new JavaClassName(Type.getInternalName(List.class)), - Arrays.asList(new IntermediateSuperWildcard(new IntermediateGenericType("T")))); - - tWildcardSame = new IntermediateRefType( - new JavaClassName(Type.getInternalName(List.class)), - Arrays.asList(new IntermediateSuperWildcard(new IntermediateGenericType("T")))); - } - - @Test - public void SignatureTest_Integer(){ assertEquals(integerWildcardSignature, integerWildcard.getSignature()); } - - @Test - public void SignatureTest_T(){ assertEquals(tWildcardSignature, tWildcard.getSignature()); } - - @Test - public void HashCodeTest_Succeed() { assertEquals(tWildcardSame.hashCode(), tWildcard.hashCode());} - - @Test - public void HashCodeTest_Fail() { assertNotEquals(tWildcardSame.hashCode(), integerWildcard.hashCode()); } - - @Test - public void EqualsTest_Succeed() { assertEquals(tWildcardSame, tWildcard); } - - @Test - public void EqualsTest_Fail() { assertNotEquals(tWildcardSame, integerWildcard); } -} diff --git a/src/test/java/intermediate/types/IntermediateWildcardTest.java b/src/test/java/intermediate/types/IntermediateWildcardTest.java deleted file mode 100644 index b804d9e9..00000000 --- a/src/test/java/intermediate/types/IntermediateWildcardTest.java +++ /dev/null @@ -1,57 +0,0 @@ -package intermediate.types; - -import de.dhbwstuttgart.intermediate.types.IntermediateExtendsWildcard; -import de.dhbwstuttgart.intermediate.types.IntermediateGenericType; -import de.dhbwstuttgart.intermediate.types.IntermediateRefType; -import de.dhbwstuttgart.intermediate.types.IntermediateWildcard; -import de.dhbwstuttgart.parser.scope.JavaClassName; -import org.junit.BeforeClass; -import org.junit.Test; -import org.objectweb.asm.Type; - -import java.util.Arrays; -import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; - -public class IntermediateWildcardTest { - - private static String wildcardSignature; - private static IntermediateRefType wildcard; - - private static IntermediateRefType wildcardSame; - private static IntermediateRefType tWildcard; - - @BeforeClass - public static void StartUp(){ - - wildcardSignature = "Ljava/util/List<*>;"; - wildcard = new IntermediateRefType( - new JavaClassName(Type.getInternalName(List.class)), - Arrays.asList(new IntermediateWildcard())); - - wildcardSame = new IntermediateRefType( - new JavaClassName(Type.getInternalName(List.class)), - Arrays.asList(new IntermediateWildcard())); - - tWildcard = new IntermediateRefType( - new JavaClassName(Type.getInternalName(List.class)), - Arrays.asList(new IntermediateExtendsWildcard(new IntermediateGenericType("T")))); - } - - @Test - public void SignatureTest_Wildcard(){ assertEquals(wildcardSignature, wildcard.getSignature()); } - - @Test - public void HashCodeTest_Succeed() { assertEquals(wildcardSame.hashCode(), wildcard.hashCode());} - - @Test - public void HashCodeTest_Fail() { assertNotEquals(wildcardSame.hashCode(), tWildcard.hashCode()); } - - @Test - public void EqualsTest_Succeed() { assertEquals(wildcardSame, wildcard); } - - @Test - public void EqualsTest_Fail() { assertNotEquals(wildcardSame, tWildcard); } -} From d8bdcf854c0251b02aae56f407289123b7502b6d Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Tue, 29 Mar 2022 08:56:38 +0200 Subject: [PATCH 28/69] Refactoring der Bytecodegenerierung und Anpassung von Kommentaren. --- .../bytecode/BytecodeGenMethod.java | 66 ++++--------------- .../bytecode/descriptor/TypeToDescriptor.java | 1 - .../bytecode/funN/FunNUtilities.java | 2 + .../bytecode/signature/TypeToSignature.java | 1 - 4 files changed, 13 insertions(+), 57 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index 526eaa7a..8fcebbf0 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -592,28 +592,7 @@ public class BytecodeGenMethod implements StatementVisitor { this.lamCounter++; String typeErasure = createDescriptorWithTypeErasure(lambdaExpression); - //ByteCodeForFunNGenerator.generateBCForFunN(lambdaExpression, typeErasure,path); //old - //ToDo Etienne: umbauen - //ToDo Refactor - /* - FunN f; - ASTToIntermediate converter = new ASTToIntermediate(); - //Fehler in return Typ - IntermediateInnerType returnType = (IntermediateInnerType) converter.convert(resolver.resolve(lambdaExpression.getReturnType())); - List arguments = lambdaExpression.params - .getFormalparalist() - .stream() - .map(FormalParameter::getType) - .map(resolver::resolve) - .map(converter::convert) - .filter(t -> t instanceof IntermediateInnerType) - .map(t -> (IntermediateInnerType) t) - .collect(Collectors.toList());//ToDo - f = new FunN(arguments, returnType); - FunN.writeClassFile(f.getSuperClassName(), f.getSuperBytecode(), path); - FunN.writeClassFile(f.getClassName(), f.getBytecode(), path); - */ - ///* + //ToDo Etienne: Double Check RefTypeOrTPHOrWildcardOrGeneric returnType = resolver.resolve(lambdaExpression.getReturnType()); List argumentTypes = lambdaExpression .params @@ -623,12 +602,11 @@ public class BytecodeGenMethod implements StatementVisitor { .map(resolver::resolve) .collect(Collectors.toList()); FunNUtilities funNUtilities = FunNGenerator.getInstance(); - byte[] superBytecode = funNUtilities.generateSuperBytecode(argumentTypes.size()); - byte[] specializedBytecode = funNUtilities.generateSpecializedBytecode(argumentTypes, returnType); - FunNUtilities.writeClassFile(funNUtilities.getSuperClassName(argumentTypes.size()), superBytecode, path); - FunNUtilities.writeClassFile(funNUtilities.getSpecializedClassName(argumentTypes, returnType), specializedBytecode, path); - //*/ - //ToDo Etienne: umbauen end + FunNUtilities.writeClassFile(funNUtilities.getSuperClassName(argumentTypes.size()), + funNUtilities.generateSuperBytecode(argumentTypes.size()), path); + FunNUtilities.writeClassFile(funNUtilities.getSpecializedClassName(argumentTypes, returnType), + funNUtilities.generateSpecializedBytecode(argumentTypes, returnType), path); + Lambda lam = new Lambda(lambdaExpression); String lamDesc = lam.accept(new DescriptorToString(resultSet)); // Call site, which, when invoked, returns an instance of the functional @@ -850,26 +828,7 @@ public class BytecodeGenMethod implements StatementVisitor { } else if(!helper.isInCurrPkg(clazz)){ if(clazz.contains(CONSTANTS.$$)) { mDesc = helper.getDescriptorOfApplyMethod(methCallType); - //helper.generateBCForFunN(mDesc); //old - //ToDo Etienne: Refactor - /* - FunN f; - ASTToIntermediate converter = new ASTToIntermediate(); - IntermediateInnerType returnType = (IntermediateInnerType) converter.convert(resolver.resolve(methodCall.getType())); - List arguments = methodCall - .argTypes - .stream() - .map(resolver::resolve) - .map(converter::convert) - .filter(t -> t instanceof IntermediateInnerType) - .map(t -> (IntermediateInnerType) t) - .collect(Collectors.toList());//ToDo - f = new FunN(arguments, returnType); - - FunN.writeClassFile(f.getSuperClassName(), f.getSuperBytecode(), path); - FunN.writeClassFile(f.getClassName(), f.getBytecode(), path); - */ - ///* + //ToDo Etienne: Double Check RefTypeOrTPHOrWildcardOrGeneric returnType = resolver.resolve(methodCall.getType()); List argumentTypes = methodCall .argTypes @@ -877,13 +836,10 @@ public class BytecodeGenMethod implements StatementVisitor { .map(resolver::resolve) .collect(Collectors.toList()); FunNUtilities funNUtilities = FunNGenerator.getInstance(); - byte[] superBytecode = funNUtilities.generateSuperBytecode(argumentTypes.size()); - byte[] specializedBytecode = funNUtilities.generateSpecializedBytecode(argumentTypes, returnType); - FunNUtilities.writeClassFile(funNUtilities.getSuperClassName(argumentTypes.size()), superBytecode, path); - FunNUtilities.writeClassFile(funNUtilities.getSpecializedClassName(argumentTypes, returnType), specializedBytecode, path); - //*/ - //ToDo Etienne End -// mDesc = helper.generateBCForFunN(methCallType,typesOfParams); + FunNUtilities.writeClassFile(funNUtilities.getSuperClassName(argumentTypes.size()), + funNUtilities.generateSuperBytecode(argumentTypes.size()), path); + FunNUtilities.writeClassFile(funNUtilities.getSpecializedClassName(argumentTypes, returnType), + funNUtilities.generateSpecializedBytecode(argumentTypes, returnType), path); }else { try { cLoader2 = new DirectoryClassLoader(path, classLoader); diff --git a/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java b/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java index dd4f62a2..932770ed 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java @@ -8,7 +8,6 @@ public class TypeToDescriptor implements TypeVisitor{ @Override public String visit(RefType refType) { - //ToDo Etienne: check if it works if (refType.getName().toString().matches("Fun\\d+\\$\\$") && refType.getParaList().size() > 0) { FunNUtilities funNUtilities = FunNGenerator.getInstance(); return funNUtilities.getSpecializedDescriptor(funNUtilities.getArguments(refType.getParaList()), funNUtilities.getReturnType(refType.getParaList())); diff --git a/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNUtilities.java b/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNUtilities.java index d545723b..7ae4da4d 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNUtilities.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNUtilities.java @@ -31,4 +31,6 @@ public interface FunNUtilities { } return false; } + + } diff --git a/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java b/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java index 53b39b3a..c3249f03 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java @@ -31,7 +31,6 @@ public class TypeToSignature implements TypeVisitor { public String visit(RefType refType) { if(refType.getName().toString().equals("void")) return "V"; - //ToDo Etienne: check if it works if (refType.getName().toString().matches("Fun\\d+\\$\\$") && refType.getParaList().size() > 0){ FunNUtilities funNUtilities = FunNGenerator.getInstance(); return funNUtilities.getSpecializedSignature(funNUtilities.getArguments(refType.getParaList()), funNUtilities.getReturnType(refType.getParaList())); From fcedec60e734329d08e346d8b46521e3ae4f1112 Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Tue, 29 Mar 2022 09:02:32 +0200 Subject: [PATCH 29/69] =?UTF-8?q?Hinzuf=C3=BCgen=20OLFunTest.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/bytecode/OLFunTest.java | 71 ++++++++++++++++---------- src/test/java/general/TestCleanUp.java | 14 +++++ 2 files changed, 58 insertions(+), 27 deletions(-) create mode 100644 src/test/java/general/TestCleanUp.java diff --git a/src/test/java/bytecode/OLFunTest.java b/src/test/java/bytecode/OLFunTest.java index 1277cdde..e2352098 100644 --- a/src/test/java/bytecode/OLFunTest.java +++ b/src/test/java/bytecode/OLFunTest.java @@ -1,52 +1,69 @@ package bytecode; -import static org.junit.Assert.assertEquals; - import java.io.File; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; -import org.junit.Test; - +import general.TestCleanUp; +import org.junit.*; import de.dhbwstuttgart.core.JavaTXCompiler; +import static org.junit.Assert.*; +/** + * Test which only checks if the class {@code OLFun} was correctly compiled. + * This is achived by verifying the existence of the three implementations of {@code m}. + * + * @since Studienarbeit Type Erasure + * @author etiennezink + */ public class OLFunTest { private static String path; private static File fileToTest; private static JavaTXCompiler compiler; private static ClassLoader loader; private static Class classToTest; - private static String pathToClassFile; + private static Class classFun1IntInt; + private static Class classFun1DoubleDouble; + private static Class classFun1StringString; private static Object instanceOfClass; - - @Test - public void generateBC() throws Exception { + + private static String generatedByteCodeDirectory = System.getProperty("user.dir") + "/src/test/resources/testBytecode/generatedBC/"; + + @BeforeClass + public static void setUp() throws Exception { path = System.getProperty("user.dir")+"/src/test/resources/bytecode/javFiles/OLFun.jav"; fileToTest = new File(path); compiler = new JavaTXCompiler(fileToTest); - compiler.generateBytecode(System.getProperty("user.dir")+"/src/test/resources/testBytecode/generatedBC/"); - pathToClassFile = System.getProperty("user.dir")+"/src/test/resources/testBytecode/generatedBC/"; - loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + compiler.generateBytecode(generatedByteCodeDirectory); + loader = new URLClassLoader(new URL[] {new URL("file://"+generatedByteCodeDirectory)}); classToTest = loader.loadClass("OLFun"); - /* + classFun1IntInt = loader.loadClass("Fun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$"); + classFun1DoubleDouble = loader.loadClass("Fun1$$Ljava$lang$Double$_$Ljava$lang$Double$_$"); + classFun1StringString = loader.loadClass("Fun1$$Ljava$lang$String$_$Ljava$lang$String$_$"); instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); - - Method m = classToTest.getDeclaredMethod("m"); - Class lambda = m.invoke(instanceOfClass).getClass(); - Method apply = lambda.getMethod("apply", Object.class); - - // Damit man auf die Methode zugreifen kann - apply.setAccessible(true); - - Integer i = 77; - - Integer result = (Integer) apply.invoke(m.invoke(instanceOfClass), i); - - assertEquals(77, result); - */ } + @Test + public void mExistsWithInteger() throws Exception{ + Method m = classToTest.getDeclaredMethod("m", classFun1IntInt ,Integer.class); + assertNotNull(m); + } + @Test + public void mExistsWithDouble() throws Exception{ + Method m = classToTest.getDeclaredMethod("m", classFun1DoubleDouble ,Double.class); + assertNotNull(m); + } + + @Test + public void mExistsWithString() throws Exception{ + Method m = classToTest.getDeclaredMethod("m", classFun1StringString ,String.class); + assertNotNull(m); + } + + @AfterClass + public static void cleanUp(){ + TestCleanUp.cleanUpDirectory(new File(generatedByteCodeDirectory), f -> f.getName().contains(".class")); + } } diff --git a/src/test/java/general/TestCleanUp.java b/src/test/java/general/TestCleanUp.java new file mode 100644 index 00000000..f1b82cc8 --- /dev/null +++ b/src/test/java/general/TestCleanUp.java @@ -0,0 +1,14 @@ +package general; + +import java.io.File; +import java.io.FileFilter; + +public class TestCleanUp { + + public static void cleanUpDirectory(File directory, FileFilter fileFilter){ + if(!directory.isDirectory()) throw new RuntimeException("Directory for bytecode generation is wrong!"); + for (File file: directory.listFiles(fileFilter)) { + file.delete(); + } + } +} From 4ed30f11f73d359ebe5bc20d2ce8a82f1106a9dd Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Tue, 29 Mar 2022 15:00:52 +0200 Subject: [PATCH 30/69] =?UTF-8?q?=C3=84nderung:=20Spezialisierte=20FunN=20?= =?UTF-8?q?beinhaltet=20TPH=20im=20Namen=20und=20dieser=20wird=20FunN=20al?= =?UTF-8?q?s=20Generic=20hinzugef=C3=BCgt.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bytecode/descriptor/TypeToDescriptor.java | 8 ++++- .../bytecode/funN/FunNGenerator.java | 30 +++++++++++++------ .../bytecode/signature/TypeToSignature.java | 15 +++++++--- src/test/java/bytecode/OLFunTest.java | 12 ++++---- .../resources/bytecode/javFiles/OLFun.jav | 5 ++-- 5 files changed, 47 insertions(+), 23 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java b/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java index 932770ed..ca1b9476 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java @@ -6,9 +6,15 @@ import de.dhbwstuttgart.syntaxtree.type.*; public class TypeToDescriptor implements TypeVisitor{ + private final boolean specializedFunN; + + public TypeToDescriptor(){ this(false); } + + public TypeToDescriptor(boolean specializedFunN) { this.specializedFunN = specializedFunN; } + @Override public String visit(RefType refType) { - if (refType.getName().toString().matches("Fun\\d+\\$\\$") && refType.getParaList().size() > 0) { + if (refType.getName().toString().matches("Fun\\d+\\$\\$") && specializedFunN) { FunNUtilities funNUtilities = FunNGenerator.getInstance(); return funNUtilities.getSpecializedDescriptor(funNUtilities.getArguments(refType.getParaList()), funNUtilities.getReturnType(refType.getParaList())); } diff --git a/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java b/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java index c9eae6b0..6e2b57e7 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java @@ -16,10 +16,16 @@ import java.io.File; import java.io.FileOutputStream; import java.util.List; import java.util.stream.Collectors; +import java.util.stream.Stream; import static org.objectweb.asm.Opcodes.*; -//ToDo Kommentieren +/** + * //ToDo beschreiben + * + * @since Studienarbeit Type Erasure + * @author etiennezink + */ public class FunNGenerator implements FunNUtilities{ private static FunNGenerator funNGenerator = new FunNGenerator(); @@ -37,8 +43,9 @@ public class FunNGenerator implements FunNUtilities{ private final RefType objectRefType = new RefType(new JavaClassName(objectSuperType), null); private final String objectSignature = applySignature(objectRefType); - private static String applyDescriptor(RefTypeOrTPHOrWildcardOrGeneric a) { return a.acceptTV(new TypeToDescriptor()); } - private static String applySignature(RefTypeOrTPHOrWildcardOrGeneric a) { return a.acceptTV(new TypeToSignature()); } + private static String applyDescriptor(RefTypeOrTPHOrWildcardOrGeneric a) { return a.acceptTV(new TypeToDescriptor(true)); } + private static String applySignature(RefTypeOrTPHOrWildcardOrGeneric a) { return a.acceptTV(new TypeToSignature(true)); } + private static String applyNameDescriptor(RefTypeOrTPHOrWildcardOrGeneric a){ return a instanceof TypePlaceholder ? applySignature(a)+";" : String.format("L%s;", applyDescriptor(a)); } @Override public byte[] generateSuperBytecode(int numberArguments) { @@ -71,17 +78,24 @@ public class FunNGenerator implements FunNUtilities{ @Override public byte[] generateSpecializedBytecode(List argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType) { - StringBuilder funNClassSignature = new StringBuilder(objectSignature + applySignature(new RefType(new JavaClassName(getSuperClassName(argumentTypes.size())), null))); + List parameters = Stream + .concat(argumentTypes.stream(), Stream.of(returnType)) + .collect(Collectors.toList()); + RefType superFunN = new RefType(new JavaClassName(getSuperClassName(argumentTypes.size())), parameters , null); + StringBuilder funNClassSignature = new StringBuilder(objectSignature + (superFunN.acceptTV(new TypeToSignature()))); boolean containsGeneric = false; String genericSignature = "<"; for (int currentTypArgumentIndex = 0; currentTypArgumentIndex < argumentTypes.size(); currentTypArgumentIndex++) { RefTypeOrTPHOrWildcardOrGeneric typArgument = argumentTypes.get(currentTypArgumentIndex); - if (typArgument == null) continue; if (typArgument instanceof GenericRefType){ GenericRefType generic = (GenericRefType) typArgument; genericSignature += String.format("%s:%s", generic.getParsedName(), applyDescriptor(generic)); containsGeneric = true; + } else if(typArgument instanceof TypePlaceholder){ + TypePlaceholder placeholder = (TypePlaceholder) typArgument; + genericSignature += String.format("%s:%s", applySignature(placeholder).substring(1), objectSignature); + containsGeneric = true; } } genericSignature += ">"; @@ -100,11 +114,9 @@ public class FunNGenerator implements FunNUtilities{ argumentTypes.size(), argumentTypes .stream() - .map(r -> r instanceof TypePlaceholder ? objectRefType : r) - .map(FunNGenerator::applyDescriptor) - .map(d -> String.format("L%s;", d)) + .map(FunNGenerator::applyNameDescriptor) .collect(Collectors.joining()), - applyDescriptor(returnType)) + applyNameDescriptor(returnType)) .replace('/', '$') .replace(";", "$_$"); } diff --git a/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java b/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java index c3249f03..52c12cb7 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java @@ -19,19 +19,26 @@ import de.dhbwstuttgart.syntaxtree.type.TypeVisitor; public class TypeToSignature implements TypeVisitor { private List constraints; - public TypeToSignature() { - this.constraints = new ArrayList<>(); - } + private final boolean specializedFunN; + + public TypeToSignature() { this(new ArrayList<>(), false); } + + public TypeToSignature(boolean specializedFunN) { this(new ArrayList<>(), specializedFunN); } public TypeToSignature(List constraints) { + this(constraints, false); + } + + public TypeToSignature(List constraints, boolean specializedFunN){ this.constraints = constraints; + this.specializedFunN = specializedFunN; } @Override public String visit(RefType refType) { if(refType.getName().toString().equals("void")) return "V"; - if (refType.getName().toString().matches("Fun\\d+\\$\\$") && refType.getParaList().size() > 0){ + if (refType.getName().toString().matches("Fun\\d+\\$\\$") && specializedFunN){ FunNUtilities funNUtilities = FunNGenerator.getInstance(); return funNUtilities.getSpecializedSignature(funNUtilities.getArguments(refType.getParaList()), funNUtilities.getReturnType(refType.getParaList())); } diff --git a/src/test/java/bytecode/OLFunTest.java b/src/test/java/bytecode/OLFunTest.java index e2352098..3142ce26 100644 --- a/src/test/java/bytecode/OLFunTest.java +++ b/src/test/java/bytecode/OLFunTest.java @@ -38,19 +38,19 @@ public class OLFunTest { compiler.generateBytecode(generatedByteCodeDirectory); loader = new URLClassLoader(new URL[] {new URL("file://"+generatedByteCodeDirectory)}); classToTest = loader.loadClass("OLFun"); - classFun1IntInt = loader.loadClass("Fun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$"); - classFun1DoubleDouble = loader.loadClass("Fun1$$Ljava$lang$Double$_$Ljava$lang$Double$_$"); - classFun1StringString = loader.loadClass("Fun1$$Ljava$lang$String$_$Ljava$lang$String$_$"); instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + //classFun1IntInt = loader.loadClass("Fun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$"); + //classFun1DoubleDouble = loader.loadClass("Fun1$$Ljava$lang$Double$_$Ljava$lang$Double$_$"); + classFun1StringString = loader.loadClass("Fun1$$Ljava$lang$String$_$Ljava$lang$String$_$"); } - @Test + //@Test public void mExistsWithInteger() throws Exception{ Method m = classToTest.getDeclaredMethod("m", classFun1IntInt ,Integer.class); assertNotNull(m); } - @Test + //@Test public void mExistsWithDouble() throws Exception{ Method m = classToTest.getDeclaredMethod("m", classFun1DoubleDouble ,Double.class); assertNotNull(m); @@ -62,7 +62,7 @@ public class OLFunTest { assertNotNull(m); } - @AfterClass + //@AfterClass public static void cleanUp(){ TestCleanUp.cleanUpDirectory(new File(generatedByteCodeDirectory), f -> f.getName().contains(".class")); } diff --git a/src/test/resources/bytecode/javFiles/OLFun.jav b/src/test/resources/bytecode/javFiles/OLFun.jav index e780a06f..feffe034 100644 --- a/src/test/resources/bytecode/javFiles/OLFun.jav +++ b/src/test/resources/bytecode/javFiles/OLFun.jav @@ -1,6 +1,6 @@ import java.lang.String; -import java.lang.Integer; -import java.lang.Double; +//import java.lang.Integer; +//import java.lang.Double; import java.util.Vector; import java.lang.Boolean; @@ -10,7 +10,6 @@ import java.lang.Boolean; public class OLFun { //f = x -> {return x + x;}; - m(f, x) { x = f.apply(x+x); } From 9444ee38d63a92936c96e147ddd507e816c887c5 Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Tue, 29 Mar 2022 15:43:43 +0200 Subject: [PATCH 31/69] =?UTF-8?q?=C3=84nderung=20generateSuperBytecode()?= =?UTF-8?q?=20sodass=20dies=20nun=20korrekten=20Bytecode=20generiert.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java b/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java index 6e2b57e7..46e219aa 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java @@ -55,11 +55,11 @@ public class FunNGenerator implements FunNUtilities{ for (int currentParameter = 1; currentParameter <= numberArguments; currentParameter++){ superFunNClassSignature.append(String.format("%s%d:%s",argumentGenericBase, currentParameter, objectSignature)); - superFunNMethodSignature.append(applySignature( new GenericRefType(argumentGenericBase + currentParameter, null))); + superFunNMethodSignature.append(String.format("T%s;", applySignature( new GenericRefType(argumentGenericBase + currentParameter, null)))); superFunNMethodDescriptor.append(objectSignature); } superFunNClassSignature.append(String.format("%s:%s>%s", returnGeneric, objectSignature, objectSignature)); - superFunNMethodSignature.append(String.format(")%s", applySignature(new GenericRefType(returnGeneric, null)))); + superFunNMethodSignature.append(String.format(")T%s;", applySignature(new GenericRefType(returnGeneric, null)))); superFunNMethodDescriptor.append(String.format(")%s", objectSignature)); ClassWriter classWriter = new ClassWriter(0); From 70120104628d84aadf6040e6bf100de774f4564c Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Tue, 29 Mar 2022 15:58:10 +0200 Subject: [PATCH 32/69] Korrektur in TypeToDescriptor und TypeToSignature -> Ohne Angabe im Deskriptor wird automatisch angenommen es soll eine spezialisierte Signatur erstellt werden. --- .../bytecode/descriptor/TypeToDescriptor.java | 2 +- .../bytecode/signature/TypeToSignature.java | 12 ++++++------ src/test/resources/bytecode/javFiles/OLFun.jav | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java b/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java index ca1b9476..f10f8070 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java @@ -8,7 +8,7 @@ public class TypeToDescriptor implements TypeVisitor{ private final boolean specializedFunN; - public TypeToDescriptor(){ this(false); } + public TypeToDescriptor(){ this(true); } public TypeToDescriptor(boolean specializedFunN) { this.specializedFunN = specializedFunN; } diff --git a/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java b/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java index 52c12cb7..8e5a87dd 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java @@ -19,26 +19,26 @@ import de.dhbwstuttgart.syntaxtree.type.TypeVisitor; public class TypeToSignature implements TypeVisitor { private List constraints; - private final boolean specializedFunN; + private final boolean superFunN; - public TypeToSignature() { this(new ArrayList<>(), false); } + public TypeToSignature() { this(new ArrayList<>(), true); } public TypeToSignature(boolean specializedFunN) { this(new ArrayList<>(), specializedFunN); } public TypeToSignature(List constraints) { - this(constraints, false); + this(constraints, true); } - public TypeToSignature(List constraints, boolean specializedFunN){ + public TypeToSignature(List constraints, boolean superFunN){ this.constraints = constraints; - this.specializedFunN = specializedFunN; + this.superFunN = superFunN; } @Override public String visit(RefType refType) { if(refType.getName().toString().equals("void")) return "V"; - if (refType.getName().toString().matches("Fun\\d+\\$\\$") && specializedFunN){ + if (refType.getName().toString().matches("Fun\\d+\\$\\$") && !superFunN){ FunNUtilities funNUtilities = FunNGenerator.getInstance(); return funNUtilities.getSpecializedSignature(funNUtilities.getArguments(refType.getParaList()), funNUtilities.getReturnType(refType.getParaList())); } diff --git a/src/test/resources/bytecode/javFiles/OLFun.jav b/src/test/resources/bytecode/javFiles/OLFun.jav index feffe034..e2d6f3f7 100644 --- a/src/test/resources/bytecode/javFiles/OLFun.jav +++ b/src/test/resources/bytecode/javFiles/OLFun.jav @@ -11,6 +11,6 @@ public class OLFun { //f = x -> {return x + x;}; m(f, x) { - x = f.apply(x+x); + x = f.apply(x+x); } } \ No newline at end of file From ed00aeb056698bcecc846786f8c6794595babb97 Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Tue, 29 Mar 2022 16:20:14 +0200 Subject: [PATCH 33/69] Fixed bug mit der korrekten Signatur im Bytecode der FunN Typen. Verbesserung der BytecodeGenMethod -> Nun werden die korrekt resolveten Typen verwendet. --- .../java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java | 4 +++- .../de/dhbwstuttgart/bytecode/funN/FunNGenerator.java | 2 +- .../dhbwstuttgart/bytecode/signature/TypeToSignature.java | 8 ++++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index 8fcebbf0..5cbcfca9 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -831,8 +831,10 @@ public class BytecodeGenMethod implements StatementVisitor { //ToDo Etienne: Double Check RefTypeOrTPHOrWildcardOrGeneric returnType = resolver.resolve(methodCall.getType()); List argumentTypes = methodCall - .argTypes + .arglist + .getArguments() .stream() + .map(TypableStatement::getType) .map(resolver::resolve) .collect(Collectors.toList()); FunNUtilities funNUtilities = FunNGenerator.getInstance(); diff --git a/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java b/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java index 46e219aa..8bd512b8 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java @@ -82,7 +82,7 @@ public class FunNGenerator implements FunNUtilities{ .concat(argumentTypes.stream(), Stream.of(returnType)) .collect(Collectors.toList()); RefType superFunN = new RefType(new JavaClassName(getSuperClassName(argumentTypes.size())), parameters , null); - StringBuilder funNClassSignature = new StringBuilder(objectSignature + (superFunN.acceptTV(new TypeToSignature()))); + StringBuilder funNClassSignature = new StringBuilder(objectSignature + (superFunN.acceptTV(new TypeToSignature(false)))); boolean containsGeneric = false; String genericSignature = "<"; diff --git a/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java b/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java index 8e5a87dd..0026b85f 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java @@ -19,7 +19,7 @@ import de.dhbwstuttgart.syntaxtree.type.TypeVisitor; public class TypeToSignature implements TypeVisitor { private List constraints; - private final boolean superFunN; + private final boolean specializedFunN; public TypeToSignature() { this(new ArrayList<>(), true); } @@ -29,16 +29,16 @@ public class TypeToSignature implements TypeVisitor { this(constraints, true); } - public TypeToSignature(List constraints, boolean superFunN){ + public TypeToSignature(List constraints, boolean specializedFunN){ this.constraints = constraints; - this.superFunN = superFunN; + this.specializedFunN = specializedFunN; } @Override public String visit(RefType refType) { if(refType.getName().toString().equals("void")) return "V"; - if (refType.getName().toString().matches("Fun\\d+\\$\\$") && !superFunN){ + if (refType.getName().toString().matches("Fun\\d+\\$\\$") && specializedFunN){ FunNUtilities funNUtilities = FunNGenerator.getInstance(); return funNUtilities.getSpecializedSignature(funNUtilities.getArguments(refType.getParaList()), funNUtilities.getReturnType(refType.getParaList())); } From c65102d89a3cef669a5f0c31df91f9eec3c70bf3 Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Tue, 29 Mar 2022 17:00:06 +0200 Subject: [PATCH 34/69] =?UTF-8?q?Hinzuf=C3=BCgen=20von=20OLFun2=20und=20?= =?UTF-8?q?=C3=84nderung=20der=20Spezialisierungen=20von=20FunN,=20dass=20?= =?UTF-8?q?diese=20statt=20des=20TPH=20im=20Namen=20Object=20haben.=20Anso?= =?UTF-8?q?nsten=20werden=20diese=20nicht=20wieder=20gefunden.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bytecode/funN/FunNGenerator.java | 8 +-- src/test/java/bytecode/OLFun2Test.java | 69 +++++++++++++++++++ src/test/java/bytecode/OLFunTest.java | 15 ++-- .../resources/bytecode/javFiles/OLFun.jav | 3 - .../resources/bytecode/javFiles/OLFun2.jav | 13 ++++ 5 files changed, 93 insertions(+), 15 deletions(-) create mode 100644 src/test/java/bytecode/OLFun2Test.java create mode 100644 src/test/resources/bytecode/javFiles/OLFun2.jav diff --git a/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java b/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java index 8bd512b8..5b6a9e44 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java @@ -39,13 +39,13 @@ public class FunNGenerator implements FunNUtilities{ private final String methodName = "apply"; private final int bytecodeVersion = V1_8; - private final String objectSuperType = Type.getInternalName(Object.class).replace('.','/'); - private final RefType objectRefType = new RefType(new JavaClassName(objectSuperType), null); - private final String objectSignature = applySignature(objectRefType); + private static final String objectSuperType = Type.getInternalName(Object.class).replace('.','/'); + private static final RefType objectRefType = new RefType(new JavaClassName(objectSuperType), null); + private static final String objectSignature = applySignature(objectRefType); private static String applyDescriptor(RefTypeOrTPHOrWildcardOrGeneric a) { return a.acceptTV(new TypeToDescriptor(true)); } private static String applySignature(RefTypeOrTPHOrWildcardOrGeneric a) { return a.acceptTV(new TypeToSignature(true)); } - private static String applyNameDescriptor(RefTypeOrTPHOrWildcardOrGeneric a){ return a instanceof TypePlaceholder ? applySignature(a)+";" : String.format("L%s;", applyDescriptor(a)); } + private static String applyNameDescriptor(RefTypeOrTPHOrWildcardOrGeneric a){ return a instanceof TypePlaceholder ? applyNameDescriptor(objectRefType) : String.format("L%s;", applyDescriptor(a)); } @Override public byte[] generateSuperBytecode(int numberArguments) { diff --git a/src/test/java/bytecode/OLFun2Test.java b/src/test/java/bytecode/OLFun2Test.java new file mode 100644 index 00000000..6ec8701b --- /dev/null +++ b/src/test/java/bytecode/OLFun2Test.java @@ -0,0 +1,69 @@ +package bytecode; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.function.Function; + +import general.TestCleanUp; +import org.junit.*; +import de.dhbwstuttgart.core.JavaTXCompiler; +import static org.junit.Assert.*; + +/** + * //ToDo Etienne: Beschreiben + * + * @since Studienarbeit Type Erasure + * @author etiennezink + */ +public class OLFun2Test { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static Class classFun1IntInt; + private static Class classFun1DoubleDouble; + private static Class classFun1StringString; + + private static String generatedByteCodeDirectory = System.getProperty("user.dir") + "/src/test/resources/testBytecode/generatedBC/"; + + //ToDo Etienne: Nach Anpassung des Bytecode die Tests hinzufügen + //ToDo Etienne: Aufruf von m testen + @BeforeClass + public static void setUp() throws Exception { + path = System.getProperty("user.dir")+"/src/test/resources/bytecode/javFiles/OLFun2.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(generatedByteCodeDirectory); + loader = new URLClassLoader(new URL[] {new URL("file://"+generatedByteCodeDirectory)}); + classToTest = loader.loadClass("OLFun2"); + classFun1IntInt = loader.loadClass("Fun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$"); + classFun1DoubleDouble = loader.loadClass("Fun1$$Ljava$lang$Double$_$Ljava$lang$Double$_$"); + classFun1StringString = loader.loadClass("Fun1$$Ljava$lang$String$_$Ljava$lang$String$_$"); + } + + @Test + public void mExistsWithInteger() throws Exception{ + Method m = classToTest.getDeclaredMethod("m", classFun1IntInt); + assertNotNull(m); + } + + @Test + public void mExistsWithDouble() throws Exception{ + Method m = classToTest.getDeclaredMethod("m", classFun1DoubleDouble); + assertNotNull(m); + } + + @Test + public void mExistsWithString() throws Exception{ + Method m = classToTest.getDeclaredMethod("m", classFun1StringString); + assertNotNull(m); + } + + //@AfterClass + public static void cleanUp(){ + TestCleanUp.cleanUpDirectory(new File(generatedByteCodeDirectory), f -> f.getName().contains(".class")); + } +} diff --git a/src/test/java/bytecode/OLFunTest.java b/src/test/java/bytecode/OLFunTest.java index 3142ce26..d1910e07 100644 --- a/src/test/java/bytecode/OLFunTest.java +++ b/src/test/java/bytecode/OLFunTest.java @@ -11,8 +11,7 @@ import de.dhbwstuttgart.core.JavaTXCompiler; import static org.junit.Assert.*; /** - * Test which only checks if the class {@code OLFun} was correctly compiled. - * This is achived by verifying the existence of the three implementations of {@code m}. + * //ToDo Etienne: Beschreiben * * @since Studienarbeit Type Erasure * @author etiennezink @@ -26,10 +25,11 @@ public class OLFunTest { private static Class classFun1IntInt; private static Class classFun1DoubleDouble; private static Class classFun1StringString; - private static Object instanceOfClass; private static String generatedByteCodeDirectory = System.getProperty("user.dir") + "/src/test/resources/testBytecode/generatedBC/"; + //ToDo Etienne: Nach Anpassung des Bytecode die Tests hinzufügen + //ToDo Etienne: Aufruf von m testen @BeforeClass public static void setUp() throws Exception { path = System.getProperty("user.dir")+"/src/test/resources/bytecode/javFiles/OLFun.jav"; @@ -38,19 +38,18 @@ public class OLFunTest { compiler.generateBytecode(generatedByteCodeDirectory); loader = new URLClassLoader(new URL[] {new URL("file://"+generatedByteCodeDirectory)}); classToTest = loader.loadClass("OLFun"); - instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); - //classFun1IntInt = loader.loadClass("Fun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$"); - //classFun1DoubleDouble = loader.loadClass("Fun1$$Ljava$lang$Double$_$Ljava$lang$Double$_$"); + classFun1IntInt = loader.loadClass("Fun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$"); + classFun1DoubleDouble = loader.loadClass("Fun1$$Ljava$lang$Double$_$Ljava$lang$Double$_$"); classFun1StringString = loader.loadClass("Fun1$$Ljava$lang$String$_$Ljava$lang$String$_$"); } - //@Test + @Test public void mExistsWithInteger() throws Exception{ Method m = classToTest.getDeclaredMethod("m", classFun1IntInt ,Integer.class); assertNotNull(m); } - //@Test + @Test public void mExistsWithDouble() throws Exception{ Method m = classToTest.getDeclaredMethod("m", classFun1DoubleDouble ,Double.class); assertNotNull(m); diff --git a/src/test/resources/bytecode/javFiles/OLFun.jav b/src/test/resources/bytecode/javFiles/OLFun.jav index e2d6f3f7..4896f948 100644 --- a/src/test/resources/bytecode/javFiles/OLFun.jav +++ b/src/test/resources/bytecode/javFiles/OLFun.jav @@ -4,9 +4,6 @@ import java.lang.String; import java.util.Vector; import java.lang.Boolean; - - - public class OLFun { //f = x -> {return x + x;}; diff --git a/src/test/resources/bytecode/javFiles/OLFun2.jav b/src/test/resources/bytecode/javFiles/OLFun2.jav new file mode 100644 index 00000000..fd57e184 --- /dev/null +++ b/src/test/resources/bytecode/javFiles/OLFun2.jav @@ -0,0 +1,13 @@ +import java.lang.String; +//import java.lang.Integer; +//import java.lang.Double; +import java.util.Vector; +import java.lang.Boolean; + +public class OLFun2 { + + x; + m(f){ + x = f.apply(x + x) + } +} \ No newline at end of file From eebb07ec8b591cca0cf4abb6d7f164432db1d704 Mon Sep 17 00:00:00 2001 From: Etienne Zink Date: Tue, 29 Mar 2022 19:19:31 +0200 Subject: [PATCH 35/69] =?UTF-8?q?Verbesserung=20FunNGenerator:=20Generics?= =?UTF-8?q?=20werden=20nicht=20mehr=20mehrfach=20hinzugef=C3=BCgt.=20TPHS?= =?UTF-8?q?=20werden=20im=20Klassenname=20als=20LTPH=20angegeben,=20so=20e?= =?UTF-8?q?ntsteht=20keine=20Uneindeutigkeit=20zu=20Klassen=20mit=20Object?= =?UTF-8?q?=20(ohne=20TPH)=20im=20Klassenname.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bytecode/funN/FunNGenerator.java | 29 ++++++++++--------- .../resources/bytecode/javFiles/OLFun.jav | 4 +-- .../resources/bytecode/javFiles/OLFun2.jav | 4 +-- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java b/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java index 5b6a9e44..3a651c93 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java @@ -39,13 +39,13 @@ public class FunNGenerator implements FunNUtilities{ private final String methodName = "apply"; private final int bytecodeVersion = V1_8; - private static final String objectSuperType = Type.getInternalName(Object.class).replace('.','/'); - private static final RefType objectRefType = new RefType(new JavaClassName(objectSuperType), null); - private static final String objectSignature = applySignature(objectRefType); + private final String objectSuperType = Type.getInternalName(Object.class).replace('.','/'); + private final RefType objectRefType = new RefType(new JavaClassName(objectSuperType), null); + private final String objectSignature = applySignature(objectRefType); - private static String applyDescriptor(RefTypeOrTPHOrWildcardOrGeneric a) { return a.acceptTV(new TypeToDescriptor(true)); } - private static String applySignature(RefTypeOrTPHOrWildcardOrGeneric a) { return a.acceptTV(new TypeToSignature(true)); } - private static String applyNameDescriptor(RefTypeOrTPHOrWildcardOrGeneric a){ return a instanceof TypePlaceholder ? applyNameDescriptor(objectRefType) : String.format("L%s;", applyDescriptor(a)); } + private String applyDescriptor(RefTypeOrTPHOrWildcardOrGeneric a) { return a.acceptTV(new TypeToDescriptor(true)); } + private String applySignature(RefTypeOrTPHOrWildcardOrGeneric a) { return a.acceptTV(new TypeToSignature(true)); } + private String applyNameDescriptor(RefTypeOrTPHOrWildcardOrGeneric a){ return a instanceof TypePlaceholder ? "LTPH;" : String.format("L%s;", applyDescriptor(a)); } @Override public byte[] generateSuperBytecode(int numberArguments) { @@ -86,14 +86,16 @@ public class FunNGenerator implements FunNUtilities{ boolean containsGeneric = false; String genericSignature = "<"; - for (int currentTypArgumentIndex = 0; currentTypArgumentIndex < argumentTypes.size(); currentTypArgumentIndex++) { - RefTypeOrTPHOrWildcardOrGeneric typArgument = argumentTypes.get(currentTypArgumentIndex); - if (typArgument instanceof GenericRefType){ - GenericRefType generic = (GenericRefType) typArgument; + for (RefTypeOrTPHOrWildcardOrGeneric typeArgument : parameters) { + //ToDo Etienne: Refactor + if (typeArgument instanceof GenericRefType){ + GenericRefType generic = (GenericRefType) typeArgument; + if(genericSignature.contains(generic.getParsedName())) continue; genericSignature += String.format("%s:%s", generic.getParsedName(), applyDescriptor(generic)); containsGeneric = true; - } else if(typArgument instanceof TypePlaceholder){ - TypePlaceholder placeholder = (TypePlaceholder) typArgument; + } else if(typeArgument instanceof TypePlaceholder){ + TypePlaceholder placeholder = (TypePlaceholder) typeArgument; + if(genericSignature.contains(applySignature(placeholder).substring(1))) continue; genericSignature += String.format("%s:%s", applySignature(placeholder).substring(1), objectSignature); containsGeneric = true; } @@ -109,12 +111,11 @@ public class FunNGenerator implements FunNUtilities{ @Override public String getSpecializedClassName(List argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType) { - if (returnType instanceof TypePlaceholder) returnType = objectRefType; return String.format("Fun%d$$%s%s", argumentTypes.size(), argumentTypes .stream() - .map(FunNGenerator::applyNameDescriptor) + .map(this::applyNameDescriptor) .collect(Collectors.joining()), applyNameDescriptor(returnType)) .replace('/', '$') diff --git a/src/test/resources/bytecode/javFiles/OLFun.jav b/src/test/resources/bytecode/javFiles/OLFun.jav index 4896f948..adf8c6a8 100644 --- a/src/test/resources/bytecode/javFiles/OLFun.jav +++ b/src/test/resources/bytecode/javFiles/OLFun.jav @@ -1,6 +1,6 @@ import java.lang.String; -//import java.lang.Integer; -//import java.lang.Double; +import java.lang.Integer; +import java.lang.Double; import java.util.Vector; import java.lang.Boolean; diff --git a/src/test/resources/bytecode/javFiles/OLFun2.jav b/src/test/resources/bytecode/javFiles/OLFun2.jav index fd57e184..406c0d98 100644 --- a/src/test/resources/bytecode/javFiles/OLFun2.jav +++ b/src/test/resources/bytecode/javFiles/OLFun2.jav @@ -1,6 +1,6 @@ import java.lang.String; -//import java.lang.Integer; -//import java.lang.Double; +import java.lang.Integer; +import java.lang.Double; import java.util.Vector; import java.lang.Boolean; From dfd12422a6c5ccc4a5d13ef28f0be8e5112741d4 Mon Sep 17 00:00:00 2001 From: Andreas Stadelmeier Date: Tue, 29 Mar 2022 19:25:01 +0200 Subject: [PATCH 36/69] Set language level to Java 17. Add target AST as records --- pom.xml | 15 +++- .../target/generate/ASTToTargetAST.java | 70 +++++++++++++++++++ .../target/tree/MethodParameter.java | 6 ++ .../target/tree/TargetClass.java | 10 +++ .../target/tree/TargetConstructor.java | 7 ++ .../target/tree/TargetField.java | 7 ++ .../target/tree/TargetMethod.java | 9 +++ .../tree/type/TargetExtendsWildcard.java | 7 ++ .../target/tree/type/TargetFunNType.java | 6 ++ .../target/tree/type/TargetRefType.java | 8 +++ .../target/tree/type/TargetSuperWildcard.java | 4 ++ .../target/tree/type/TargetType.java | 5 ++ 12 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/MethodParameter.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/TargetField.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/type/TargetFunNType.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/type/TargetRefType.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/type/TargetType.java diff --git a/pom.xml b/pom.xml index 95b20386..105ce877 100644 --- a/pom.xml +++ b/pom.xml @@ -118,6 +118,14 @@ http://maven.apache.org/maven-v4_0_0.xsd"> + + org.apache.maven.plugins + maven-compiler-plugin + + 17 + 17 + + @@ -129,8 +137,11 @@ http://maven.apache.org/maven-v4_0_0.xsd"> UTF-8 UTF-8 - 1.8 - 1.8 + 17 + 17 + + --enable-preview + 0.23.0 de.dhbwstuttgart.core.ConsoleInterface diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java new file mode 100644 index 00000000..14896b83 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -0,0 +1,70 @@ +package de.dhbwstuttgart.target.generate; + +import de.dhbwstuttgart.syntaxtree.ASTVisitor; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.Field; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.type.*; +import de.dhbwstuttgart.target.tree.TargetClass; +import de.dhbwstuttgart.target.tree.TargetConstructor; +import de.dhbwstuttgart.target.tree.TargetField; +import de.dhbwstuttgart.target.tree.TargetMethod; +import de.dhbwstuttgart.target.tree.type.TargetRefType; +import de.dhbwstuttgart.target.tree.type.TargetSuperWildcard; +import de.dhbwstuttgart.target.tree.type.TargetType; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class ASTToTargetAST { + + public TargetClass convert(ClassOrInterface input, Map sigma){ + 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(it, sigma)).collect(Collectors.toList()), + input.getMethods().stream().map(it -> convert(it, sigma)).collect(Collectors.toList())); + } + + private TargetMethod convert(Method input, Map sigma) { + return null; + } + + private TargetField convert(Field input, Map sigma) { + return null; + } + + private TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, Map sigma) { + return input.acceptTV(new TypeVisitor<>() { + @Override + public TargetType visit(RefType refType) { + return new TargetRefType(refType.getName().toString(), + refType.getParaList().stream().map((it) -> convert(it, sigma)).collect(Collectors.toList())); + } + + @Override + public TargetType visit(SuperWildcardType superWildcardType) { + return new TargetSuperWildcard(convert(superWildcardType.getInnerType(), sigma)); + } + + @Override + public TargetType visit(TypePlaceholder typePlaceholder) { + return convert(sigma.get(typePlaceholder), sigma); + } + + @Override + public TargetType visit(ExtendsWildcardType extendsWildcardType) { + return null; + } + + @Override + public TargetType visit(GenericRefType genericRefType) { + return null; + } + }); + } +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/MethodParameter.java b/src/main/java/de/dhbwstuttgart/target/tree/MethodParameter.java new file mode 100644 index 00000000..4ae31828 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/MethodParameter.java @@ -0,0 +1,6 @@ +package de.dhbwstuttgart.target.tree; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record MethodParameter(TargetType type, String name) { +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java new file mode 100644 index 00000000..a78da9d3 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java @@ -0,0 +1,10 @@ +package de.dhbwstuttgart.target.tree; + +import de.dhbwstuttgart.target.tree.type.TargetRefType; +import de.dhbwstuttgart.target.tree.type.TargetType; + +import java.util.List; + +public record TargetClass(int modifiers, String qualifiedName, TargetType superType, List implementingInterfaces, + List constructors, List fields, List methods) {} + diff --git a/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java new file mode 100644 index 00000000..b93219ff --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java @@ -0,0 +1,7 @@ +package de.dhbwstuttgart.target.tree; + +import java.util.List; + +public record TargetConstructor(List parameterTypes) { +} + diff --git a/src/main/java/de/dhbwstuttgart/target/tree/TargetField.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetField.java new file mode 100644 index 00000000..cbba1dec --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetField.java @@ -0,0 +1,7 @@ +package de.dhbwstuttgart.target.tree; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetField(TargetType type, String name) { +} + diff --git a/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java new file mode 100644 index 00000000..910c12a0 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java @@ -0,0 +1,9 @@ +package de.dhbwstuttgart.target.tree; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +import java.util.List; + +public record TargetMethod(String name, List parameterTypes) { +} + diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java new file mode 100644 index 00000000..b30b85e9 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java @@ -0,0 +1,7 @@ +package de.dhbwstuttgart.target.tree.type; + +import java.util.List; + +public record TargetExtendsWildcard(TargetType innerType) implements TargetType{ +} + diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetFunNType.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetFunNType.java new file mode 100644 index 00000000..c3e86f79 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetFunNType.java @@ -0,0 +1,6 @@ +package de.dhbwstuttgart.target.tree.type; + +import java.util.List; + +public record TargetFunNType(int N, List params) implements TargetType { +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetRefType.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetRefType.java new file mode 100644 index 00000000..1c27cd62 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetRefType.java @@ -0,0 +1,8 @@ +package de.dhbwstuttgart.target.tree.type; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +import java.util.List; + +public record TargetRefType(String name, List params) implements TargetType { +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java new file mode 100644 index 00000000..421102cb --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java @@ -0,0 +1,4 @@ +package de.dhbwstuttgart.target.tree.type; + +public record TargetSuperWildcard(TargetType innerType) implements TargetType { +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetType.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetType.java new file mode 100644 index 00000000..849df99c --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetType.java @@ -0,0 +1,5 @@ +package de.dhbwstuttgart.target.tree.type; + +public sealed interface TargetType + permits TargetExtendsWildcard, TargetFunNType, TargetRefType, TargetSuperWildcard { +} From 8e80cc2985780f6193b62cc284e9f1137fb6631f Mon Sep 17 00:00:00 2001 From: Andreas Stadelmeier Date: Wed, 30 Mar 2022 03:17:55 +0200 Subject: [PATCH 37/69] Add TargetExpression --- .../target/generate/ASTToTargetAST.java | 31 ++-- .../generate/StatementToTargetExpression.java | 156 ++++++++++++++++++ .../target/tree/TargetMethod.java | 4 +- .../target/tree/expression/TargetAssign.java | 4 + .../target/tree/expression/TargetBlock.java | 6 + .../tree/expression/TargetExpression.java | 7 + .../expression/TargetLambdaExpression.java | 8 + .../target/tree/expression/TargetNew.java | 8 + .../target/tree/expression/TargetReturn.java | 4 + .../target/tree/expression/TargetSuper.java | 4 + .../target/tree/expression/TargetThis.java | 4 + .../target/tree/type/TargetGenericType.java | 4 + .../target/tree/type/TargetType.java | 2 +- src/test/java/targetast/ASTToTargetTest.java | 5 + 14 files changed, 232 insertions(+), 15 deletions(-) create mode 100644 src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetAssign.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBlock.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLambdaExpression.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetNew.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetReturn.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetSuper.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetThis.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/type/TargetGenericType.java create mode 100644 src/test/java/targetast/ASTToTargetTest.java diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index 14896b83..63248f92 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -4,14 +4,11 @@ import de.dhbwstuttgart.syntaxtree.ASTVisitor; import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.Field; import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.statement.Block; import de.dhbwstuttgart.syntaxtree.type.*; -import de.dhbwstuttgart.target.tree.TargetClass; -import de.dhbwstuttgart.target.tree.TargetConstructor; -import de.dhbwstuttgart.target.tree.TargetField; -import de.dhbwstuttgart.target.tree.TargetMethod; -import de.dhbwstuttgart.target.tree.type.TargetRefType; -import de.dhbwstuttgart.target.tree.type.TargetSuperWildcard; -import de.dhbwstuttgart.target.tree.type.TargetType; +import de.dhbwstuttgart.target.tree.*; +import de.dhbwstuttgart.target.tree.expression.TargetBlock; +import de.dhbwstuttgart.target.tree.type.*; import java.util.ArrayList; import java.util.List; @@ -31,14 +28,24 @@ public class ASTToTargetAST { } private TargetMethod convert(Method input, Map sigma) { - return null; + List params = input.getParameterList().getFormalparalist().stream() + .map(param -> new MethodParameter(convert(param.getType(), sigma), param.getName())).collect(Collectors.toList()); + return new TargetMethod(input.name, params, convert(input.block)); + } + + private TargetBlock convert(Block block) { + return new TargetBlock(block.statements.stream().map(e -> { + StatementToTargetExpression converter = new StatementToTargetExpression(); + e.accept(converter); + return converter.result; + }).collect(Collectors.toList())); } private TargetField convert(Field input, Map sigma) { return null; } - private TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, Map sigma) { + private TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, Map sigma) { return input.acceptTV(new TypeVisitor<>() { @Override public TargetType visit(RefType refType) { @@ -53,17 +60,17 @@ public class ASTToTargetAST { @Override public TargetType visit(TypePlaceholder typePlaceholder) { - return convert(sigma.get(typePlaceholder), sigma); + return sigma.get(typePlaceholder); } @Override public TargetType visit(ExtendsWildcardType extendsWildcardType) { - return null; + return new TargetExtendsWildcard(convert(extendsWildcardType.getInnerType(), sigma)); } @Override public TargetType visit(GenericRefType genericRefType) { - return null; + return new TargetGenericType(genericRefType.getParsedName()); } }); } diff --git a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java new file mode 100644 index 00000000..cf083f3d --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java @@ -0,0 +1,156 @@ +package de.dhbwstuttgart.target.generate; + +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; +import de.dhbwstuttgart.syntaxtree.ASTVisitor; +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.statement.*; +import de.dhbwstuttgart.target.tree.expression.TargetExpression; + +public class StatementToTargetExpression implements StatementVisitor { + public TargetExpression result; + + @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/TargetMethod.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java index 910c12a0..6538b7a5 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java @@ -1,9 +1,9 @@ package de.dhbwstuttgart.target.tree; -import de.dhbwstuttgart.target.tree.type.TargetType; +import de.dhbwstuttgart.target.tree.expression.TargetBlock; import java.util.List; -public record TargetMethod(String name, List parameterTypes) { +public record TargetMethod(String name, List parameterTypes, TargetBlock block) { } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetAssign.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetAssign.java new file mode 100644 index 00000000..c603db44 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetAssign.java @@ -0,0 +1,4 @@ +package de.dhbwstuttgart.target.tree.expression; + +public record TargetAssign(TargetExpression leftSide, TargetExpression rightSide) implements TargetExpression { +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBlock.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBlock.java new file mode 100644 index 00000000..eed51adc --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBlock.java @@ -0,0 +1,6 @@ +package de.dhbwstuttgart.target.tree.expression; + +import java.util.List; + +public record TargetBlock(List statememts) implements TargetExpression { +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java new file mode 100644 index 00000000..82d33daa --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java @@ -0,0 +1,7 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.*; + +public sealed interface TargetExpression + permits TargetBlock, TargetLambdaExpression, TargetReturn, TargetThis, TargetSuper, TargetNew, TargetAssign { +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLambdaExpression.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLambdaExpression.java new file mode 100644 index 00000000..815ef036 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLambdaExpression.java @@ -0,0 +1,8 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.MethodParameter; + +import java.util.List; + +public record TargetLambdaExpression(List params, TargetExpression block) implements TargetExpression { +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetNew.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetNew.java new file mode 100644 index 00000000..7e78cc57 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetNew.java @@ -0,0 +1,8 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +import java.util.List; + +public record TargetNew(TargetType instantiatedType, List params) implements TargetExpression { +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetReturn.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetReturn.java new file mode 100644 index 00000000..1c86dbc6 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetReturn.java @@ -0,0 +1,4 @@ +package de.dhbwstuttgart.target.tree.expression; + +public record TargetReturn(TargetExpression expression) implements TargetExpression { +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetSuper.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetSuper.java new file mode 100644 index 00000000..40cd73b8 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetSuper.java @@ -0,0 +1,4 @@ +package de.dhbwstuttgart.target.tree.expression; + +public record TargetSuper() implements TargetExpression { +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetThis.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetThis.java new file mode 100644 index 00000000..9bbc5891 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetThis.java @@ -0,0 +1,4 @@ +package de.dhbwstuttgart.target.tree.expression; + +public record TargetThis() implements TargetExpression { +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetGenericType.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetGenericType.java new file mode 100644 index 00000000..fce6b7ee --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetGenericType.java @@ -0,0 +1,4 @@ +package de.dhbwstuttgart.target.tree.type; + +public record TargetGenericType(String name) implements TargetType { +} 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 849df99c..eed6dcab 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetType.java @@ -1,5 +1,5 @@ package de.dhbwstuttgart.target.tree.type; public sealed interface TargetType - permits TargetExtendsWildcard, TargetFunNType, TargetRefType, TargetSuperWildcard { + permits TargetExtendsWildcard, TargetFunNType, TargetGenericType, TargetRefType, TargetSuperWildcard { } diff --git a/src/test/java/targetast/ASTToTargetTest.java b/src/test/java/targetast/ASTToTargetTest.java new file mode 100644 index 00000000..64d3368f --- /dev/null +++ b/src/test/java/targetast/ASTToTargetTest.java @@ -0,0 +1,5 @@ +package targetast; + +public class ASTToTargetTest { + +} From e8cc6ade11f5129e250e0a50bba4aac1ab413e4a Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Wed, 27 Apr 2022 13:05:01 +0200 Subject: [PATCH 38/69] Start working on the code generator --- .../target/bytecode/Codegen.java | 57 +++++++++++++++++++ .../target/tree/TargetConstructor.java | 5 ++ .../target/tree/TargetField.java | 6 +- .../target/tree/TargetMethod.java | 4 ++ .../target/tree/type/TargetRefType.java | 4 ++ .../target/tree/type/TargetType.java | 2 + 6 files changed, 77 insertions(+), 1 deletion(-) create mode 100755 src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java diff --git a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java new file mode 100755 index 00000000..90a04fb0 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java @@ -0,0 +1,57 @@ +package de.dhbwstuttgart.target.bytecode; + +import de.dhbwstuttgart.target.tree.TargetClass; +import de.dhbwstuttgart.target.tree.TargetConstructor; +import de.dhbwstuttgart.target.tree.TargetField; +import de.dhbwstuttgart.target.tree.TargetMethod; +import de.dhbwstuttgart.target.tree.expression.TargetBlock; +import de.dhbwstuttgart.target.tree.type.TargetType; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.MethodVisitor; + +import static org.objectweb.asm.Opcodes.*; + +public class Codegen { + private TargetClass clazz; + private ClassWriter cw; + + public Codegen(TargetClass clazz) { + this.clazz = clazz; + this.cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + } + + private void generateBlock(MethodVisitor mv, TargetBlock block) { + + } + + private void generateField(TargetField field) { + cw.visitField(field.access(), field.name(), field.getDescriptor(), null, null); + } + + private void generateConstructor(TargetConstructor constructor) { + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "", constructor.getDescriptor(), null, null); + mv.visitEnd(); + } + + private void generateMethod(TargetMethod method) { + // TODO Access modifier + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, method.name(), method.getDescriptor(), null, null); + generateBlock(mv, method.block()); + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + + public byte[] generate() { + // TODO Access modifier and signature + cw.visit(V12, ACC_PUBLIC, clazz.qualifiedName(), + null, clazz.superType().toSignature(), + clazz.implementingInterfaces().stream().map(TargetType::toSignature).toArray(String[]::new) + ); + clazz.fields().forEach(this::generateField); + clazz.constructors().forEach(this::generateConstructor); + clazz.methods().forEach(this::generateMethod); + + cw.visitEnd(); + return cw.toByteArray(); + } +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java index b93219ff..94aab071 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java @@ -3,5 +3,10 @@ package de.dhbwstuttgart.target.tree; import java.util.List; public record TargetConstructor(List parameterTypes) { + + public String getDescriptor() { + // TODO + return null; + } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/TargetField.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetField.java index cbba1dec..c466b159 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/TargetField.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetField.java @@ -2,6 +2,10 @@ package de.dhbwstuttgart.target.tree; import de.dhbwstuttgart.target.tree.type.TargetType; -public record TargetField(TargetType type, String name) { +public record TargetField(int access, TargetType type, String name) { + public String getDescriptor() { + // TODO + return null; + } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java index 6538b7a5..9c50f6e7 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java @@ -5,5 +5,9 @@ import de.dhbwstuttgart.target.tree.expression.TargetBlock; import java.util.List; public record TargetMethod(String name, List parameterTypes, TargetBlock block) { + public String getDescriptor() { + // TODO + 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 1c27cd62..33c38f5d 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetRefType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetRefType.java @@ -5,4 +5,8 @@ import de.dhbwstuttgart.target.tree.type.TargetType; import java.util.List; public record TargetRefType(String name, List params) implements TargetType { + @Override + public String toSignature() { + return this.name; + } } 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 eed6dcab..f4d8f7d0 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetType.java @@ -2,4 +2,6 @@ package de.dhbwstuttgart.target.tree.type; public sealed interface TargetType permits TargetExtendsWildcard, TargetFunNType, TargetGenericType, TargetRefType, TargetSuperWildcard { + + public String toSignature(); } From 590a4f04aed0eb9aab7c0ab2fae25f5584668ad9 Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Tue, 3 May 2022 21:37:14 +0200 Subject: [PATCH 39/69] Implement target t AST --- pom.xml | 3 +- .../target/bytecode/CodeGenException.java | 7 ++ .../target/bytecode/Codegen.java | 83 +++++++++++++++++-- .../target/tree/TargetConstructor.java | 4 +- .../target/tree/TargetField.java | 5 ++ .../target/tree/TargetMethod.java | 2 +- .../target/tree/expression/TargetAssign.java | 4 +- .../tree/expression/TargetBinaryOp.java | 40 +++++++++ .../target/tree/expression/TargetBlock.java | 8 +- .../target/tree/expression/TargetBreak.java | 11 +++ .../target/tree/expression/TargetCast.java | 6 ++ .../tree/expression/TargetContinue.java | 11 +++ .../target/tree/expression/TargetDot.java | 6 ++ .../tree/expression/TargetExpression.java | 4 +- .../tree/expression/TargetFieldVar.java | 7 ++ .../target/tree/expression/TargetFor.java | 11 +++ .../target/tree/expression/TargetForEach.java | 11 +++ .../target/tree/expression/TargetIf.java | 10 +++ .../tree/expression/TargetInstanceOf.java | 12 +++ .../expression/TargetLambdaExpression.java | 3 +- .../target/tree/expression/TargetLiteral.java | 35 ++++++++ .../tree/expression/TargetLocalVar.java | 6 ++ .../tree/expression/TargetMethodCall.java | 9 ++ .../target/tree/expression/TargetNew.java | 2 +- .../target/tree/expression/TargetReturn.java | 6 ++ .../target/tree/expression/TargetSuper.java | 4 +- .../target/tree/expression/TargetSwitch.java | 16 ++++ .../target/tree/expression/TargetThis.java | 4 +- .../target/tree/expression/TargetUnaryOp.java | 15 ++++ .../target/tree/expression/TargetVarDecl.java | 11 +++ .../target/tree/expression/TargetWhile.java | 11 +++ .../tree/type/TargetExtendsWildcard.java | 6 +- .../target/tree/type/TargetFunNType.java | 4 + .../target/tree/type/TargetGenericType.java | 4 + .../target/tree/type/TargetRefType.java | 2 +- .../target/tree/type/TargetSuperWildcard.java | 4 + .../target/tree/type/TargetType.java | 15 +++- 37 files changed, 382 insertions(+), 20 deletions(-) create mode 100644 src/main/java/de/dhbwstuttgart/target/bytecode/CodeGenException.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBinaryOp.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBreak.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetCast.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetContinue.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetDot.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFieldVar.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFor.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetForEach.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetIf.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetInstanceOf.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLiteral.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLocalVar.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetMethodCall.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetSwitch.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetUnaryOp.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetVarDecl.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetWhile.java diff --git a/pom.xml b/pom.xml index 105ce877..3f7cc7e3 100644 --- a/pom.xml +++ b/pom.xml @@ -124,7 +124,8 @@ http://maven.apache.org/maven-v4_0_0.xsd"> 17 17 - + --enable-preview + diff --git a/src/main/java/de/dhbwstuttgart/target/bytecode/CodeGenException.java b/src/main/java/de/dhbwstuttgart/target/bytecode/CodeGenException.java new file mode 100644 index 00000000..f517e767 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/bytecode/CodeGenException.java @@ -0,0 +1,7 @@ +package de.dhbwstuttgart.target.bytecode; + +public class CodeGenException extends RuntimeException { + public CodeGenException(String cause) { + super(cause); + } +} diff --git a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java index 90a04fb0..fe10d9d6 100755 --- a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java @@ -5,10 +5,15 @@ import de.dhbwstuttgart.target.tree.TargetConstructor; import de.dhbwstuttgart.target.tree.TargetField; import de.dhbwstuttgart.target.tree.TargetMethod; import de.dhbwstuttgart.target.tree.expression.TargetBlock; +import de.dhbwstuttgart.target.tree.expression.TargetExpression; +import de.dhbwstuttgart.target.tree.expression.TargetVarDecl; import de.dhbwstuttgart.target.tree.type.TargetType; +import javassist.compiler.CodeGen; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; +import java.util.Map; + import static org.objectweb.asm.Opcodes.*; public class Codegen { @@ -20,8 +25,72 @@ public class Codegen { this.cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); } - private void generateBlock(MethodVisitor mv, TargetBlock block) { + private record LocalVar(int index, String name, TargetType type) {} + private class Scope { + Scope parent; + Map locals; + + Scope(Scope parent) { + this.parent = parent; + } + + void add(LocalVar var) { + locals.put(var.name, var); + } + + LocalVar get(String name) { + var local = locals.get(name); + if (local != null ){ + return local; + } + if (parent != null) { + return parent.get(name); + } + throw new CodeGenException("Unknown symbol '" + name + "'"); + } + } + + private class State { + Scope scope = new Scope(null); + int localCounter = 1; + MethodVisitor mv; + + State(MethodVisitor mv) { + this.mv = mv; + } + + void enterScope() { + this.scope = new Scope(this.scope); + } + + void exitScope() { + this.scope = this.scope.parent; + } + + void createVariable(String name, TargetType type) { + scope.add(new LocalVar(localCounter, name, type)); + localCounter += 1; + } + } + + private void generate(State state, TargetExpression expr) { + switch (expr) { + case TargetBlock block: + var localCounter = state.localCounter; + state.enterScope(); + for (var e : block.statements()) { + generate(state, e); + } + state.exitScope(); + state.localCounter = localCounter; + break; + case TargetVarDecl varDecl: + state.createVariable(varDecl.name(), varDecl.varType()); + break; + default: + throw new IllegalStateException("Unexpected value: " + expr); + } } private void generateField(TargetField field) { @@ -29,21 +98,21 @@ public class Codegen { } private void generateConstructor(TargetConstructor constructor) { - MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "", constructor.getDescriptor(), null, null); + MethodVisitor mv = cw.visitMethod(constructor.access(), "", constructor.getDescriptor(), null, null); + generate(new State(mv), constructor.block()); + mv.visitMaxs(0, 0); mv.visitEnd(); } private void generateMethod(TargetMethod method) { - // TODO Access modifier - MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, method.name(), method.getDescriptor(), null, null); - generateBlock(mv, method.block()); + MethodVisitor mv = cw.visitMethod(method.access(), method.name(), method.getDescriptor(), null, null); + generate(new State(mv), method.block()); mv.visitMaxs(0, 0); mv.visitEnd(); } public byte[] generate() { - // TODO Access modifier and signature - cw.visit(V12, ACC_PUBLIC, clazz.qualifiedName(), + cw.visit(V1_8, clazz.modifiers(), clazz.qualifiedName(), null, clazz.superType().toSignature(), clazz.implementingInterfaces().stream().map(TargetType::toSignature).toArray(String[]::new) ); diff --git a/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java index 94aab071..594d5a20 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java @@ -1,8 +1,10 @@ package de.dhbwstuttgart.target.tree; +import de.dhbwstuttgart.target.tree.expression.TargetBlock; + import java.util.List; -public record TargetConstructor(List parameterTypes) { +public record TargetConstructor(int access, List parameterTypes, TargetBlock block) { public String getDescriptor() { // TODO diff --git a/src/main/java/de/dhbwstuttgart/target/tree/TargetField.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetField.java index c466b159..c9076736 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/TargetField.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetField.java @@ -1,11 +1,16 @@ package de.dhbwstuttgart.target.tree; import de.dhbwstuttgart.target.tree.type.TargetType; +import org.objectweb.asm.Opcodes; public record TargetField(int access, TargetType type, String name) { public String getDescriptor() { // TODO return null; } + + public boolean isStatic() { + return (access & Opcodes.ACC_STATIC) != 0; + } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java index 9c50f6e7..767f2689 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java @@ -4,7 +4,7 @@ import de.dhbwstuttgart.target.tree.expression.TargetBlock; import java.util.List; -public record TargetMethod(String name, List parameterTypes, TargetBlock block) { +public record TargetMethod(int access, String name, List parameterTypes, TargetBlock block) { public String getDescriptor() { // TODO return null; diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetAssign.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetAssign.java index c603db44..fd4bf51e 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetAssign.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetAssign.java @@ -1,4 +1,6 @@ package de.dhbwstuttgart.target.tree.expression; -public record TargetAssign(TargetExpression leftSide, TargetExpression rightSide) implements TargetExpression { +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetAssign(TargetType type, TargetExpression leftSide, TargetExpression rightSide) implements TargetExpression { } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBinaryOp.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBinaryOp.java new file mode 100644 index 00000000..233157c5 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBinaryOp.java @@ -0,0 +1,40 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.expression.TargetExpression; +import de.dhbwstuttgart.target.tree.type.TargetType; + +public sealed interface TargetBinaryOp extends TargetExpression { + TargetExpression left(); + TargetExpression right(); + + // Artihmetic + record Add(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + record Sub(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + record Div(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + record Mul(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + record Rem(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + + // Bitwise + record BAnd(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + record BOr(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + record XOr(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + record Shl(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + record Shr(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + record UShr(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + + // Conditional + record And(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + record Or(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + + // Comparison + record Equal(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + record Greater(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + record GreaterOrEqual(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + record Less(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + record LessOrEqual(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + record NotEqual(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + + record Assign(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} +} + + diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBlock.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBlock.java index eed51adc..87cc3b5e 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBlock.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBlock.java @@ -1,6 +1,12 @@ package de.dhbwstuttgart.target.tree.expression; +import de.dhbwstuttgart.target.tree.type.TargetType; + import java.util.List; -public record TargetBlock(List statememts) implements TargetExpression { +public record TargetBlock(List statements) implements TargetExpression { + @Override + public TargetType type() { + return null; + } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBreak.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBreak.java new file mode 100644 index 00000000..ae918c44 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBreak.java @@ -0,0 +1,11 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetBreak() implements TargetExpression { + + @Override + public TargetType type() { + return null; + } +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetCast.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetCast.java new file mode 100644 index 00000000..f95bc9a8 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetCast.java @@ -0,0 +1,6 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetCast(TargetType type, TargetExpression expr) implements TargetExpression { +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetContinue.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetContinue.java new file mode 100644 index 00000000..42ebc995 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetContinue.java @@ -0,0 +1,11 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetContinue() implements TargetExpression { + + @Override + public TargetType type() { + return null; + } +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetDot.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetDot.java new file mode 100644 index 00000000..6eef9857 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetDot.java @@ -0,0 +1,6 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetDot(TargetType type, boolean isStatic, TargetExpression left, String right) implements TargetExpression { +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java index 82d33daa..7c9c85a2 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java @@ -3,5 +3,7 @@ package de.dhbwstuttgart.target.tree.expression; import de.dhbwstuttgart.target.tree.type.*; public sealed interface TargetExpression - permits TargetBlock, TargetLambdaExpression, TargetReturn, TargetThis, TargetSuper, TargetNew, TargetAssign { + permits TargetAssign, TargetBinaryOp, TargetBlock, TargetBreak, TargetCast, TargetContinue, TargetDot, TargetFieldVar, TargetFor, TargetForEach, TargetIf, TargetInstanceOf, TargetLambdaExpression, TargetLiteral, TargetLocalVar, TargetMethodCall, TargetNew, TargetReturn, TargetSuper, TargetSwitch, TargetThis, TargetUnaryOp, TargetVarDecl, TargetWhile { + + TargetType type(); } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFieldVar.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFieldVar.java new file mode 100644 index 00000000..9835fc9f --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFieldVar.java @@ -0,0 +1,7 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.TargetField; +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetFieldVar(TargetType type, TargetField field) implements TargetExpression { +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFor.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFor.java new file mode 100644 index 00000000..2ce402ab --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFor.java @@ -0,0 +1,11 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetFor(TargetExpression init, TargetExpression termination, TargetExpression increment, TargetExpression body) implements TargetExpression { + + @Override + public TargetType type() { + return null; + } +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetForEach.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetForEach.java new file mode 100644 index 00000000..392b84e4 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetForEach.java @@ -0,0 +1,11 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetForEach(TargetExpression vardecl, TargetExpression list) implements TargetExpression { + + @Override + public TargetType type() { + return null; + } +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetIf.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetIf.java new file mode 100644 index 00000000..ef94fc0b --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetIf.java @@ -0,0 +1,10 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetIf(TargetExpression expr, TargetExpression if_body, TargetExpression else_body) implements TargetExpression { + @Override + public TargetType type() { + return null; + } +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetInstanceOf.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetInstanceOf.java new file mode 100644 index 00000000..79bf75f9 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetInstanceOf.java @@ -0,0 +1,12 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.syntaxtree.statement.Expression; +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetInstanceOf(Expression left, TargetType right) implements TargetExpression { + + @Override + public TargetType type() { + return TargetType.Boolean; + } +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLambdaExpression.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLambdaExpression.java index 815ef036..13da5b9c 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLambdaExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLambdaExpression.java @@ -1,8 +1,9 @@ package de.dhbwstuttgart.target.tree.expression; import de.dhbwstuttgart.target.tree.MethodParameter; +import de.dhbwstuttgart.target.tree.type.TargetType; import java.util.List; -public record TargetLambdaExpression(List params, TargetExpression block) implements TargetExpression { +public record TargetLambdaExpression(TargetType type, List params, TargetExpression block) implements TargetExpression { } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLiteral.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLiteral.java new file mode 100644 index 00000000..31ccb1f7 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLiteral.java @@ -0,0 +1,35 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public sealed interface TargetLiteral extends TargetExpression { + Object value(); + + record CharLiteral(Integer value) implements TargetLiteral { + @Override + public TargetType type() { + return TargetType.Char; + } + } + + record IntLiteral(Integer value) implements TargetLiteral { + @Override + public TargetType type() { + return TargetType.Integer; + } + } + + record LongLiteral(Long value) implements TargetLiteral { + @Override + public TargetType type() { + return TargetType.Long; + } + } + + record StringLiteral(String value) implements TargetLiteral { + @Override + public TargetType type() { + return TargetType.String; + } + } +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLocalVar.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLocalVar.java new file mode 100644 index 00000000..e4fa977f --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLocalVar.java @@ -0,0 +1,6 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetLocalVar(TargetType type, String name) implements TargetExpression { +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetMethodCall.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetMethodCall.java new file mode 100644 index 00000000..6a812604 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetMethodCall.java @@ -0,0 +1,9 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.TargetMethod; +import de.dhbwstuttgart.target.tree.type.TargetType; + +import java.util.List; + +public record TargetMethodCall(TargetType type, TargetExpression expr, List args, TargetMethod method) implements TargetExpression { +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetNew.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetNew.java index 7e78cc57..6819a744 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetNew.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetNew.java @@ -4,5 +4,5 @@ import de.dhbwstuttgart.target.tree.type.TargetType; import java.util.List; -public record TargetNew(TargetType instantiatedType, List params) implements TargetExpression { +public record TargetNew(TargetType type, List params) implements TargetExpression { } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetReturn.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetReturn.java index 1c86dbc6..c419cc1c 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetReturn.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetReturn.java @@ -1,4 +1,10 @@ package de.dhbwstuttgart.target.tree.expression; +import de.dhbwstuttgart.target.tree.type.TargetType; + public record TargetReturn(TargetExpression expression) implements TargetExpression { + @Override + public TargetType type() { + return null; + } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetSuper.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetSuper.java index 40cd73b8..ddffe386 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetSuper.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetSuper.java @@ -1,4 +1,6 @@ package de.dhbwstuttgart.target.tree.expression; -public record TargetSuper() implements TargetExpression { +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetSuper(TargetType type) implements TargetExpression { } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetSwitch.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetSwitch.java new file mode 100644 index 00000000..a6823913 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetSwitch.java @@ -0,0 +1,16 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.syntaxtree.statement.Expression; +import de.dhbwstuttgart.target.tree.type.TargetType; + +import java.util.List; + +public record TargetSwitch(Expression expr, List cases, Expression default_) implements TargetExpression { + + @Override + public TargetType type() { + return null; + } + + record Case(Expression value, Expression body) {} +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetThis.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetThis.java index 9bbc5891..fe9b722c 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetThis.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetThis.java @@ -1,4 +1,6 @@ package de.dhbwstuttgart.target.tree.expression; -public record TargetThis() implements TargetExpression { +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetThis(TargetType type) implements TargetExpression { } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetUnaryOp.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetUnaryOp.java new file mode 100644 index 00000000..eec72196 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetUnaryOp.java @@ -0,0 +1,15 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public sealed interface TargetUnaryOp extends TargetExpression { + TargetExpression expr(); + + record Negate(TargetType type, TargetExpression expr) implements TargetUnaryOp {} + record Not(TargetType type, TargetExpression expr) implements TargetUnaryOp {} + + record PreIncrement(TargetType type, TargetExpression expr) implements TargetUnaryOp {} + record PostIncrement(TargetType type, TargetExpression expr) implements TargetUnaryOp {} + record PreDecrement(TargetType type, TargetExpression expr) implements TargetUnaryOp {} + record PostDecrement(TargetType type, TargetExpression expr) implements TargetUnaryOp {} +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetVarDecl.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetVarDecl.java new file mode 100644 index 00000000..b0c15225 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetVarDecl.java @@ -0,0 +1,11 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetVarDecl(String name, TargetType varType) implements TargetExpression { + + @Override + public TargetType type() { + return null; + } +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetWhile.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetWhile.java new file mode 100644 index 00000000..5f0b8b06 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetWhile.java @@ -0,0 +1,11 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetWhile(TargetExpression expr, TargetExpression body) implements TargetExpression { + + @Override + public TargetType type() { + return null; + } +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java index b30b85e9..4dc033de 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java @@ -2,6 +2,10 @@ package de.dhbwstuttgart.target.tree.type; import java.util.List; -public record TargetExtendsWildcard(TargetType innerType) implements TargetType{ +public record TargetExtendsWildcard(TargetType innerType) implements TargetType { + @Override + public String toSignature() { + return null; + } } 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 c3e86f79..76394836 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetFunNType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetFunNType.java @@ -3,4 +3,8 @@ package de.dhbwstuttgart.target.tree.type; import java.util.List; public record TargetFunNType(int N, List params) implements TargetType { + @Override + public String toSignature() { + 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 fce6b7ee..12269632 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetGenericType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetGenericType.java @@ -1,4 +1,8 @@ package de.dhbwstuttgart.target.tree.type; public record TargetGenericType(String name) implements TargetType { + @Override + public String toSignature() { + 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 33c38f5d..66a2b8ac 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetRefType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetRefType.java @@ -7,6 +7,6 @@ import java.util.List; public record TargetRefType(String name, List params) implements TargetType { @Override public String toSignature() { - return this.name; + return "L" + this.name.replaceAll("\\.", "/"); } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java index 421102cb..1414daab 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java @@ -1,4 +1,8 @@ package de.dhbwstuttgart.target.tree.type; public record TargetSuperWildcard(TargetType innerType) implements TargetType { + @Override + public String toSignature() { + return null; + } } 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 f4d8f7d0..7f78b431 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetType.java @@ -1,7 +1,20 @@ package de.dhbwstuttgart.target.tree.type; +import java.util.List; + public sealed interface TargetType permits TargetExtendsWildcard, TargetFunNType, TargetGenericType, TargetRefType, TargetSuperWildcard { - public String toSignature(); + // Builtin types + TargetRefType Boolean = new TargetRefType("java.lang.Boolean", List.of()); + TargetRefType Char = new TargetRefType("java.lang.Character", List.of()); + TargetRefType Byte = new TargetRefType("java.lang.Byte", List.of()); + TargetRefType Short = new TargetRefType("java.lang.Short", List.of()); + TargetRefType Integer = new TargetRefType("java.lang.Integer", List.of()); + TargetRefType Long = new TargetRefType("java.lang.Long", List.of()); + TargetRefType Float = new TargetRefType("java.lang.Float", List.of()); + TargetRefType Double = new TargetRefType("java.lang.Double", List.of()); + TargetRefType String = new TargetRefType("java.lang.String", List.of()); + + String toSignature(); } From 8666bfdf17b917cd60f24a5ba6426840a894f150 Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Sun, 15 May 2022 18:45:49 +0200 Subject: [PATCH 40/69] Start testing --- .../target/bytecode/Codegen.java | 486 +++++++++++++++++- .../target/generate/ASTToTargetAST.java | 3 +- .../target/tree/TargetClass.java | 24 +- .../target/tree/TargetConstructor.java | 2 +- .../target/tree/TargetField.java | 2 +- .../target/tree/TargetInterface.java | 6 + .../target/tree/TargetMethod.java | 7 +- .../target/tree/expression/TargetAssign.java | 2 +- .../tree/expression/TargetBinaryOp.java | 3 +- .../tree/expression/TargetClassName.java | 6 + .../target/tree/expression/TargetDot.java | 6 - .../tree/expression/TargetExpression.java | 2 +- .../tree/expression/TargetFieldVar.java | 3 +- .../target/tree/expression/TargetIf.java | 2 +- .../tree/expression/TargetMethodCall.java | 2 +- .../target/tree/expression/TargetNew.java | 2 +- .../expression/TargetStatementExpression.java | 4 + .../target/tree/expression/TargetTernary.java | 6 + .../target/tree/expression/TargetUnaryOp.java | 10 +- .../target/tree/expression/TargetWhile.java | 2 +- .../target/tree/type/TargetRefType.java | 2 +- .../target/tree/type/TargetType.java | 1 + .../java/targetast/ByteArrayClassLoader.java | 9 + src/test/java/targetast/TestCodegen.java | 25 + 24 files changed, 581 insertions(+), 36 deletions(-) create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/TargetInterface.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetClassName.java delete mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetDot.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetStatementExpression.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetTernary.java create mode 100644 src/test/java/targetast/ByteArrayClassLoader.java create mode 100644 src/test/java/targetast/TestCodegen.java diff --git a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java index fe10d9d6..c8bf7fd8 100755 --- a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java @@ -4,17 +4,17 @@ import de.dhbwstuttgart.target.tree.TargetClass; import de.dhbwstuttgart.target.tree.TargetConstructor; import de.dhbwstuttgart.target.tree.TargetField; import de.dhbwstuttgart.target.tree.TargetMethod; -import de.dhbwstuttgart.target.tree.expression.TargetBlock; -import de.dhbwstuttgart.target.tree.expression.TargetExpression; -import de.dhbwstuttgart.target.tree.expression.TargetVarDecl; +import de.dhbwstuttgart.target.tree.expression.*; +import de.dhbwstuttgart.target.tree.type.TargetRefType; import de.dhbwstuttgart.target.tree.type.TargetType; -import javassist.compiler.CodeGen; import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import java.util.Map; import static org.objectweb.asm.Opcodes.*; +import static de.dhbwstuttgart.target.tree.expression.TargetBinaryOp.*; public class Codegen { private TargetClass clazz; @@ -25,9 +25,9 @@ public class Codegen { this.cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); } - private record LocalVar(int index, String name, TargetType type) {} + private static record LocalVar(int index, String name, TargetType type) {} - private class Scope { + private static class Scope { Scope parent; Map locals; @@ -51,7 +51,7 @@ public class Codegen { } } - private class State { + private static class State { Scope scope = new Scope(null); int localCounter = 1; MethodVisitor mv; @@ -74,22 +74,488 @@ public class Codegen { } } + private void boxPrimitive(State state, TargetType type) { + var mv = state.mv; + if (type.equals(TargetType.Boolean)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); + } else if (type.equals(TargetType.Byte)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false); + } else if (type.equals(TargetType.Double)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false); + } else if (type.equals(TargetType.Long)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(L)Ljava/lang/Long;", false); + } else if (type.equals(TargetType.Integer)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(L)Ljava/lang/Integer;", false); + } else if (type.equals(TargetType.Float)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false); + } else if (type.equals(TargetType.Short)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false); + } else if (type.equals(TargetType.Char)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Char", "valueOf", "(C)Ljava/lang/Char;", false); + } + } + + private void unboxPrimitive(State state, TargetType type) { + var mv = state.mv; + if (type.equals(TargetType.Boolean)) { + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false); + } else if (type.equals(TargetType.Byte)) { + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false); + } else if (type.equals(TargetType.Double)) { + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false); + } else if (type.equals(TargetType.Long)) { + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()L", false); + } else if (type.equals(TargetType.Integer)) { + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false); + } else if (type.equals(TargetType.Float)) { + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false); + } else if (type.equals(TargetType.Short)) { + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false); + } else if (type.equals(TargetType.Char)) { + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Char", "charValue", "()C", false); + } + } + + private void generateRelationalOperator(State state, TargetBinaryOp op, int code) { + var mv = state.mv; + Label if_true = new Label(); + Label end = new Label(); + generate(state, op.left()); + generate(state, op.right()); + mv.visitJumpInsn(code, if_true); + mv.visitInsn(ICONST_0); + mv.visitJumpInsn(GOTO, end); + mv.visitLabel(if_true); + mv.visitInsn(ICONST_1); + mv.visitLabel(end); + } + + private void generateRelationalOperator(State state, TargetBinaryOp op, int cmp, int code) { + var mv = state.mv; + Label if_true = new Label(); + Label end = new Label(); + generate(state, op.left()); + generate(state, op.right()); + mv.visitInsn(cmp); + mv.visitInsn(code); + mv.visitJumpInsn(code, if_true); + mv.visitInsn(ICONST_0); + mv.visitJumpInsn(GOTO, end); + mv.visitLabel(if_true); + mv.visitInsn(ICONST_1); + mv.visitLabel(end); + } + + private void generateBinaryOp(State state, TargetBinaryOp op) { + var mv = state.mv; + switch (op) { + case Add add: { + generate(state, add.left()); + generate(state, add.right()); + var type = add.type(); + if (type.equals(TargetType.Byte) + || type.equals(TargetType.Integer) + || type.equals(TargetType.Short)) { + mv.visitInsn(IADD); + } else if (type.equals(TargetType.Long)) { + mv.visitInsn(LADD); + } else if (type.equals(TargetType.Float)) { + mv.visitInsn(FADD); + } else if (type.equals(TargetType.Double)) { + mv.visitInsn(DADD); + } else { + throw new CodeGenException("Invalid argument to Add expression"); + } + break; + } + case Sub sub: { + generate(state, sub.left()); + generate(state, sub.right()); + var type = sub.type(); + if (type.equals(TargetType.Byte) + || type.equals(TargetType.Integer) + || type.equals(TargetType.Short)) { + mv.visitInsn(ISUB); + } else if (type.equals(TargetType.Long)) { + mv.visitInsn(LSUB); + } else if (type.equals(TargetType.Float)) { + mv.visitInsn(FSUB); + } else if (type.equals(TargetType.Double)) { + mv.visitInsn(DSUB); + } else { + throw new CodeGenException("Invalid argument to Sub expression"); + } + break; + } + case Div div: { + generate(state, div.left()); + generate(state, div.right()); + var type = div.type(); + if (type.equals(TargetType.Byte) + || type.equals(TargetType.Integer) + || type.equals(TargetType.Short)) { + mv.visitInsn(IDIV); + } else if (type.equals(TargetType.Long)) { + mv.visitInsn(LDIV); + } else if (type.equals(TargetType.Float)) { + mv.visitInsn(FDIV); + } else if (type.equals(TargetType.Double)) { + mv.visitInsn(DDIV); + } else { + throw new CodeGenException("Invalid argument to Div expression"); + } + break; + } + case Mul mul: { + generate(state, mul.left()); + generate(state, mul.right()); + var type = mul.type(); + if (type.equals(TargetType.Byte) + || type.equals(TargetType.Integer) + || type.equals(TargetType.Short)) { + mv.visitInsn(IMUL); + } else if (type.equals(TargetType.Long)) { + mv.visitInsn(LMUL); + } else if (type.equals(TargetType.Float)) { + mv.visitInsn(FMUL); + } else if (type.equals(TargetType.Double)) { + mv.visitInsn(DMUL); + } else { + throw new CodeGenException("Invalid argument to Mul expression"); + } + break; + } + case Rem rem: { + generate(state, rem.left()); + generate(state, rem.right()); + var type = rem.type(); + if (type.equals(TargetType.Byte) + || type.equals(TargetType.Integer) + || type.equals(TargetType.Short)) { + mv.visitInsn(IREM); + } else if (type.equals(TargetType.Long)) { + mv.visitInsn(LREM); + } else if (type.equals(TargetType.Float)) { + mv.visitInsn(FREM); + } else if (type.equals(TargetType.Double)) { + mv.visitInsn(DREM); + } else { + throw new CodeGenException("Invalid argument to Rem expression"); + } + break; + } + case Or or: { + Label or_false = new Label(); + Label or_true = new Label(); + Label end = new Label(); + generate(state, or.left()); + mv.visitJumpInsn(IFNE, or_true); + generate(state, or.right()); + mv.visitJumpInsn(IFEQ, or_false); + mv.visitLabel(or_true); + mv.visitInsn(ICONST_1); + mv.visitJumpInsn(GOTO, end); + mv.visitLabel(or_false); + mv.visitInsn(ICONST_0); + mv.visitLabel(end); + break; + } + case And and: { + Label and_false = new Label(); + Label end = new Label(); + generate(state, and.left()); + mv.visitJumpInsn(IFEQ, and_false); + generate(state, and.right()); + mv.visitJumpInsn(IFEQ, and_false); + mv.visitInsn(ICONST_1); + mv.visitJumpInsn(GOTO, end); + mv.visitLabel(and_false); + mv.visitInsn(ICONST_0); + mv.visitLabel(end); + break; + } + case BAnd band: { + generate(state, band.left()); + generate(state, band.right()); + if (band.type().equals(TargetType.Long)) + mv.visitInsn(LAND); + else mv.visitInsn(IAND); + break; + } + case BOr bor: { + generate(state, bor.left()); + generate(state, bor.right()); + if (bor.type().equals(TargetType.Long)) + mv.visitInsn(LOR); + else mv.visitInsn(IOR); + break; + } + case XOr xor: { + generate(state, xor.left()); + generate(state, xor.right()); + if (xor.type().equals(TargetType.Long)) + mv.visitInsn(LXOR); + else mv.visitInsn(IXOR); + break; + } + case Shl shl: { + generate(state, shl.left()); + generate(state, shl.right()); + if (shl.type().equals(TargetType.Long)) + mv.visitInsn(LSHL); + else mv.visitInsn(ISHL); + break; + } + case Shr shr: { + generate(state, shr.left()); + generate(state, shr.right()); + if (shr.type().equals(TargetType.Long)) + mv.visitInsn(LSHR); + else mv.visitInsn(ISHR); + break; + } + case UShr ushr: { + generate(state, ushr.left()); + generate(state, ushr.right()); + if (ushr.type().equals(TargetType.Long)) + mv.visitInsn(LUSHR); + else mv.visitInsn(IUSHR); + break; + } + case Greater greater: { + var type = greater.type(); + if (type.equals(TargetType.Long)) { + generateRelationalOperator(state, greater, LCMP, IFGT); + } else if (type.equals(TargetType.Float)) { + generateRelationalOperator(state, greater, FCMPL, IFGT); + } else if (type.equals(TargetType.Double)) { + generateRelationalOperator(state, greater, DCMPL, IFGT); + } else { + generateRelationalOperator(state, greater, IF_ICMPGT); + } + break; + } + case Less less: { + var type = less.type(); + if (type.equals(TargetType.Long)) { + generateRelationalOperator(state, less, LCMP, IFLT); + } else if (type.equals(TargetType.Float)) { + generateRelationalOperator(state, less, FCMPL, IFLT); + } else if (type.equals(TargetType.Double)) { + generateRelationalOperator(state, less, DCMPL, IFLT); + } else { + generateRelationalOperator(state, less, IF_ICMPLT); + } + break; + } + case GreaterOrEqual greaterOrEqual: { + var type = greaterOrEqual.type(); + if (type.equals(TargetType.Long)) { + generateRelationalOperator(state, greaterOrEqual, LCMP, IFGE); + } else if (type.equals(TargetType.Float)) { + generateRelationalOperator(state, greaterOrEqual, FCMPL, IFGE); + } else if (type.equals(TargetType.Double)) { + generateRelationalOperator(state, greaterOrEqual, DCMPL, IFGE); + } else { + generateRelationalOperator(state, greaterOrEqual, IF_ICMPGE); + } + break; + } + case LessOrEqual lessOrEqual: { + var type = lessOrEqual.type(); + if (type.equals(TargetType.Long)) { + generateRelationalOperator(state, lessOrEqual, LCMP, IFLE); + } else if (type.equals(TargetType.Float)) { + generateRelationalOperator(state, lessOrEqual, FCMPL, IFLE); + } else if (type.equals(TargetType.Double)) { + generateRelationalOperator(state, lessOrEqual, DCMPL, IFLE); + } else { + generateRelationalOperator(state, lessOrEqual, IF_ICMPLE); + } + break; + } + case Equal equal: { + var type = equal.type(); + if (type.equals(TargetType.Long)) { + generateRelationalOperator(state, equal, LCMP, IFEQ); + } else if (type.equals(TargetType.Float)) { + generateRelationalOperator(state, equal, FCMPL, IFEQ); + } else if (type.equals(TargetType.Double)) { + generateRelationalOperator(state, equal, DCMPL, IFEQ); + } else if (type.equals(TargetType.Char) + || type.equals(TargetType.Short) + || type.equals(TargetType.Byte) + || type.equals(TargetType.Integer)) { + generateRelationalOperator(state, equal, IF_ICMPEQ); + } else { + generateRelationalOperator(state, equal, IF_ACMPEQ); + } + break; + } + case NotEqual notEqual: { + var type = notEqual.type(); + if (type.equals(TargetType.Long)) { + generateRelationalOperator(state, notEqual, LCMP, IFNE); + } else if (type.equals(TargetType.Float)) { + generateRelationalOperator(state, notEqual, FCMPL, IFNE); + } else if (type.equals(TargetType.Double)) { + generateRelationalOperator(state, notEqual, DCMPL, IFNE); + } else if (type.equals(TargetType.Char) + || type.equals(TargetType.Short) + || type.equals(TargetType.Byte) + || type.equals(TargetType.Integer)) { + generateRelationalOperator(state, notEqual, IF_ICMPNE); + } else { + generateRelationalOperator(state, notEqual, IF_ACMPNE); + } + break; + } + } + } + + private void generateLambdaExpression(State state, TargetLambdaExpression lambda) { + } + private void generate(State state, TargetExpression expr) { + var mv = state.mv; switch (expr) { - case TargetBlock block: + case TargetBlock block: { var localCounter = state.localCounter; state.enterScope(); for (var e : block.statements()) { generate(state, e); + if (e instanceof TargetMethodCall) { + if (e.type() != null) mv.visitInsn(POP); + } else if (e instanceof TargetStatementExpression) { + mv.visitInsn(POP); + } } state.exitScope(); state.localCounter = localCounter; break; + } case TargetVarDecl varDecl: state.createVariable(varDecl.name(), varDecl.varType()); break; + case TargetBinaryOp op: + generateBinaryOp(state, op); + break; + case TargetAssign assign: { + switch (assign.left()) { + case TargetLocalVar local: { + generate(state, assign.right()); + boxPrimitive(state, assign.right().type()); + mv.visitInsn(ASTORE); + break; + } + case TargetFieldVar dot: { + generate(state, dot.left()); + TargetRefType type = (TargetRefType) dot.type(); + generate(state, assign.right()); + boxPrimitive(state, assign.right().type()); + if (dot.isStatic()) + mv.visitInsn(DUP); + else mv.visitInsn(DUP_X1); + mv.visitFieldInsn(dot.isStatic() ? PUTSTATIC : PUTFIELD, dot.right(), type.name(), type.toSignature()); + break; + } + default: + throw new CodeGenException("Invalid assignment"); + } + break; + } + case TargetLocalVar localVar: { + LocalVar local = state.scope.get(localVar.name()); + mv.visitVarInsn(ALOAD, local.index()); + unboxPrimitive(state, local.type()); + break; + } + case TargetFieldVar dot: { + if (!dot.isStatic()) + generate(state, dot.left()); + var type = (TargetRefType) dot.left().type(); + mv.visitFieldInsn(dot.isStatic() ? GETSTATIC : GETFIELD, type.name(), dot.right(), dot.type().toSignature()); + break; + } + case TargetFor _for: { + state.enterScope(); + var localCounter = state.localCounter; + if (_for.init() != null) + generate(state, _for.init()); + Label start = new Label(); + Label end = new Label(); + mv.visitLabel(start); + if (_for.termination() != null) + generate(state, _for.termination()); + mv.visitJumpInsn(IFEQ, end); + generate(state, _for.body()); + if (_for.increment() != null) { + generate(state, _for.increment()); + if (_for.increment().type() != null) { + mv.visitInsn(POP); + } + } + mv.visitJumpInsn(GOTO, start); + mv.visitLabel(end); + state.exitScope(); + state.localCounter = localCounter; + break; + } + case TargetWhile _while: { + Label start = new Label(); + Label end = new Label(); + mv.visitLabel(start); + generate(state, _while.cond()); + mv.visitJumpInsn(IFEQ, end); + generate(state, _while.body()); + mv.visitJumpInsn(GOTO, start); + mv.visitLabel(end); + break; + } + case TargetIf _if: { + generate(state, _if.cond()); + Label _else = new Label(); + Label end = new Label(); + mv.visitJumpInsn(IFEQ, _else); + generate(state, _if.if_body()); + mv.visitJumpInsn(GOTO, end); + mv.visitLabel(_else); + if (_if.else_body() != null) { + generate(state, _if.else_body()); + } + mv.visitLabel(end); + break; + } + case TargetReturn ret: { + generate(state, ret.expression()); + if (ret.expression() != null) + mv.visitInsn(ARETURN); + else mv.visitInsn(RETURN); + break; + } + case TargetThis _this: { + mv.visitVarInsn(ALOAD, 0); + break; + } + case TargetSuper _super: { + // TODO + break; + } + case TargetMethodCall call: { + var method = call.method(); + generate(state, call.expr()); + for (TargetExpression e : call.args()) { + generate(state, e); + boxPrimitive(state, e.type()); + } + mv.visitMethodInsn(method.isStatic() ? INVOKESTATIC: INVOKEVIRTUAL, method.owner().qualifiedName(), method.name(), method.getDescriptor(), false); + break; + } + case TargetLambdaExpression lambda: + generateLambdaExpression(state, lambda); + break; default: - throw new IllegalStateException("Unexpected value: " + expr); + throw new CodeGenException("Unexpected value: " + expr); } } @@ -99,6 +565,7 @@ public class Codegen { private void generateConstructor(TargetConstructor constructor) { MethodVisitor mv = cw.visitMethod(constructor.access(), "", constructor.getDescriptor(), null, null); + mv.visitCode(); generate(new State(mv), constructor.block()); mv.visitMaxs(0, 0); mv.visitEnd(); @@ -106,6 +573,7 @@ public class Codegen { private void generateMethod(TargetMethod method) { MethodVisitor mv = cw.visitMethod(method.access(), method.name(), method.getDescriptor(), null, null); + mv.visitCode(); generate(new State(mv), method.block()); mv.visitMaxs(0, 0); mv.visitEnd(); diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index 63248f92..19420501 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -30,7 +30,8 @@ public class ASTToTargetAST { private TargetMethod convert(Method input, Map sigma) { List params = input.getParameterList().getFormalparalist().stream() .map(param -> new MethodParameter(convert(param.getType(), sigma), param.getName())).collect(Collectors.toList()); - return new TargetMethod(input.name, params, convert(input.block)); + // TODO + return new TargetMethod(0, null, input.name, params, convert(input.block)); } private TargetBlock convert(Block block) { diff --git a/src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java index a78da9d3..b6c88b2d 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java @@ -1,10 +1,32 @@ 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.lang.annotation.Target; +import java.util.ArrayList; import java.util.List; public record TargetClass(int modifiers, String qualifiedName, TargetType superType, List implementingInterfaces, - List constructors, List fields, List methods) {} + 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<>()); + } + public TargetClass(int modifiers, String qualifiedName, List implementingInterfaces) { + this(modifiers, qualifiedName, TargetType.Object, implementingInterfaces, new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); + } + + public void addMethod(int access, String name, List parameterTypes, TargetBlock block) { + this.methods.add(new TargetMethod(access, this, name, parameterTypes, block)); + } + + public void addConstructor(int access, List paramterTypes, TargetBlock block) { + this.constructors.add(new TargetConstructor(access, this, paramterTypes, block)); + } + + public void addField(int access, TargetType type, String name) { + this.fields.add(new TargetField(access, this, 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 594d5a20..4972fbed 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java @@ -4,7 +4,7 @@ import de.dhbwstuttgart.target.tree.expression.TargetBlock; import java.util.List; -public record TargetConstructor(int access, List parameterTypes, TargetBlock block) { +public record TargetConstructor(int access, TargetClass owner, List parameterTypes, TargetBlock block) { public String getDescriptor() { // TODO diff --git a/src/main/java/de/dhbwstuttgart/target/tree/TargetField.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetField.java index c9076736..08b8e0d7 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 type, String name) { +public record TargetField(int access, TargetClass owner, TargetType type, String name) { public String getDescriptor() { // TODO return null; diff --git a/src/main/java/de/dhbwstuttgart/target/tree/TargetInterface.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetInterface.java new file mode 100644 index 00000000..f15acad4 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetInterface.java @@ -0,0 +1,6 @@ +package de.dhbwstuttgart.target.tree; + +import java.util.List; + +public record TargetInterface(String name, List methods, List extendedInterfaces) { +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java index 767f2689..fefe7d2e 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java @@ -1,13 +1,18 @@ package de.dhbwstuttgart.target.tree; import de.dhbwstuttgart.target.tree.expression.TargetBlock; +import org.objectweb.asm.Opcodes; import java.util.List; -public record TargetMethod(int access, String name, List parameterTypes, TargetBlock block) { +public record TargetMethod(int access, TargetClass owner, String name, List parameterTypes, TargetBlock block) { public String getDescriptor() { // TODO return null; } + + public boolean isStatic() { + return (access & Opcodes.ACC_STATIC) != 0; + } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetAssign.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetAssign.java index fd4bf51e..609de796 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetAssign.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetAssign.java @@ -2,5 +2,5 @@ package de.dhbwstuttgart.target.tree.expression; import de.dhbwstuttgart.target.tree.type.TargetType; -public record TargetAssign(TargetType type, TargetExpression leftSide, TargetExpression rightSide) implements TargetExpression { +public record TargetAssign(TargetType type, TargetExpression left, TargetExpression right) implements TargetStatementExpression { } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBinaryOp.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBinaryOp.java index 233157c5..fc06719b 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBinaryOp.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBinaryOp.java @@ -7,7 +7,7 @@ public sealed interface TargetBinaryOp extends TargetExpression { TargetExpression left(); TargetExpression right(); - // Artihmetic + // Arithmetic record Add(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} record Sub(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} record Div(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} @@ -34,7 +34,6 @@ public sealed interface TargetBinaryOp extends TargetExpression { record LessOrEqual(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} record NotEqual(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} - record Assign(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetClassName.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetClassName.java new file mode 100644 index 00000000..7131acac --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetClassName.java @@ -0,0 +1,6 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetClassName(TargetType type) implements TargetExpression { +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetDot.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetDot.java deleted file mode 100644 index 6eef9857..00000000 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetDot.java +++ /dev/null @@ -1,6 +0,0 @@ -package de.dhbwstuttgart.target.tree.expression; - -import de.dhbwstuttgart.target.tree.type.TargetType; - -public record TargetDot(TargetType type, boolean isStatic, TargetExpression left, String right) implements TargetExpression { -} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java index 7c9c85a2..64146f7e 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java @@ -3,7 +3,7 @@ package de.dhbwstuttgart.target.tree.expression; import de.dhbwstuttgart.target.tree.type.*; public sealed interface TargetExpression - permits TargetAssign, TargetBinaryOp, TargetBlock, TargetBreak, TargetCast, TargetContinue, TargetDot, TargetFieldVar, TargetFor, TargetForEach, TargetIf, TargetInstanceOf, TargetLambdaExpression, TargetLiteral, TargetLocalVar, TargetMethodCall, TargetNew, TargetReturn, TargetSuper, TargetSwitch, TargetThis, TargetUnaryOp, TargetVarDecl, TargetWhile { + permits TargetBinaryOp, TargetBlock, TargetBreak, TargetCast, TargetClassName, TargetContinue, TargetFieldVar, TargetFor, TargetForEach, TargetIf, TargetInstanceOf, TargetLambdaExpression, TargetLiteral, TargetLocalVar, TargetReturn, TargetStatementExpression, TargetSuper, TargetSwitch, TargetTernary, TargetThis, TargetUnaryOp, TargetVarDecl, TargetWhile { TargetType type(); } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFieldVar.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFieldVar.java index 9835fc9f..5d41b1b4 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFieldVar.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFieldVar.java @@ -1,7 +1,6 @@ package de.dhbwstuttgart.target.tree.expression; -import de.dhbwstuttgart.target.tree.TargetField; import de.dhbwstuttgart.target.tree.type.TargetType; -public record TargetFieldVar(TargetType type, TargetField field) implements TargetExpression { +public record TargetFieldVar(TargetType type, boolean isStatic, TargetExpression left, String right) implements TargetExpression { } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetIf.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetIf.java index ef94fc0b..78bc766b 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetIf.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetIf.java @@ -2,7 +2,7 @@ package de.dhbwstuttgart.target.tree.expression; import de.dhbwstuttgart.target.tree.type.TargetType; -public record TargetIf(TargetExpression expr, TargetExpression if_body, TargetExpression else_body) implements TargetExpression { +public record TargetIf(TargetExpression cond, TargetExpression if_body, TargetExpression else_body) implements TargetExpression { @Override public TargetType type() { return null; diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetMethodCall.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetMethodCall.java index 6a812604..0e7359f8 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetMethodCall.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetMethodCall.java @@ -5,5 +5,5 @@ import de.dhbwstuttgart.target.tree.type.TargetType; import java.util.List; -public record TargetMethodCall(TargetType type, TargetExpression expr, List args, TargetMethod method) implements TargetExpression { +public record TargetMethodCall(TargetType type, TargetExpression expr, List args, TargetMethod method) implements TargetStatementExpression { } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetNew.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetNew.java index 6819a744..30fb295c 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetNew.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetNew.java @@ -4,5 +4,5 @@ import de.dhbwstuttgart.target.tree.type.TargetType; import java.util.List; -public record TargetNew(TargetType type, List params) implements TargetExpression { +public record TargetNew(TargetType type, List params) implements TargetStatementExpression { } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetStatementExpression.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetStatementExpression.java new file mode 100644 index 00000000..2d804d6a --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetStatementExpression.java @@ -0,0 +1,4 @@ +package de.dhbwstuttgart.target.tree.expression; + +public sealed interface TargetStatementExpression extends TargetExpression permits TargetAssign, TargetMethodCall, TargetNew, TargetUnaryOp.PostDecrement, TargetUnaryOp.PostIncrement, TargetUnaryOp.PreDecrement, TargetUnaryOp.PreIncrement { +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetTernary.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetTernary.java new file mode 100644 index 00000000..17349489 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetTernary.java @@ -0,0 +1,6 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetTernary(TargetType type, TargetExpression cond, TargetExpression ifTrue, TargetExpression ifFalse) implements TargetExpression { +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetUnaryOp.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetUnaryOp.java index eec72196..457a55ad 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetUnaryOp.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetUnaryOp.java @@ -6,10 +6,10 @@ public sealed interface TargetUnaryOp extends TargetExpression { TargetExpression expr(); record Negate(TargetType type, TargetExpression expr) implements TargetUnaryOp {} - record Not(TargetType type, TargetExpression expr) implements TargetUnaryOp {} + record Not(TargetType type, TargetExpression expr) implements TargetUnaryOp {} - record PreIncrement(TargetType type, TargetExpression expr) implements TargetUnaryOp {} - record PostIncrement(TargetType type, TargetExpression expr) implements TargetUnaryOp {} - record PreDecrement(TargetType type, TargetExpression expr) implements TargetUnaryOp {} - record PostDecrement(TargetType type, TargetExpression expr) implements TargetUnaryOp {} + record PreIncrement(TargetType type, TargetExpression expr) implements TargetStatementExpression {} + record PostIncrement(TargetType type, TargetExpression expr) implements TargetStatementExpression {} + record PreDecrement(TargetType type, TargetExpression expr) implements TargetStatementExpression {} + record PostDecrement(TargetType type, TargetExpression expr) implements TargetStatementExpression {} } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetWhile.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetWhile.java index 5f0b8b06..62ff90dc 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetWhile.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetWhile.java @@ -2,7 +2,7 @@ package de.dhbwstuttgart.target.tree.expression; import de.dhbwstuttgart.target.tree.type.TargetType; -public record TargetWhile(TargetExpression expr, TargetExpression body) implements TargetExpression { +public record TargetWhile(TargetExpression cond, TargetExpression body) implements TargetExpression { @Override public TargetType type() { 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 66a2b8ac..1e892a25 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetRefType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetRefType.java @@ -7,6 +7,6 @@ import java.util.List; public record TargetRefType(String name, List params) implements TargetType { @Override public String toSignature() { - return "L" + this.name.replaceAll("\\.", "/"); + return "L" + this.name.replaceAll("\\.", "/") + ";"; } } 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 7f78b431..49ed4106 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetType.java @@ -15,6 +15,7 @@ public sealed interface TargetType TargetRefType Float = new TargetRefType("java.lang.Float", List.of()); TargetRefType Double = new TargetRefType("java.lang.Double", List.of()); TargetRefType String = new TargetRefType("java.lang.String", List.of()); + TargetRefType Object = new TargetRefType("java.lang.Object", List.of()); String toSignature(); } diff --git a/src/test/java/targetast/ByteArrayClassLoader.java b/src/test/java/targetast/ByteArrayClassLoader.java new file mode 100644 index 00000000..227b7094 --- /dev/null +++ b/src/test/java/targetast/ByteArrayClassLoader.java @@ -0,0 +1,9 @@ +package targetast; + +import java.util.Map; + +public class ByteArrayClassLoader extends ClassLoader { + public Class loadClass(byte[] code) { + return this.defineClass(null, code, 0, code.length); + } +} diff --git a/src/test/java/targetast/TestCodegen.java b/src/test/java/targetast/TestCodegen.java new file mode 100644 index 00000000..dc5f03f8 --- /dev/null +++ b/src/test/java/targetast/TestCodegen.java @@ -0,0 +1,25 @@ +package targetast; + +import de.dhbwstuttgart.target.bytecode.Codegen; +import de.dhbwstuttgart.target.tree.TargetClass; +import de.dhbwstuttgart.target.tree.TargetMethod; +import de.dhbwstuttgart.target.tree.expression.TargetBlock; +import org.junit.Test; +import org.objectweb.asm.Opcodes; + +import java.util.List; + +public class TestCodegen { + + private static Class generateClass(TargetClass clazz) { + var codegen = new Codegen(clazz); + return new ByteArrayClassLoader().loadClass(codegen.generate()); + } + + @Test + public void testEmptyClass() throws Exception { + var clazz = new TargetClass(Opcodes.ACC_PUBLIC, "Main"); + clazz.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "main", List.of(), new TargetBlock(List.of())); + generateClass(clazz).getDeclaredMethod("main").invoke(null); + } +} From 6c584f92e99910d2d90157451b76a349a2eb70b2 Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Mon, 16 May 2022 14:18:58 +0200 Subject: [PATCH 41/69] More tests --- .../target/bytecode/Codegen.java | 228 +++++++++++++++--- .../target/generate/ASTToTargetAST.java | 2 +- .../target/tree/TargetClass.java | 8 +- .../target/tree/TargetConstructor.java | 3 +- .../target/tree/TargetField.java | 3 +- .../target/tree/TargetMethod.java | 22 +- .../tree/expression/TargetBinaryOp.java | 20 +- .../target/tree/expression/TargetLiteral.java | 23 +- .../tree/expression/TargetMethodCall.java | 3 +- .../target/tree/expression/TargetVarDecl.java | 2 +- .../target/tree/type/TargetRefType.java | 10 +- .../target/tree/type/TargetType.java | 20 +- src/test/java/targetast/TestCodegen.java | 178 +++++++++++++- 13 files changed, 455 insertions(+), 67 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java index c8bf7fd8..ee5ed659 100755 --- a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java @@ -11,10 +11,12 @@ import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; +import java.util.HashMap; import java.util.Map; import static org.objectweb.asm.Opcodes.*; import static de.dhbwstuttgart.target.tree.expression.TargetBinaryOp.*; +import static de.dhbwstuttgart.target.tree.expression.TargetLiteral.*; public class Codegen { private TargetClass clazz; @@ -25,11 +27,11 @@ public class Codegen { this.cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); } - private static record LocalVar(int index, String name, TargetType type) {} + private record LocalVar(int index, String name, TargetType type) {} private static class Scope { Scope parent; - Map locals; + Map locals = new HashMap<>(); Scope(Scope parent) { this.parent = parent; @@ -41,7 +43,7 @@ public class Codegen { LocalVar get(String name) { var local = locals.get(name); - if (local != null ){ + if (local != null) { return local; } if (parent != null) { @@ -53,11 +55,12 @@ public class Codegen { private static class State { Scope scope = new Scope(null); - int localCounter = 1; + int localCounter; MethodVisitor mv; - State(MethodVisitor mv) { + State(MethodVisitor mv, int localCounter) { this.mv = mv; + this.localCounter = localCounter; } void enterScope() { @@ -68,9 +71,11 @@ public class Codegen { this.scope = this.scope.parent; } - void createVariable(String name, TargetType type) { - scope.add(new LocalVar(localCounter, name, type)); + LocalVar createVariable(String name, TargetType type) { + var local = new LocalVar(localCounter, name, type); + scope.add(local); localCounter += 1; + return local; } } @@ -83,9 +88,9 @@ public class Codegen { } else if (type.equals(TargetType.Double)) { mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false); } else if (type.equals(TargetType.Long)) { - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(L)Ljava/lang/Long;", false); + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false); } else if (type.equals(TargetType.Integer)) { - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(L)Ljava/lang/Integer;", false); + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false); } else if (type.equals(TargetType.Float)) { mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false); } else if (type.equals(TargetType.Short)) { @@ -104,7 +109,7 @@ public class Codegen { } else if (type.equals(TargetType.Double)) { mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false); } else if (type.equals(TargetType.Long)) { - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()L", false); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false); } else if (type.equals(TargetType.Integer)) { mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false); } else if (type.equals(TargetType.Float)) { @@ -116,12 +121,14 @@ public class Codegen { } } - private void generateRelationalOperator(State state, TargetBinaryOp op, int code) { + private void generateRelationalOperator(State state, TargetRelationalOp op, int code) { var mv = state.mv; Label if_true = new Label(); Label end = new Label(); generate(state, op.left()); + convertTo(state, op.exprType(), op.type()); generate(state, op.right()); + convertTo(state, op.exprType(), op.type()); mv.visitJumpInsn(code, if_true); mv.visitInsn(ICONST_0); mv.visitJumpInsn(GOTO, end); @@ -130,12 +137,14 @@ public class Codegen { mv.visitLabel(end); } - private void generateRelationalOperator(State state, TargetBinaryOp op, int cmp, int code) { + private void generateRelationalOperator(State state, TargetRelationalOp op, int cmp, int code) { var mv = state.mv; Label if_true = new Label(); Label end = new Label(); generate(state, op.left()); + convertTo(state, op.left().type(), op.exprType()); generate(state, op.right()); + convertTo(state, op.right().type(), op.exprType()); mv.visitInsn(cmp); mv.visitInsn(code); mv.visitJumpInsn(code, if_true); @@ -146,14 +155,82 @@ public class Codegen { mv.visitLabel(end); } + private void convertTo(State state, TargetType source, TargetType dest) { + var mv = state.mv; + if (source.equals(dest)) + return; + if (source.equals(TargetType.Long)) { + if (dest.equals(TargetType.Integer)) + mv.visitInsn(L2I); + else if (dest.equals(TargetType.Float)) + mv.visitInsn(L2F); + else if (dest.equals(TargetType.Double)) + mv.visitInsn(L2D); + else if (dest.equals(TargetType.Byte) + || dest.equals(TargetType.Char) + || dest.equals(TargetType.Short)) { + mv.visitInsn(L2I); + source = TargetType.Integer; + } + } else if (source.equals(TargetType.Float)) { + if (dest.equals(TargetType.Integer)) + mv.visitInsn(F2I); + else if (dest.equals(TargetType.Double)) + mv.visitInsn(F2D); + else if (dest.equals(TargetType.Long)) + mv.visitInsn(F2L); + else if (dest.equals(TargetType.Byte) + || dest.equals(TargetType.Char) + || dest.equals(TargetType.Short)) { + mv.visitInsn(F2I); + source = TargetType.Integer; + } + } else if (source.equals(TargetType.Double)) { + if (dest.equals(TargetType.Integer)) + mv.visitInsn(D2I); + else if (dest.equals(TargetType.Float)) + mv.visitInsn(D2F); + else if (dest.equals(TargetType.Long)) + mv.visitInsn(D2L); + else if (dest.equals(TargetType.Byte) + || dest.equals(TargetType.Char) + || dest.equals(TargetType.Short)) { + mv.visitInsn(D2I); + source = TargetType.Integer; + } + } + if (source.equals(TargetType.Byte) + || source.equals(TargetType.Char) + || source.equals(TargetType.Short) + || source.equals(TargetType.Integer)) { + if (dest.equals(TargetType.Byte)) + mv.visitInsn(I2B); + else if (dest.equals(TargetType.Char)) + mv.visitInsn(I2C); + else if (dest.equals(TargetType.Short)) + mv.visitInsn(I2S); + else if (dest.equals(TargetType.Long)) + mv.visitInsn(I2L); + else if (dest.equals(TargetType.Float)) + mv.visitInsn(I2F); + else if (dest.equals(TargetType.Double)) + mv.visitInsn(I2D); + } else { + mv.visitTypeInsn(CHECKCAST, ((TargetRefType) dest).getName()); + } + } + private void generateBinaryOp(State state, TargetBinaryOp op) { var mv = state.mv; switch (op) { case Add add: { generate(state, add.left()); + convertTo(state, add.left().type(), op.type()); generate(state, add.right()); + convertTo(state, add.right().type(), op.type()); var type = add.type(); if (type.equals(TargetType.Byte) + || type.equals(TargetType.Char) || type.equals(TargetType.Integer) || type.equals(TargetType.Short)) { mv.visitInsn(IADD); @@ -170,9 +247,12 @@ public class Codegen { } case Sub sub: { generate(state, sub.left()); + convertTo(state, sub.left().type(), op.type()); generate(state, sub.right()); + convertTo(state, sub.right().type(), op.type()); var type = sub.type(); if (type.equals(TargetType.Byte) + || type.equals(TargetType.Char) || type.equals(TargetType.Integer) || type.equals(TargetType.Short)) { mv.visitInsn(ISUB); @@ -189,9 +269,12 @@ public class Codegen { } case Div div: { generate(state, div.left()); + convertTo(state, div.left().type(), op.type()); generate(state, div.right()); + convertTo(state, div.right().type(), op.type()); var type = div.type(); if (type.equals(TargetType.Byte) + || type.equals(TargetType.Char) || type.equals(TargetType.Integer) || type.equals(TargetType.Short)) { mv.visitInsn(IDIV); @@ -208,9 +291,12 @@ public class Codegen { } case Mul mul: { generate(state, mul.left()); + convertTo(state, mul.left().type(), op.type()); generate(state, mul.right()); + convertTo(state, mul.right().type(), op.type()); var type = mul.type(); if (type.equals(TargetType.Byte) + || type.equals(TargetType.Char) || type.equals(TargetType.Integer) || type.equals(TargetType.Short)) { mv.visitInsn(IMUL); @@ -227,9 +313,12 @@ public class Codegen { } case Rem rem: { generate(state, rem.left()); + convertTo(state, rem.left().type(), op.type()); generate(state, rem.right()); + convertTo(state, rem.right().type(), op.type()); var type = rem.type(); if (type.equals(TargetType.Byte) + || type.equals(TargetType.Char) || type.equals(TargetType.Integer) || type.equals(TargetType.Short)) { mv.visitInsn(IREM); @@ -276,7 +365,9 @@ public class Codegen { } case BAnd band: { generate(state, band.left()); + convertTo(state, band.left().type(), op.type()); generate(state, band.right()); + convertTo(state, band.right().type(), op.type()); if (band.type().equals(TargetType.Long)) mv.visitInsn(LAND); else mv.visitInsn(IAND); @@ -284,7 +375,9 @@ public class Codegen { } case BOr bor: { generate(state, bor.left()); + convertTo(state, bor.left().type(), op.type()); generate(state, bor.right()); + convertTo(state, bor.right().type(), op.type()); if (bor.type().equals(TargetType.Long)) mv.visitInsn(LOR); else mv.visitInsn(IOR); @@ -292,7 +385,9 @@ public class Codegen { } case XOr xor: { generate(state, xor.left()); + convertTo(state, xor.left().type(), op.type()); generate(state, xor.right()); + convertTo(state, xor.right().type(), op.type()); if (xor.type().equals(TargetType.Long)) mv.visitInsn(LXOR); else mv.visitInsn(IXOR); @@ -300,7 +395,9 @@ public class Codegen { } case Shl shl: { generate(state, shl.left()); + convertTo(state, shl.left().type(), op.type()); generate(state, shl.right()); + convertTo(state, shl.right().type(), op.type()); if (shl.type().equals(TargetType.Long)) mv.visitInsn(LSHL); else mv.visitInsn(ISHL); @@ -308,7 +405,9 @@ public class Codegen { } case Shr shr: { generate(state, shr.left()); + convertTo(state, shr.left().type(), op.type()); generate(state, shr.right()); + convertTo(state, shr.right().type(), op.type()); if (shr.type().equals(TargetType.Long)) mv.visitInsn(LSHR); else mv.visitInsn(ISHR); @@ -316,14 +415,16 @@ public class Codegen { } case UShr ushr: { generate(state, ushr.left()); + convertTo(state, ushr.left().type(), op.type()); generate(state, ushr.right()); + convertTo(state, ushr.right().type(), op.type()); if (ushr.type().equals(TargetType.Long)) mv.visitInsn(LUSHR); else mv.visitInsn(IUSHR); break; } case Greater greater: { - var type = greater.type(); + var type = greater.exprType(); if (type.equals(TargetType.Long)) { generateRelationalOperator(state, greater, LCMP, IFGT); } else if (type.equals(TargetType.Float)) { @@ -336,7 +437,7 @@ public class Codegen { break; } case Less less: { - var type = less.type(); + var type = less.exprType(); if (type.equals(TargetType.Long)) { generateRelationalOperator(state, less, LCMP, IFLT); } else if (type.equals(TargetType.Float)) { @@ -349,7 +450,7 @@ public class Codegen { break; } case GreaterOrEqual greaterOrEqual: { - var type = greaterOrEqual.type(); + var type = greaterOrEqual.exprType(); if (type.equals(TargetType.Long)) { generateRelationalOperator(state, greaterOrEqual, LCMP, IFGE); } else if (type.equals(TargetType.Float)) { @@ -362,7 +463,7 @@ public class Codegen { break; } case LessOrEqual lessOrEqual: { - var type = lessOrEqual.type(); + var type = lessOrEqual.exprType(); if (type.equals(TargetType.Long)) { generateRelationalOperator(state, lessOrEqual, LCMP, IFLE); } else if (type.equals(TargetType.Float)) { @@ -375,7 +476,7 @@ public class Codegen { break; } case Equal equal: { - var type = equal.type(); + var type = equal.exprType(); if (type.equals(TargetType.Long)) { generateRelationalOperator(state, equal, LCMP, IFEQ); } else if (type.equals(TargetType.Float)) { @@ -393,7 +494,7 @@ public class Codegen { break; } case NotEqual notEqual: { - var type = notEqual.type(); + var type = notEqual.exprType(); if (type.equals(TargetType.Long)) { generateRelationalOperator(state, notEqual, LCMP, IFNE); } else if (type.equals(TargetType.Float)) { @@ -419,6 +520,8 @@ public class Codegen { private void generate(State state, TargetExpression expr) { var mv = state.mv; switch (expr) { + case TargetClassName className: + break; // NOP case TargetBlock block: { var localCounter = state.localCounter; state.enterScope(); @@ -434,18 +537,60 @@ public class Codegen { state.localCounter = localCounter; break; } - case TargetVarDecl varDecl: - state.createVariable(varDecl.name(), varDecl.varType()); + case TargetCast cast: + generate(state, cast.expr()); + convertTo(state, cast.expr().type(), cast.type()); break; + case TargetInstanceOf instanceOf: + mv.visitTypeInsn(INSTANCEOF, ((TargetRefType) instanceOf.right()).getName()); + break; + case TargetLiteral literal: + switch (literal) { + case IntLiteral intLiteral: + mv.visitLdcInsn(intLiteral.value()); + break; + case FloatLiteral floatLiteral: + mv.visitLdcInsn(floatLiteral.value()); + break; + case LongLiteral longLiteral: + mv.visitLdcInsn(longLiteral.value()); + break; + case StringLiteral stringLiteral: + mv.visitLdcInsn(stringLiteral.value()); + break; + case CharLiteral charLiteral: + mv.visitIntInsn(BIPUSH, charLiteral.value()); + break; + case DoubleLiteral doubleLiteral: + mv.visitLdcInsn(doubleLiteral.value()); + break; + case BooleanLiteral booleanLiteral: + if (booleanLiteral.value()) { + mv.visitInsn(ICONST_1); + } else { + mv.visitInsn(ICONST_0); + } + break; + } + break; + case TargetVarDecl varDecl: { + var local = state.createVariable(varDecl.name(), varDecl.varType()); + generate(state, varDecl.value()); + boxPrimitive(state, varDecl.varType()); + mv.visitVarInsn(ASTORE, local.index()); + break; + } case TargetBinaryOp op: generateBinaryOp(state, op); break; case TargetAssign assign: { switch (assign.left()) { - case TargetLocalVar local: { + case TargetLocalVar localVar: { generate(state, assign.right()); boxPrimitive(state, assign.right().type()); - mv.visitInsn(ASTORE); + var local = state.scope.get(localVar.name()); + mv.visitInsn(DUP); + mv.visitVarInsn(ASTORE, local.index()); break; } case TargetFieldVar dot: { @@ -456,7 +601,7 @@ public class Codegen { if (dot.isStatic()) mv.visitInsn(DUP); else mv.visitInsn(DUP_X1); - mv.visitFieldInsn(dot.isStatic() ? PUTSTATIC : PUTFIELD, dot.right(), type.name(), type.toSignature()); + mv.visitFieldInsn(dot.isStatic() ? PUTSTATIC : PUTFIELD, dot.right(), type.getName(), type.toSignature()); break; } default: @@ -474,7 +619,7 @@ public class Codegen { if (!dot.isStatic()) generate(state, dot.left()); var type = (TargetRefType) dot.left().type(); - mv.visitFieldInsn(dot.isStatic() ? GETSTATIC : GETFIELD, type.name(), dot.right(), dot.type().toSignature()); + mv.visitFieldInsn(dot.isStatic() ? GETSTATIC : GETFIELD, type.getName(), dot.right(), dot.type().toSignature()); break; } case TargetFor _for: { @@ -528,9 +673,11 @@ public class Codegen { } case TargetReturn ret: { generate(state, ret.expression()); - if (ret.expression() != null) + + if (ret.expression() != null) { + boxPrimitive(state, ret.expression().type()); mv.visitInsn(ARETURN); - else mv.visitInsn(RETURN); + } else mv.visitInsn(RETURN); break; } case TargetThis _this: { @@ -542,13 +689,12 @@ public class Codegen { break; } case TargetMethodCall call: { - var method = call.method(); generate(state, call.expr()); for (TargetExpression e : call.args()) { generate(state, e); boxPrimitive(state, e.type()); } - mv.visitMethodInsn(method.isStatic() ? INVOKESTATIC: INVOKEVIRTUAL, method.owner().qualifiedName(), method.name(), method.getDescriptor(), false); + mv.visitMethodInsn(call.isStatic() ? INVOKESTATIC: INVOKEVIRTUAL, call.owner().getName(), call.name(), call.descriptor(), false); break; } case TargetLambdaExpression lambda: @@ -566,7 +712,11 @@ public class Codegen { private void generateConstructor(TargetConstructor constructor) { MethodVisitor mv = cw.visitMethod(constructor.access(), "", constructor.getDescriptor(), null, null); mv.visitCode(); - generate(new State(mv), constructor.block()); + var state = new State(mv, 1); + for (var param: constructor.parameters()) + state.createVariable(param.name(), param.type()); + generate(state, constructor.block()); + mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } @@ -574,18 +724,32 @@ public class Codegen { private void generateMethod(TargetMethod method) { MethodVisitor mv = cw.visitMethod(method.access(), method.name(), method.getDescriptor(), null, null); mv.visitCode(); - generate(new State(mv), method.block()); + var state = new State(mv, method.isStatic() ? 0 : 1); + for (var param: method.parameters()) + state.createVariable(param.name(), param.type()); + generate(state, method.block()); + if (method.returnType() == null) + mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } public byte[] generate() { cw.visit(V1_8, clazz.modifiers(), clazz.qualifiedName(), - null, clazz.superType().toSignature(), + null, ((TargetRefType) clazz.superType()).getName(), clazz.implementingInterfaces().stream().map(TargetType::toSignature).toArray(String[]::new) ); clazz.fields().forEach(this::generateField); - clazz.constructors().forEach(this::generateConstructor); + if (clazz.constructors().size() == 0) { + var mv = cw.visitMethod(ACC_PROTECTED, "", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, ((TargetRefType) clazz.superType()).getName(), "", "()V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + else clazz.constructors().forEach(this::generateConstructor); clazz.methods().forEach(this::generateMethod); cw.visitEnd(); diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index 19420501..709a3350 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -31,7 +31,7 @@ public class ASTToTargetAST { List params = input.getParameterList().getFormalparalist().stream() .map(param -> new MethodParameter(convert(param.getType(), sigma), param.getName())).collect(Collectors.toList()); // TODO - return new TargetMethod(0, null, input.name, params, convert(input.block)); + return new TargetMethod(0, null, input.name, params, null, convert(input.block)); } private TargetBlock convert(Block block) { diff --git a/src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java index b6c88b2d..63010136 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java @@ -17,16 +17,16 @@ public record TargetClass(int modifiers, String qualifiedName, TargetType superT this(modifiers, qualifiedName, TargetType.Object, implementingInterfaces, new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); } - public void addMethod(int access, String name, List parameterTypes, TargetBlock block) { - this.methods.add(new TargetMethod(access, this, name, parameterTypes, 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)); } public void addConstructor(int access, List paramterTypes, TargetBlock block) { - this.constructors.add(new TargetConstructor(access, this, paramterTypes, block)); + this.constructors.add(new TargetConstructor(access, new TargetRefType(this.qualifiedName, List.of()), paramterTypes, block)); } public void addField(int access, TargetType type, String name) { - this.fields.add(new TargetField(access, this, type, name)); + this.fields.add(new TargetField(access, new TargetRefType(this.qualifiedName, List.of()), 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 4972fbed..3a242c1e 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java @@ -1,10 +1,11 @@ package de.dhbwstuttgart.target.tree; import de.dhbwstuttgart.target.tree.expression.TargetBlock; +import de.dhbwstuttgart.target.tree.type.TargetRefType; import java.util.List; -public record TargetConstructor(int access, TargetClass owner, List parameterTypes, TargetBlock block) { +public record TargetConstructor(int access, TargetRefType owner, List parameters, TargetBlock block) { public String getDescriptor() { // TODO diff --git a/src/main/java/de/dhbwstuttgart/target/tree/TargetField.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetField.java index 08b8e0d7..2c183dcb 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/TargetField.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetField.java @@ -1,9 +1,10 @@ package de.dhbwstuttgart.target.tree; +import de.dhbwstuttgart.target.tree.type.TargetRefType; import de.dhbwstuttgart.target.tree.type.TargetType; import org.objectweb.asm.Opcodes; -public record TargetField(int access, TargetClass owner, TargetType type, String name) { +public record TargetField(int access, TargetRefType owner, TargetType type, String name) { public String getDescriptor() { // TODO return null; diff --git a/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java index fefe7d2e..bfd8f3b4 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java @@ -1,14 +1,30 @@ 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; + +public record TargetMethod(int access, TargetRefType owner, String name, List parameters, TargetType returnType, TargetBlock block) { + public static String getDescriptor(TargetType returnType, TargetType... parameters) { + String ret = "("; + for (var parameterType : parameters) { + ret += parameterType.toSignature(); + } + ret += ")"; + if (returnType == null) { + ret += "V"; + } else { + ret += returnType.toSignature(); + } + return ret; + } -public record TargetMethod(int access, TargetClass owner, String name, List parameterTypes, TargetBlock block) { public String getDescriptor() { - // TODO - return null; + return getDescriptor(returnType, parameters.stream().map(MethodParameter::type).toArray(TargetType[]::new)); } public boolean isStatic() { diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBinaryOp.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBinaryOp.java index fc06719b..814a4d67 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBinaryOp.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBinaryOp.java @@ -26,13 +26,21 @@ public sealed interface TargetBinaryOp extends TargetExpression { record And(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} record Or(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + sealed interface TargetRelationalOp extends TargetBinaryOp { + @Override + default TargetType type() { + return TargetType.Boolean; + } + TargetType exprType(); + } + // Comparison - record Equal(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} - record Greater(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} - record GreaterOrEqual(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} - record Less(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} - record LessOrEqual(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} - record NotEqual(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + record Equal(TargetType exprType, TargetExpression left, TargetExpression right) implements TargetRelationalOp {} + record Greater(TargetType exprType, TargetExpression left, TargetExpression right) implements TargetRelationalOp {} + record GreaterOrEqual(TargetType exprType, TargetExpression left, TargetExpression right) implements TargetRelationalOp {} + record Less(TargetType exprType, TargetExpression left, TargetExpression right) implements TargetRelationalOp {} + record LessOrEqual(TargetType exprType, TargetExpression left, TargetExpression right) implements TargetRelationalOp {} + record NotEqual(TargetType exprType, TargetExpression left, TargetExpression right) implements TargetRelationalOp {} } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLiteral.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLiteral.java index 31ccb1f7..c4673682 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLiteral.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLiteral.java @@ -5,7 +5,14 @@ import de.dhbwstuttgart.target.tree.type.TargetType; public sealed interface TargetLiteral extends TargetExpression { Object value(); - record CharLiteral(Integer value) implements TargetLiteral { + record BooleanLiteral(Boolean value) implements TargetLiteral { + @Override + public TargetType type() { + return TargetType.Boolean; + } + } + + record CharLiteral(Character value) implements TargetLiteral { @Override public TargetType type() { return TargetType.Char; @@ -26,6 +33,20 @@ public sealed interface TargetLiteral extends TargetExpression { } } + record FloatLiteral(Float value) implements TargetLiteral { + @Override + public TargetType type() { + return TargetType.Float; + } + } + + record DoubleLiteral(Double value) implements TargetLiteral { + @Override + public TargetType type() { + return TargetType.Double; + } + } + record StringLiteral(String value) implements TargetLiteral { @Override public TargetType type() { diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetMethodCall.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetMethodCall.java index 0e7359f8..132ec11b 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetMethodCall.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetMethodCall.java @@ -1,9 +1,10 @@ package de.dhbwstuttgart.target.tree.expression; import de.dhbwstuttgart.target.tree.TargetMethod; +import de.dhbwstuttgart.target.tree.type.TargetRefType; import de.dhbwstuttgart.target.tree.type.TargetType; import java.util.List; -public record TargetMethodCall(TargetType type, TargetExpression expr, List args, TargetMethod method) implements TargetStatementExpression { +public record TargetMethodCall(TargetType type, TargetExpression expr, List args, TargetRefType owner, String name, String descriptor, boolean isStatic) implements TargetStatementExpression { } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetVarDecl.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetVarDecl.java index b0c15225..b1eda5e7 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetVarDecl.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetVarDecl.java @@ -2,7 +2,7 @@ package de.dhbwstuttgart.target.tree.expression; import de.dhbwstuttgart.target.tree.type.TargetType; -public record TargetVarDecl(String name, TargetType varType) implements TargetExpression { +public record TargetVarDecl(TargetType varType, String name, TargetExpression value) implements TargetExpression { @Override public TargetType type() { 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 1e892a25..5944fdbe 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetRefType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetRefType.java @@ -5,8 +5,16 @@ import de.dhbwstuttgart.target.tree.type.TargetType; import java.util.List; public record TargetRefType(String name, List params) implements TargetType { + public TargetRefType(String name) { + this(name, List.of()); + } + + public String getName() { + return this.name.replaceAll("\\.", "/"); + } + @Override public String toSignature() { - return "L" + this.name.replaceAll("\\.", "/") + ";"; + return "L" + getName() + ";"; } } 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 49ed4106..f3d6092f 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetType.java @@ -6,16 +6,16 @@ public sealed interface TargetType permits TargetExtendsWildcard, TargetFunNType, TargetGenericType, TargetRefType, TargetSuperWildcard { // Builtin types - TargetRefType Boolean = new TargetRefType("java.lang.Boolean", List.of()); - TargetRefType Char = new TargetRefType("java.lang.Character", List.of()); - TargetRefType Byte = new TargetRefType("java.lang.Byte", List.of()); - TargetRefType Short = new TargetRefType("java.lang.Short", List.of()); - TargetRefType Integer = new TargetRefType("java.lang.Integer", List.of()); - TargetRefType Long = new TargetRefType("java.lang.Long", List.of()); - TargetRefType Float = new TargetRefType("java.lang.Float", List.of()); - TargetRefType Double = new TargetRefType("java.lang.Double", List.of()); - TargetRefType String = new TargetRefType("java.lang.String", List.of()); - TargetRefType Object = new TargetRefType("java.lang.Object", List.of()); + TargetRefType Boolean = new TargetRefType("java.lang.Boolean"); + TargetRefType Char = new TargetRefType("java.lang.Character"); + TargetRefType Byte = new TargetRefType("java.lang.Byte"); + TargetRefType Short = new TargetRefType("java.lang.Short"); + TargetRefType Integer = new TargetRefType("java.lang.Integer"); + TargetRefType Long = new TargetRefType("java.lang.Long"); + TargetRefType Float = new TargetRefType("java.lang.Float"); + TargetRefType Double = new TargetRefType("java.lang.Double"); + TargetRefType String = new TargetRefType("java.lang.String"); + TargetRefType Object = new TargetRefType("java.lang.Object"); String toSignature(); } diff --git a/src/test/java/targetast/TestCodegen.java b/src/test/java/targetast/TestCodegen.java index dc5f03f8..0171032f 100644 --- a/src/test/java/targetast/TestCodegen.java +++ b/src/test/java/targetast/TestCodegen.java @@ -1,25 +1,193 @@ package targetast; import de.dhbwstuttgart.target.bytecode.Codegen; +import de.dhbwstuttgart.target.tree.MethodParameter; import de.dhbwstuttgart.target.tree.TargetClass; import de.dhbwstuttgart.target.tree.TargetMethod; -import de.dhbwstuttgart.target.tree.expression.TargetBlock; +import de.dhbwstuttgart.target.tree.expression.*; +import de.dhbwstuttgart.target.tree.type.TargetRefType; +import de.dhbwstuttgart.target.tree.type.TargetType; import org.junit.Test; +import static org.junit.Assert.*; import org.objectweb.asm.Opcodes; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; import java.util.List; + public class TestCodegen { - private static Class generateClass(TargetClass clazz) { + private static Class generateClass(TargetClass clazz) throws IOException { var codegen = new Codegen(clazz); - return new ByteArrayClassLoader().loadClass(codegen.generate()); + var bytes = codegen.generate(); + var path = Path.of(System.getProperty("user.dir"), "src/test/resources/target/"); + Files.createDirectories(path); + Files.write(path.resolve(clazz.qualifiedName() + ".class"), bytes, StandardOpenOption.CREATE); + return new ByteArrayClassLoader().loadClass(bytes); } @Test public void testEmptyClass() throws Exception { - var clazz = new TargetClass(Opcodes.ACC_PUBLIC, "Main"); - clazz.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "main", List.of(), new TargetBlock(List.of())); + var clazz = new TargetClass(Opcodes.ACC_PUBLIC, "Empty"); + clazz.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "main", List.of(), null, new TargetBlock(List.of())); generateClass(clazz).getDeclaredMethod("main").invoke(null); } + + @Test + public void testArithmetic() throws Exception { + var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "Arithmetic"); + + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "add", + List.of(new MethodParameter(TargetType.Integer, "a"), new MethodParameter(TargetType.Integer, "b")), + TargetType.Integer, + new TargetBlock(List.of(new TargetReturn( + new TargetBinaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "a"), new TargetLocalVar(TargetType.Integer, "b"))) + )) + ); + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "sub", + List.of(new MethodParameter(TargetType.Integer, "a"), new MethodParameter(TargetType.Integer, "b")), + TargetType.Integer, + new TargetBlock(List.of(new TargetReturn( + new TargetBinaryOp.Sub(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "a"), new TargetLocalVar(TargetType.Integer, "b"))) + )) + ); + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "div", + List.of(new MethodParameter(TargetType.Integer, "a"), new MethodParameter(TargetType.Integer, "b")), + TargetType.Integer, + new TargetBlock(List.of(new TargetReturn( + new TargetBinaryOp.Div(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "a"), new TargetLocalVar(TargetType.Integer, "b"))) + )) + ); + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "mul", + List.of(new MethodParameter(TargetType.Integer, "a"), new MethodParameter(TargetType.Integer, "b")), + TargetType.Integer, + new TargetBlock(List.of(new TargetReturn( + new TargetBinaryOp.Mul(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "a"), new TargetLocalVar(TargetType.Integer, "b"))) + )) + ); + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "rem", + List.of(new MethodParameter(TargetType.Integer, "a"), new MethodParameter(TargetType.Integer, "b")), + TargetType.Integer, + new TargetBlock(List.of(new TargetReturn( + new TargetBinaryOp.Rem(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "a"), new TargetLocalVar(TargetType.Integer, "b"))) + )) + ); + + + var clazz = generateClass(targetClass); + assertEquals(clazz.getDeclaredMethod("add", Integer.class, Integer.class).invoke(null, 10, 10), 20); + assertEquals(clazz.getDeclaredMethod("sub", Integer.class, Integer.class).invoke(null, 20, 10), 10); + assertEquals(clazz.getDeclaredMethod("div", Integer.class, Integer.class).invoke(null, 20, 10), 2); + assertEquals(clazz.getDeclaredMethod("mul", Integer.class, Integer.class).invoke(null, 20, 10), 200); + assertEquals(clazz.getDeclaredMethod("rem", Integer.class, Integer.class).invoke(null, 10, 3), 1); + } + + // When adding two numbers and the return type is Long it needs to convert both values to Long + @Test + public void testArithmeticConvert() throws Exception { + var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "ArithmeticConvert"); + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "add", List.of(), TargetType.Long, + new TargetBlock(List.of(new TargetReturn( + new TargetBinaryOp.Add(TargetType.Long, new TargetLiteral.CharLiteral((char)10), new TargetLiteral.LongLiteral((long)20)) + ))) + ); + var clazz = generateClass(targetClass); + assertEquals(clazz.getDeclaredMethod("add").invoke(null), (long)30); + } + + @Test + public void testMethodCall() throws Exception { + var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "HelloWorld"); + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "helloWorld", List.of(), null, + new TargetBlock(List.of(new TargetMethodCall(null, + new TargetFieldVar( + new TargetRefType("java.io.PrintStream"), true, + new TargetClassName(new TargetRefType("java.lang.System")), + "out" + ), + List.of(new TargetLiteral.StringLiteral("Hello World!")), + new TargetRefType("java.io.PrintStream"), + "println", + TargetMethod.getDescriptor(null, TargetType.String), + false + ))) + ); + + var clazz = generateClass(targetClass); + clazz.getDeclaredMethod("helloWorld").invoke(null); + } + + @Test + public void testIfStatement() throws Exception { + var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "IfStmt"); + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "ifStmt", + List.of(new MethodParameter(TargetType.Integer, "val")), + TargetType.Integer, + new TargetBlock(List.of(new TargetIf( + new TargetBinaryOp.Equal(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "val"), new TargetLiteral.IntLiteral(10)), + new TargetReturn(new TargetLiteral.IntLiteral(1)), + new TargetIf( + new TargetBinaryOp.Less(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "val"), new TargetLiteral.IntLiteral(5)), + new TargetReturn(new TargetLiteral.IntLiteral(2)), + new TargetReturn(new TargetLiteral.IntLiteral(3)) + ) + ))) + ); + var clazz = generateClass(targetClass); + var ifStmt = clazz.getDeclaredMethod("ifStmt", Integer.class); + assertEquals(ifStmt.invoke(null, 10), 1); + assertEquals(ifStmt.invoke(null, 3), 2); + assertEquals(ifStmt.invoke(null, 20), 3); + } + + @Test + public void testFor() throws Exception { + var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "For"); + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "forLoop", List.of(), TargetType.Integer, + new TargetBlock(List.of( + new TargetVarDecl(TargetType.Integer, "sum", new TargetLiteral.IntLiteral(0)), + new TargetFor( + new TargetVarDecl(TargetType.Integer, "i", new TargetLiteral.IntLiteral(0)), + new TargetBinaryOp.Less(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetLiteral.IntLiteral(10)), + new TargetAssign(TargetType.Integer, + new TargetLocalVar(TargetType.Integer, "i"), + new TargetBinaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetLiteral.IntLiteral(1))), + new TargetBlock(List.of( + new TargetAssign(TargetType.Integer, + new TargetLocalVar(TargetType.Integer, "sum"), + new TargetBinaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "sum"), new TargetLocalVar(TargetType.Integer, "i")) + ) + )) + ), + new TargetReturn(new TargetLocalVar(TargetType.Integer, "sum")) + )) + ); + var clazz = generateClass(targetClass); + assertEquals(clazz.getDeclaredMethod("forLoop").invoke(null), 45); + } + + @Test + public void testWhile() throws Exception { + var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "While"); + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "whileLoop", List.of(), TargetType.Integer, + new TargetBlock(List.of( + new TargetVarDecl(TargetType.Integer, "i", new TargetLiteral.IntLiteral(0)), + new TargetWhile( + new TargetBinaryOp.Less(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetLiteral.IntLiteral(10)), + new TargetBlock(List.of( + new TargetAssign(TargetType.Integer, + new TargetLocalVar(TargetType.Integer, "i"), + new TargetBinaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetLiteral.IntLiteral(1)) + ) + )) + ), + new TargetReturn(new TargetLocalVar(TargetType.Integer, "i")) + )) + ); + var clazz = generateClass(targetClass); + assertEquals(clazz.getDeclaredMethod("whileLoop").invoke(null), 10); + } } From 20f11a5bef9f68dd188329745d51d90bd481e2cc Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Tue, 24 May 2022 14:35:30 +0200 Subject: [PATCH 42/69] Changes --- .../target/bytecode/Codegen.java | 107 ++++++++++++----- .../target/tree/TargetClass.java | 6 +- .../target/tree/TargetConstructor.java | 6 +- .../target/tree/TargetField.java | 6 +- .../target/tree/TargetMethod.java | 2 +- .../tree/expression/TargetBinaryOp.java | 1 + .../tree/expression/TargetFieldVar.java | 3 +- .../expression/TargetLambdaExpression.java | 2 +- .../tree/expression/TargetMethodCall.java | 11 +- .../target/tree/expression/TargetNew.java | 4 + .../tree/type/TargetExtendsWildcard.java | 7 +- .../target/tree/type/TargetFunNType.java | 9 +- .../target/tree/type/TargetGenericType.java | 5 + .../target/tree/type/TargetSuperWildcard.java | 5 + .../target/tree/type/TargetType.java | 1 + .../java/targetast/ByteArrayClassLoader.java | 9 +- src/test/java/targetast/Fun1$$.java | 3 + src/test/java/targetast/TestCodegen.java | 108 +++++++++++++++++- src/test/resources/target/Test.java | 9 ++ 19 files changed, 256 insertions(+), 48 deletions(-) create mode 100644 src/test/java/targetast/Fun1$$.java create mode 100644 src/test/resources/target/Test.java diff --git a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java index ee5ed659..cbc35ad7 100755 --- a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java @@ -1,17 +1,18 @@ package de.dhbwstuttgart.target.bytecode; -import de.dhbwstuttgart.target.tree.TargetClass; -import de.dhbwstuttgart.target.tree.TargetConstructor; -import de.dhbwstuttgart.target.tree.TargetField; -import de.dhbwstuttgart.target.tree.TargetMethod; +import de.dhbwstuttgart.target.tree.*; 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.objectweb.asm.ClassWriter; -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.*; +import java.lang.invoke.CallSite; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; import java.util.HashMap; +import java.util.List; import java.util.Map; import static org.objectweb.asm.Opcodes.*; @@ -56,6 +57,7 @@ public class Codegen { private static class State { Scope scope = new Scope(null); int localCounter; + int lambdaCounter; MethodVisitor mv; State(MethodVisitor mv, int localCounter) { @@ -216,7 +218,8 @@ public class Codegen { else if (dest.equals(TargetType.Double)) mv.visitInsn(I2D); } else { - mv.visitTypeInsn(CHECKCAST, ((TargetRefType) dest).getName()); + mv.visitTypeInsn(CHECKCAST, dest.getName()); + unboxPrimitive(state, dest); } } @@ -515,6 +518,38 @@ public class Codegen { } private void generateLambdaExpression(State state, TargetLambdaExpression lambda) { + var mv = state.mv; + var name = "lambda$" + state.lambdaCounter; + var impl = new TargetMethod( + ACC_PRIVATE, new TargetRefType(clazz.qualifiedName()), name, + lambda.params(), lambda.returnType(), lambda.block() + ); + generateMethod(impl); + + var mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, + MethodType.class, MethodType.class, MethodHandle.class, MethodType.class); + + var bootstrap = new Handle(H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "metafactory", + mt.toMethodDescriptorString(), false); + var handle = new Handle( + H_INVOKEVIRTUAL, clazz.getName(), name, + impl.getDescriptor(), false + ); + + // TODO maybe make this a function? + var desugared = "("; + for (var param : lambda.params()) + desugared += "Ljava/lang/Object;"; + desugared += ")"; + if (lambda.returnType() != null) + desugared += "Ljava/lang/Object;"; + else desugared += "V"; + + mv.visitVarInsn(ALOAD, 0); + mv.visitInvokeDynamicInsn("apply", TargetMethod.getDescriptor(lambda.type(), new TargetRefType(clazz.qualifiedName())), + bootstrap, Type.getType(desugared), handle, Type.getType(impl.getDescriptor())); + + state.lambdaCounter++; } private void generate(State state, TargetExpression expr) { @@ -542,7 +577,7 @@ public class Codegen { convertTo(state, cast.expr().type(), cast.type()); break; case TargetInstanceOf instanceOf: - mv.visitTypeInsn(INSTANCEOF, ((TargetRefType) instanceOf.right()).getName()); + mv.visitTypeInsn(INSTANCEOF, instanceOf.right().getName()); break; case TargetLiteral literal: switch (literal) { @@ -595,13 +630,12 @@ public class Codegen { } case TargetFieldVar dot: { generate(state, dot.left()); - TargetRefType type = (TargetRefType) dot.type(); generate(state, assign.right()); boxPrimitive(state, assign.right().type()); if (dot.isStatic()) mv.visitInsn(DUP); else mv.visitInsn(DUP_X1); - mv.visitFieldInsn(dot.isStatic() ? PUTSTATIC : PUTFIELD, dot.right(), type.getName(), type.toSignature()); + mv.visitFieldInsn(dot.isStatic() ? PUTSTATIC : PUTFIELD, dot.owner().getName(), dot.right(), dot.type().toSignature()); break; } default: @@ -618,8 +652,7 @@ public class Codegen { case TargetFieldVar dot: { if (!dot.isStatic()) generate(state, dot.left()); - var type = (TargetRefType) dot.left().type(); - mv.visitFieldInsn(dot.isStatic() ? GETSTATIC : GETFIELD, type.getName(), dot.right(), dot.type().toSignature()); + mv.visitFieldInsn(dot.isStatic() ? GETSTATIC : GETFIELD, dot.left().type().getName(), dot.right(), dot.type().toSignature()); break; } case TargetFor _for: { @@ -685,7 +718,7 @@ public class Codegen { break; } case TargetSuper _super: { - // TODO + mv.visitVarInsn(ALOAD, 0); break; } case TargetMethodCall call: { @@ -694,12 +727,29 @@ public class Codegen { generate(state, e); boxPrimitive(state, e.type()); } - mv.visitMethodInsn(call.isStatic() ? INVOKESTATIC: INVOKEVIRTUAL, call.owner().getName(), call.name(), call.descriptor(), false); + if (call.expr() instanceof TargetThis) + mv.visitMethodInsn(INVOKESPECIAL, clazz.getName(), "", call.getDescriptor(), false); + else if (call.expr() instanceof TargetSuper) + mv.visitMethodInsn(INVOKESPECIAL, clazz.superType().getName(), "", call.getDescriptor(), false); + else mv.visitMethodInsn(call.isInterface() ? INVOKEINTERFACE : call.isStatic() ? INVOKESTATIC: INVOKEVIRTUAL, + call.owner().getName(), call.name(), call.getDescriptor(), call.isInterface()); + if (call.type() != null) + unboxPrimitive(state, call.type()); break; } case TargetLambdaExpression lambda: generateLambdaExpression(state, lambda); break; + case TargetNew _new: { + mv.visitTypeInsn(NEW, _new.type().getName()); + mv.visitInsn(DUP); + for (TargetExpression e : _new.params()) { + generate(state, e); + boxPrimitive(state, e.type()); + } + mv.visitMethodInsn(INVOKESPECIAL, _new.type().getName(), "", _new.getDescriptor(), false); + break; + } default: throw new CodeGenException("Unexpected value: " + expr); } @@ -709,12 +759,26 @@ public class Codegen { cw.visitField(field.access(), field.name(), field.getDescriptor(), null, null); } + private boolean hasThisOrSuperCall(TargetBlock block) { + if (block.statements().size() == 0) return false; + TargetExpression first = block.statements().get(0); + if (!(first instanceof TargetMethodCall)) return false; + var methodCall = (TargetMethodCall) first; + if (methodCall.expr() instanceof TargetThis || methodCall.expr() instanceof TargetSuper) + return true; + return false; + } + private void generateConstructor(TargetConstructor constructor) { MethodVisitor mv = cw.visitMethod(constructor.access(), "", constructor.getDescriptor(), null, null); mv.visitCode(); var state = new State(mv, 1); for (var param: constructor.parameters()) state.createVariable(param.name(), param.type()); + if (!hasThisOrSuperCall(constructor.block())) { + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, clazz.superType().getName(), "", "()V", false); + } generate(state, constructor.block()); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); @@ -736,20 +800,11 @@ public class Codegen { public byte[] generate() { cw.visit(V1_8, clazz.modifiers(), clazz.qualifiedName(), - null, ((TargetRefType) clazz.superType()).getName(), + null, clazz.superType().getName(), clazz.implementingInterfaces().stream().map(TargetType::toSignature).toArray(String[]::new) ); clazz.fields().forEach(this::generateField); - if (clazz.constructors().size() == 0) { - var mv = cw.visitMethod(ACC_PROTECTED, "", "()V", null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, ((TargetRefType) clazz.superType()).getName(), "", "()V", false); - mv.visitInsn(RETURN); - mv.visitMaxs(0, 0); - mv.visitEnd(); - } - else clazz.constructors().forEach(this::generateConstructor); + clazz.constructors().forEach(this::generateConstructor); clazz.methods().forEach(this::generateMethod); cw.visitEnd(); diff --git a/src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java index 63010136..e7f990c0 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java @@ -17,6 +17,10 @@ public record TargetClass(int modifiers, String qualifiedName, TargetType superT this(modifiers, qualifiedName, TargetType.Object, implementingInterfaces, new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); } + public String getName() { + return qualifiedName.replaceAll("\\.", "/"); + } + 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)); } @@ -25,7 +29,7 @@ public record TargetClass(int modifiers, String qualifiedName, TargetType superT this.constructors.add(new TargetConstructor(access, new TargetRefType(this.qualifiedName, List.of()), paramterTypes, block)); } - public void addField(int access, TargetType type, String name) { + public void addField(int access, TargetRefType type, String name) { this.fields.add(new TargetField(access, new TargetRefType(this.qualifiedName, List.of()), 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 3a242c1e..3c353262 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java @@ -2,14 +2,14 @@ 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; -public record TargetConstructor(int access, TargetRefType owner, List parameters, TargetBlock block) { +public record TargetConstructor(int access, TargetType owner, List parameters, TargetBlock block) { public String getDescriptor() { - // TODO - return null; + 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 2c183dcb..489192a2 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/TargetField.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetField.java @@ -1,13 +1,11 @@ package de.dhbwstuttgart.target.tree; -import de.dhbwstuttgart.target.tree.type.TargetRefType; import de.dhbwstuttgart.target.tree.type.TargetType; import org.objectweb.asm.Opcodes; -public record TargetField(int access, TargetRefType owner, TargetType type, String name) { +public record TargetField(int access, TargetType owner, TargetType type, String name) { public String getDescriptor() { - // TODO - return null; + return type.toSignature(); } public boolean isStatic() { diff --git a/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java index bfd8f3b4..52ea71a0 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java @@ -8,7 +8,7 @@ import org.objectweb.asm.Opcodes; import java.util.List; import java.util.stream.Collectors; -public record TargetMethod(int access, TargetRefType owner, String name, List parameters, TargetType returnType, TargetBlock block) { +public record TargetMethod(int access, TargetType owner, String name, 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/expression/TargetBinaryOp.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBinaryOp.java index 814a4d67..12d56d5b 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBinaryOp.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBinaryOp.java @@ -35,6 +35,7 @@ public sealed interface TargetBinaryOp extends TargetExpression { } // Comparison + // exprType is the type that both arguments get converted to before comparison record Equal(TargetType exprType, TargetExpression left, TargetExpression right) implements TargetRelationalOp {} record Greater(TargetType exprType, TargetExpression left, TargetExpression right) implements TargetRelationalOp {} record GreaterOrEqual(TargetType exprType, TargetExpression left, TargetExpression right) implements TargetRelationalOp {} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFieldVar.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFieldVar.java index 5d41b1b4..0a72118e 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFieldVar.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFieldVar.java @@ -1,6 +1,7 @@ package de.dhbwstuttgart.target.tree.expression; +import de.dhbwstuttgart.target.tree.type.TargetRefType; import de.dhbwstuttgart.target.tree.type.TargetType; -public record TargetFieldVar(TargetType type, boolean isStatic, TargetExpression left, String right) implements TargetExpression { +public record TargetFieldVar(TargetType type, TargetRefType owner, boolean isStatic, TargetExpression left, String right) implements TargetExpression { } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLambdaExpression.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLambdaExpression.java index 13da5b9c..c0a5a811 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLambdaExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLambdaExpression.java @@ -5,5 +5,5 @@ import de.dhbwstuttgart.target.tree.type.TargetType; import java.util.List; -public record TargetLambdaExpression(TargetType type, List params, TargetExpression block) implements TargetExpression { +public record TargetLambdaExpression(TargetType type, List params, TargetType returnType, TargetBlock block) implements TargetExpression { } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetMethodCall.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetMethodCall.java index 132ec11b..12325962 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetMethodCall.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetMethodCall.java @@ -1,10 +1,19 @@ package de.dhbwstuttgart.target.tree.expression; +import de.dhbwstuttgart.target.tree.MethodParameter; import de.dhbwstuttgart.target.tree.TargetMethod; import de.dhbwstuttgart.target.tree.type.TargetRefType; import de.dhbwstuttgart.target.tree.type.TargetType; import java.util.List; -public record TargetMethodCall(TargetType type, TargetExpression expr, List args, TargetRefType owner, String name, String descriptor, boolean isStatic) implements TargetStatementExpression { +public record TargetMethodCall(TargetType type, List parameterTypes, TargetExpression expr, List args, TargetType owner, String name, boolean isStatic, boolean isInterface) implements TargetStatementExpression { + public TargetMethodCall(TargetType type, TargetExpression expr, List args, TargetType owner, String name, boolean isStatic, boolean isInterface) { + this(type, args.stream().map(TargetExpression::type).toList(), expr, args, owner, name, isStatic, isInterface); + } + + + public String getDescriptor() { + return TargetMethod.getDescriptor(type, parameterTypes.toArray(TargetType[]::new)); + } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetNew.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetNew.java index 30fb295c..e9d4ce8c 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetNew.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetNew.java @@ -1,8 +1,12 @@ package de.dhbwstuttgart.target.tree.expression; +import de.dhbwstuttgart.target.tree.TargetMethod; import de.dhbwstuttgart.target.tree.type.TargetType; import java.util.List; public record TargetNew(TargetType type, List params) implements TargetStatementExpression { + public String getDescriptor() { + return TargetMethod.getDescriptor(null, params.stream().map(TargetExpression::type).toArray(TargetType[]::new)); + } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java index 4dc033de..c9d70f19 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java @@ -1,11 +1,14 @@ package de.dhbwstuttgart.target.tree.type; -import java.util.List; - public record TargetExtendsWildcard(TargetType innerType) implements TargetType { @Override public String toSignature() { return null; } + + @Override + public String getName() { + return null; + } } 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 76394836..cfdf2b3c 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetFunNType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetFunNType.java @@ -2,9 +2,14 @@ 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 TargetType { + @Override + public String getName() { + return "Fun" + N + "$$"; + } + @Override public String toSignature() { - return "Fun$$" + N; + return "L" + getName() + ";"; } } 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 12269632..ab2e3c2b 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetGenericType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetGenericType.java @@ -5,4 +5,9 @@ public record TargetGenericType(String name) implements TargetType { public String toSignature() { return null; } + + @Override + public java.lang.String getName() { + return null; + } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java index 1414daab..fee11375 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java @@ -5,4 +5,9 @@ public record TargetSuperWildcard(TargetType innerType) implements TargetType { public String toSignature() { return null; } + + @Override + public String getName() { + return null; + } } 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 f3d6092f..5d12cd34 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetType.java @@ -18,4 +18,5 @@ public sealed interface TargetType TargetRefType Object = new TargetRefType("java.lang.Object"); String toSignature(); + String getName(); } diff --git a/src/test/java/targetast/ByteArrayClassLoader.java b/src/test/java/targetast/ByteArrayClassLoader.java index 227b7094..66937cf4 100644 --- a/src/test/java/targetast/ByteArrayClassLoader.java +++ b/src/test/java/targetast/ByteArrayClassLoader.java @@ -1,9 +1,16 @@ package targetast; -import java.util.Map; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; public class ByteArrayClassLoader extends ClassLoader { public Class loadClass(byte[] code) { return this.defineClass(null, code, 0, code.length); } + + public Class loadClass(Path path) throws IOException { + var code = Files.readAllBytes(path); + return this.defineClass(null, code, 0, code.length); + } } diff --git a/src/test/java/targetast/Fun1$$.java b/src/test/java/targetast/Fun1$$.java new file mode 100644 index 00000000..882112f2 --- /dev/null +++ b/src/test/java/targetast/Fun1$$.java @@ -0,0 +1,3 @@ +public interface Fun1$$ { + public R apply(T t); +} diff --git a/src/test/java/targetast/TestCodegen.java b/src/test/java/targetast/TestCodegen.java index 0171032f..1806fb33 100644 --- a/src/test/java/targetast/TestCodegen.java +++ b/src/test/java/targetast/TestCodegen.java @@ -3,7 +3,6 @@ package targetast; import de.dhbwstuttgart.target.bytecode.Codegen; import de.dhbwstuttgart.target.tree.MethodParameter; import de.dhbwstuttgart.target.tree.TargetClass; -import de.dhbwstuttgart.target.tree.TargetMethod; import de.dhbwstuttgart.target.tree.expression.*; import de.dhbwstuttgart.target.tree.type.TargetRefType; import de.dhbwstuttgart.target.tree.type.TargetType; @@ -20,13 +19,15 @@ import java.util.List; public class TestCodegen { + private static ByteArrayClassLoader loader = new ByteArrayClassLoader(); + private 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/"); Files.createDirectories(path); Files.write(path.resolve(clazz.qualifiedName() + ".class"), bytes, StandardOpenOption.CREATE); - return new ByteArrayClassLoader().loadClass(bytes); + return loader.loadClass(bytes); } @Test @@ -85,6 +86,34 @@ public class TestCodegen { assertEquals(clazz.getDeclaredMethod("rem", Integer.class, Integer.class).invoke(null, 10, 3), 1); } + @Test + public void testConditional() throws Exception { + var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "Conditional"); + + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "and", + List.of(new MethodParameter(TargetType.Boolean, "a"), new MethodParameter(TargetType.Boolean, "b")), + TargetType.Boolean, + new TargetBlock(List.of(new TargetReturn( + new TargetBinaryOp.And(TargetType.Boolean, new TargetLocalVar(TargetType.Boolean, "a"), new TargetLocalVar(TargetType.Boolean, "b"))) + )) + ); + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "or", + List.of(new MethodParameter(TargetType.Boolean, "a"), new MethodParameter(TargetType.Boolean, "b")), + TargetType.Boolean, + new TargetBlock(List.of(new TargetReturn( + new TargetBinaryOp.Or(TargetType.Boolean, new TargetLocalVar(TargetType.Boolean, "a"), new TargetLocalVar(TargetType.Boolean, "b"))) + )) + ); + + var clazz = generateClass(targetClass); + var and = clazz.getDeclaredMethod("and", Boolean.class, Boolean.class); + var or = clazz.getDeclaredMethod("or", Boolean.class, Boolean.class); + assertEquals(and.invoke(null, true, false), false); + assertEquals(and.invoke(null, true, true), true); + assertEquals(or.invoke(null, false, false), false); + assertEquals(or.invoke(null, true, false), true); + } + // When adding two numbers and the return type is Long it needs to convert both values to Long @Test public void testArithmeticConvert() throws Exception { @@ -104,15 +133,16 @@ public class TestCodegen { targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "helloWorld", List.of(), null, new TargetBlock(List.of(new TargetMethodCall(null, new TargetFieldVar( - new TargetRefType("java.io.PrintStream"), true, + new TargetRefType("java.io.PrintStream"), + new TargetRefType("java.lang.System"), + true, new TargetClassName(new TargetRefType("java.lang.System")), "out" ), List.of(new TargetLiteral.StringLiteral("Hello World!")), new TargetRefType("java.io.PrintStream"), "println", - TargetMethod.getDescriptor(null, TargetType.String), - false + false, false ))) ); @@ -190,4 +220,72 @@ public class TestCodegen { var clazz = generateClass(targetClass); assertEquals(clazz.getDeclaredMethod("whileLoop").invoke(null), 10); } + + @Test + public void testNew() throws Exception { + var pointType = new TargetRefType("Point"); + var pointTarget = new TargetClass(Opcodes.ACC_PUBLIC, "Point"); + pointTarget.addField(Opcodes.ACC_PUBLIC, TargetType.Integer, "x"); + pointTarget.addField(Opcodes.ACC_PUBLIC, TargetType.Integer, "y"); + pointTarget.addConstructor(Opcodes.ACC_PUBLIC, + List.of(new MethodParameter(TargetType.Integer, "x"), new MethodParameter(TargetType.Integer, "y")), + new TargetBlock(List.of( + new TargetAssign(TargetType.Integer, + new TargetFieldVar(TargetType.Integer, pointType, false, new TargetThis(pointType), "x"), + new TargetLocalVar(TargetType.Integer, "x") + ), + new TargetAssign(TargetType.Integer, + new TargetFieldVar(TargetType.Integer, pointType, false, new TargetThis(pointType), "y"), + new TargetLocalVar(TargetType.Integer, "y") + ) + )) + ); + + var mainTarget = new TargetClass(Opcodes.ACC_PUBLIC, "New"); + mainTarget.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "makePoint", + List.of(new MethodParameter(TargetType.Integer, "x"), new MethodParameter(TargetType.Integer, "y")), pointType, + new TargetBlock(List.of( + new TargetReturn(new TargetNew(pointType, List.of( + new TargetLocalVar(TargetType.Integer, "x"), + new TargetLocalVar(TargetType.Integer, "y") + ))) + )) + ); + + var pointClass = generateClass(pointTarget); + var mainClass = generateClass(mainTarget); + + var point = mainClass.getDeclaredMethod("makePoint", Integer.class, Integer.class).invoke(null, 10, 20); + assertEquals(point.getClass().getDeclaredField("x").get(point), 10); + assertEquals(point.getClass().getDeclaredField("y").get(point), 20); + } + + @Test + public void testLambda() throws Exception { + var fun = loader.loadClass(Path.of(System.getProperty("user.dir"), "src/test/java/targetast/Fun1$$.class")); + var interfaceType = new TargetRefType("Fun1$$"); + + var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "Lambda"); + targetClass.addConstructor(Opcodes.ACC_PUBLIC, List.of(), new TargetBlock(List.of())); + targetClass.addMethod(Opcodes.ACC_PUBLIC, "lambda", List.of(), TargetType.Integer, + new TargetBlock(List.of( + new TargetVarDecl(interfaceType, "by2", + new TargetLambdaExpression(interfaceType, List.of(new MethodParameter(TargetType.Integer, "num")), TargetType.Integer, + new TargetBlock(List.of( + new TargetReturn(new TargetBinaryOp.Mul(TargetType.Integer, + new TargetLocalVar(TargetType.Integer, "num"), + new TargetLiteral.IntLiteral(2) + )) + ) + )) + ), + new TargetReturn(new TargetCast(TargetType.Integer, new TargetMethodCall(TargetType.Object, List.of(TargetType.Object), new TargetLocalVar(interfaceType, "by2"), List.of( + new TargetLiteral.IntLiteral(10) + ), interfaceType, "apply", false, true))) + )) + ); + var clazz = generateClass(targetClass); + var instance = clazz.getConstructor().newInstance(); + assertEquals(clazz.getDeclaredMethod("lambda").invoke(instance), 20); + } } diff --git a/src/test/resources/target/Test.java b/src/test/resources/target/Test.java new file mode 100644 index 00000000..f7e1a0bc --- /dev/null +++ b/src/test/resources/target/Test.java @@ -0,0 +1,9 @@ +public class Test { + public void lambda() { + Interface mul2 = (Integer a) -> a * 2; + } +} + +interface Interface { + R apply(T t); +} \ No newline at end of file From 1ef3f22c18659c7b5a104aaa8824854f6623c987 Mon Sep 17 00:00:00 2001 From: JanUlrich Date: Tue, 24 May 2022 15:42:41 +0200 Subject: [PATCH 43/69] Add AST To Target AST emptyClass testcase --- .../target/generate/ASTToTargetAST.java | 6 ++++ .../java/targetast/ASTToTypedTargetAST.java | 32 +++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 src/test/java/targetast/ASTToTypedTargetAST.java diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index 709a3350..23f04d2b 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -1,5 +1,6 @@ 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; @@ -9,6 +10,7 @@ import de.dhbwstuttgart.syntaxtree.type.*; import de.dhbwstuttgart.target.tree.*; import de.dhbwstuttgart.target.tree.expression.TargetBlock; import de.dhbwstuttgart.target.tree.type.*; +import de.dhbwstuttgart.typeinference.result.ResultSet; import java.util.ArrayList; import java.util.List; @@ -17,6 +19,10 @@ import java.util.stream.Collectors; public class ASTToTargetAST { + public TargetClass convert(ClassOrInterface input, ResultSet resultSet){ + throw new NotImplementedException(); + } + public TargetClass convert(ClassOrInterface input, Map sigma){ List targetConstructors = new ArrayList<>(); //TODO constructor conversion -> also reduce syntactic sugar diff --git a/src/test/java/targetast/ASTToTypedTargetAST.java b/src/test/java/targetast/ASTToTypedTargetAST.java new file mode 100644 index 00000000..e4c93d1a --- /dev/null +++ b/src/test/java/targetast/ASTToTypedTargetAST.java @@ -0,0 +1,32 @@ +package targetast; + +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import de.dhbwstuttgart.syntaxtree.*; +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.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; + +public class ASTToTypedTargetAST { + + @Test + public void emptyClass(){ + 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().convert(emptyClass, emptyResultSet); + assert emptyTargetClass.getName().equals("EmptyClass"); + assert emptyTargetClass.methods().size() == 0; + assert emptyTargetClass.fields().size() == 0; + } + +} From 372182aa8bbaba3a5321e87325eeb0b928ab8145 Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Sun, 29 May 2022 20:06:08 +0200 Subject: [PATCH 44/69] Convert the AST --- .../parser/antlr/Java8BaseListener.java | 2 +- .../parser/antlr/Java8Lexer.java | 137 +-- .../parser/antlr/Java8Listener.java | 2 +- .../parser/antlr/Java8Parser.java | 777 +++++++++++++++--- .../target/bytecode/Codegen.java | 9 + .../target/generate/ASTToTargetAST.java | 52 +- .../generate/StatementToTargetExpression.java | 146 +++- .../tree/expression/TargetFieldVar.java | 2 +- .../tree/expression/TargetInstanceOf.java | 2 +- .../target/tree/expression/TargetUnaryOp.java | 1 + .../java/targetast/ASTToTypedTargetAST.java | 2 +- 11 files changed, 883 insertions(+), 249 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/parser/antlr/Java8BaseListener.java b/src/main/java/de/dhbwstuttgart/parser/antlr/Java8BaseListener.java index 1c94febc..644786ac 100644 --- a/src/main/java/de/dhbwstuttgart/parser/antlr/Java8BaseListener.java +++ b/src/main/java/de/dhbwstuttgart/parser/antlr/Java8BaseListener.java @@ -1,4 +1,4 @@ -// Generated from Java8.g4 by ANTLR 4.7 +// Generated from Java8.g4 by ANTLR 4.8 package de.dhbwstuttgart.parser.antlr; import org.antlr.v4.runtime.ParserRuleContext; diff --git a/src/main/java/de/dhbwstuttgart/parser/antlr/Java8Lexer.java b/src/main/java/de/dhbwstuttgart/parser/antlr/Java8Lexer.java index 9c2e22c4..c346153e 100644 --- a/src/main/java/de/dhbwstuttgart/parser/antlr/Java8Lexer.java +++ b/src/main/java/de/dhbwstuttgart/parser/antlr/Java8Lexer.java @@ -1,4 +1,4 @@ -// Generated from Java8.g4 by ANTLR 4.7 +// Generated from Java8.g4 by ANTLR 4.8 package de.dhbwstuttgart.parser.antlr; import org.antlr.v4.runtime.Lexer; import org.antlr.v4.runtime.CharStream; @@ -11,7 +11,7 @@ import org.antlr.v4.runtime.misc.*; @SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) public class Java8Lexer extends Lexer { - static { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION); } + static { RuntimeMetaData.checkVersion("4.8", RuntimeMetaData.VERSION); } protected static final DFA[] _decisionToDFA; protected static final PredictionContextCache _sharedContextCache = @@ -42,68 +42,79 @@ public class Java8Lexer extends Lexer { "DEFAULT_MODE" }; - public static final String[] ruleNames = { - "T__0", "ABSTRACT", "ASSERT", "BOOLEAN", "BREAK", "BYTE", "CASE", "CATCH", - "CHAR", "CLASS", "CONST", "CONTINUE", "DEFAULT", "DO", "DOUBLE", "ELSE", - "ENUM", "EXTENDS", "FINAL", "FINALLY", "FLOAT", "FOR", "IF", "GOTO", "IMPLEMENTS", - "IMPORT", "INSTANCEOF", "INT", "INTERFACE", "LONG", "NATIVE", "NEW", "PACKAGE", - "PRIVATE", "PROTECTED", "PUBLIC", "RETURN", "SHORT", "STATIC", "STRICTFP", - "SUPER", "SWITCH", "SYNCHRONIZED", "THIS", "THROW", "THROWS", "TRANSIENT", - "TRY", "VOID", "VOLATILE", "WHILE", "IntegerLiteral", "DecimalIntegerLiteral", - "HexIntegerLiteral", "OctalIntegerLiteral", "BinaryIntegerLiteral", "IntegerTypeSuffix", - "DecimalNumeral", "Digits", "Digit", "NonZeroDigit", "DigitsAndUnderscores", - "DigitOrUnderscore", "Underscores", "HexNumeral", "HexDigits", "HexDigit", - "HexDigitsAndUnderscores", "HexDigitOrUnderscore", "OctalNumeral", "OctalDigits", - "OctalDigit", "OctalDigitsAndUnderscores", "OctalDigitOrUnderscore", "BinaryNumeral", - "BinaryDigits", "BinaryDigit", "BinaryDigitsAndUnderscores", "BinaryDigitOrUnderscore", - "FloatingPointLiteral", "DecimalFloatingPointLiteral", "ExponentPart", - "ExponentIndicator", "SignedInteger", "Sign", "FloatTypeSuffix", "HexadecimalFloatingPointLiteral", - "HexSignificand", "BinaryExponent", "BinaryExponentIndicator", "BooleanLiteral", - "CharacterLiteral", "SingleCharacter", "StringLiteral", "StringCharacters", - "StringCharacter", "EscapeSequence", "OctalEscape", "ZeroToThree", "UnicodeEscape", - "NullLiteral", "LPAREN", "RPAREN", "LBRACE", "RBRACE", "LBRACK", "RBRACK", - "SEMI", "COMMA", "DOT", "ASSIGN", "GT", "LT", "BANG", "TILDE", "QUESTION", - "COLON", "EQUAL", "LE", "GE", "NOTEQUAL", "AND", "OR", "INC", "DEC", "ADD", - "SUB", "MUL", "DIV", "BITAND", "BITOR", "CARET", "MOD", "ARROW", "COLONCOLON", - "ADD_ASSIGN", "SUB_ASSIGN", "MUL_ASSIGN", "DIV_ASSIGN", "AND_ASSIGN", - "OR_ASSIGN", "XOR_ASSIGN", "MOD_ASSIGN", "LSHIFT_ASSIGN", "RSHIFT_ASSIGN", - "URSHIFT_ASSIGN", "Identifier", "JavaLetter", "JavaLetterOrDigit", "AT", - "ELLIPSIS", "WS", "COMMENT", "LINE_COMMENT" - }; + private static String[] makeRuleNames() { + return new String[] { + "T__0", "ABSTRACT", "ASSERT", "BOOLEAN", "BREAK", "BYTE", "CASE", "CATCH", + "CHAR", "CLASS", "CONST", "CONTINUE", "DEFAULT", "DO", "DOUBLE", "ELSE", + "ENUM", "EXTENDS", "FINAL", "FINALLY", "FLOAT", "FOR", "IF", "GOTO", + "IMPLEMENTS", "IMPORT", "INSTANCEOF", "INT", "INTERFACE", "LONG", "NATIVE", + "NEW", "PACKAGE", "PRIVATE", "PROTECTED", "PUBLIC", "RETURN", "SHORT", + "STATIC", "STRICTFP", "SUPER", "SWITCH", "SYNCHRONIZED", "THIS", "THROW", + "THROWS", "TRANSIENT", "TRY", "VOID", "VOLATILE", "WHILE", "IntegerLiteral", + "DecimalIntegerLiteral", "HexIntegerLiteral", "OctalIntegerLiteral", + "BinaryIntegerLiteral", "IntegerTypeSuffix", "DecimalNumeral", "Digits", + "Digit", "NonZeroDigit", "DigitsAndUnderscores", "DigitOrUnderscore", + "Underscores", "HexNumeral", "HexDigits", "HexDigit", "HexDigitsAndUnderscores", + "HexDigitOrUnderscore", "OctalNumeral", "OctalDigits", "OctalDigit", + "OctalDigitsAndUnderscores", "OctalDigitOrUnderscore", "BinaryNumeral", + "BinaryDigits", "BinaryDigit", "BinaryDigitsAndUnderscores", "BinaryDigitOrUnderscore", + "FloatingPointLiteral", "DecimalFloatingPointLiteral", "ExponentPart", + "ExponentIndicator", "SignedInteger", "Sign", "FloatTypeSuffix", "HexadecimalFloatingPointLiteral", + "HexSignificand", "BinaryExponent", "BinaryExponentIndicator", "BooleanLiteral", + "CharacterLiteral", "SingleCharacter", "StringLiteral", "StringCharacters", + "StringCharacter", "EscapeSequence", "OctalEscape", "ZeroToThree", "UnicodeEscape", + "NullLiteral", "LPAREN", "RPAREN", "LBRACE", "RBRACE", "LBRACK", "RBRACK", + "SEMI", "COMMA", "DOT", "ASSIGN", "GT", "LT", "BANG", "TILDE", "QUESTION", + "COLON", "EQUAL", "LE", "GE", "NOTEQUAL", "AND", "OR", "INC", "DEC", + "ADD", "SUB", "MUL", "DIV", "BITAND", "BITOR", "CARET", "MOD", "ARROW", + "COLONCOLON", "ADD_ASSIGN", "SUB_ASSIGN", "MUL_ASSIGN", "DIV_ASSIGN", + "AND_ASSIGN", "OR_ASSIGN", "XOR_ASSIGN", "MOD_ASSIGN", "LSHIFT_ASSIGN", + "RSHIFT_ASSIGN", "URSHIFT_ASSIGN", "Identifier", "JavaLetter", "JavaLetterOrDigit", + "AT", "ELLIPSIS", "WS", "COMMENT", "LINE_COMMENT" + }; + } + public static final String[] ruleNames = makeRuleNames(); - private static final String[] _LITERAL_NAMES = { - null, "'var'", "'abstract'", "'assert'", "'boolean'", "'break'", "'byte'", - "'case'", "'catch'", "'char'", "'class'", "'const'", "'continue'", "'default'", - "'do'", "'double'", "'else'", "'enum'", "'extends'", "'final'", "'finally'", - "'float'", "'for'", "'if'", "'goto'", "'implements'", "'import'", "'instanceof'", - "'int'", "'interface'", "'long'", "'native'", "'new'", "'package'", "'private'", - "'protected'", "'public'", "'return'", "'short'", "'static'", "'strictfp'", - "'super'", "'switch'", "'synchronized'", "'this'", "'throw'", "'throws'", - "'transient'", "'try'", "'void'", "'volatile'", "'while'", null, null, - null, null, null, "'null'", "'('", "')'", "'{'", "'}'", "'['", "']'", - "';'", "','", "'.'", "'='", "'>'", "'<'", "'!'", "'~'", "'?'", "':'", - "'=='", "'<='", "'>='", "'!='", "'&&'", "'||'", "'++'", "'--'", "'+'", - "'-'", "'*'", "'/'", "'&'", "'|'", "'^'", "'%'", "'->'", "'::'", "'+='", - "'-='", "'*='", "'/='", "'&='", "'|='", "'^='", "'%='", "'<<='", "'>>='", - "'>>>='", null, "'@'", "'...'" - }; - private static final String[] _SYMBOLIC_NAMES = { - null, null, "ABSTRACT", "ASSERT", "BOOLEAN", "BREAK", "BYTE", "CASE", - "CATCH", "CHAR", "CLASS", "CONST", "CONTINUE", "DEFAULT", "DO", "DOUBLE", - "ELSE", "ENUM", "EXTENDS", "FINAL", "FINALLY", "FLOAT", "FOR", "IF", "GOTO", - "IMPLEMENTS", "IMPORT", "INSTANCEOF", "INT", "INTERFACE", "LONG", "NATIVE", - "NEW", "PACKAGE", "PRIVATE", "PROTECTED", "PUBLIC", "RETURN", "SHORT", - "STATIC", "STRICTFP", "SUPER", "SWITCH", "SYNCHRONIZED", "THIS", "THROW", - "THROWS", "TRANSIENT", "TRY", "VOID", "VOLATILE", "WHILE", "IntegerLiteral", - "FloatingPointLiteral", "BooleanLiteral", "CharacterLiteral", "StringLiteral", - "NullLiteral", "LPAREN", "RPAREN", "LBRACE", "RBRACE", "LBRACK", "RBRACK", - "SEMI", "COMMA", "DOT", "ASSIGN", "GT", "LT", "BANG", "TILDE", "QUESTION", - "COLON", "EQUAL", "LE", "GE", "NOTEQUAL", "AND", "OR", "INC", "DEC", "ADD", - "SUB", "MUL", "DIV", "BITAND", "BITOR", "CARET", "MOD", "ARROW", "COLONCOLON", - "ADD_ASSIGN", "SUB_ASSIGN", "MUL_ASSIGN", "DIV_ASSIGN", "AND_ASSIGN", - "OR_ASSIGN", "XOR_ASSIGN", "MOD_ASSIGN", "LSHIFT_ASSIGN", "RSHIFT_ASSIGN", - "URSHIFT_ASSIGN", "Identifier", "AT", "ELLIPSIS", "WS", "COMMENT", "LINE_COMMENT" - }; + private static String[] makeLiteralNames() { + return new String[] { + null, "'var'", "'abstract'", "'assert'", "'boolean'", "'break'", "'byte'", + "'case'", "'catch'", "'char'", "'class'", "'const'", "'continue'", "'default'", + "'do'", "'double'", "'else'", "'enum'", "'extends'", "'final'", "'finally'", + "'float'", "'for'", "'if'", "'goto'", "'implements'", "'import'", "'instanceof'", + "'int'", "'interface'", "'long'", "'native'", "'new'", "'package'", "'private'", + "'protected'", "'public'", "'return'", "'short'", "'static'", "'strictfp'", + "'super'", "'switch'", "'synchronized'", "'this'", "'throw'", "'throws'", + "'transient'", "'try'", "'void'", "'volatile'", "'while'", null, null, + null, null, null, "'null'", "'('", "')'", "'{'", "'}'", "'['", "']'", + "';'", "','", "'.'", "'='", "'>'", "'<'", "'!'", "'~'", "'?'", "':'", + "'=='", "'<='", "'>='", "'!='", "'&&'", "'||'", "'++'", "'--'", "'+'", + "'-'", "'*'", "'/'", "'&'", "'|'", "'^'", "'%'", "'->'", "'::'", "'+='", + "'-='", "'*='", "'/='", "'&='", "'|='", "'^='", "'%='", "'<<='", "'>>='", + "'>>>='", null, "'@'", "'...'" + }; + } + private static final String[] _LITERAL_NAMES = makeLiteralNames(); + private static String[] makeSymbolicNames() { + return new String[] { + null, null, "ABSTRACT", "ASSERT", "BOOLEAN", "BREAK", "BYTE", "CASE", + "CATCH", "CHAR", "CLASS", "CONST", "CONTINUE", "DEFAULT", "DO", "DOUBLE", + "ELSE", "ENUM", "EXTENDS", "FINAL", "FINALLY", "FLOAT", "FOR", "IF", + "GOTO", "IMPLEMENTS", "IMPORT", "INSTANCEOF", "INT", "INTERFACE", "LONG", + "NATIVE", "NEW", "PACKAGE", "PRIVATE", "PROTECTED", "PUBLIC", "RETURN", + "SHORT", "STATIC", "STRICTFP", "SUPER", "SWITCH", "SYNCHRONIZED", "THIS", + "THROW", "THROWS", "TRANSIENT", "TRY", "VOID", "VOLATILE", "WHILE", "IntegerLiteral", + "FloatingPointLiteral", "BooleanLiteral", "CharacterLiteral", "StringLiteral", + "NullLiteral", "LPAREN", "RPAREN", "LBRACE", "RBRACE", "LBRACK", "RBRACK", + "SEMI", "COMMA", "DOT", "ASSIGN", "GT", "LT", "BANG", "TILDE", "QUESTION", + "COLON", "EQUAL", "LE", "GE", "NOTEQUAL", "AND", "OR", "INC", "DEC", + "ADD", "SUB", "MUL", "DIV", "BITAND", "BITOR", "CARET", "MOD", "ARROW", + "COLONCOLON", "ADD_ASSIGN", "SUB_ASSIGN", "MUL_ASSIGN", "DIV_ASSIGN", + "AND_ASSIGN", "OR_ASSIGN", "XOR_ASSIGN", "MOD_ASSIGN", "LSHIFT_ASSIGN", + "RSHIFT_ASSIGN", "URSHIFT_ASSIGN", "Identifier", "AT", "ELLIPSIS", "WS", + "COMMENT", "LINE_COMMENT" + }; + } + private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames(); public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); /** diff --git a/src/main/java/de/dhbwstuttgart/parser/antlr/Java8Listener.java b/src/main/java/de/dhbwstuttgart/parser/antlr/Java8Listener.java index a875c96f..88b4f7e7 100644 --- a/src/main/java/de/dhbwstuttgart/parser/antlr/Java8Listener.java +++ b/src/main/java/de/dhbwstuttgart/parser/antlr/Java8Listener.java @@ -1,4 +1,4 @@ -// Generated from Java8.g4 by ANTLR 4.7 +// Generated from Java8.g4 by ANTLR 4.8 package de.dhbwstuttgart.parser.antlr; import org.antlr.v4.runtime.tree.ParseTreeListener; diff --git a/src/main/java/de/dhbwstuttgart/parser/antlr/Java8Parser.java b/src/main/java/de/dhbwstuttgart/parser/antlr/Java8Parser.java index 398dd5f8..2d2fdd46 100644 --- a/src/main/java/de/dhbwstuttgart/parser/antlr/Java8Parser.java +++ b/src/main/java/de/dhbwstuttgart/parser/antlr/Java8Parser.java @@ -1,4 +1,4 @@ -// Generated from Java8.g4 by ANTLR 4.7 +// Generated from Java8.g4 by ANTLR 4.8 package de.dhbwstuttgart.parser.antlr; import org.antlr.v4.runtime.atn.*; import org.antlr.v4.runtime.dfa.DFA; @@ -11,7 +11,7 @@ import java.util.ArrayList; @SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) public class Java8Parser extends Parser { - static { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION); } + static { RuntimeMetaData.checkVersion("4.8", RuntimeMetaData.VERSION); } protected static final DFA[] _decisionToDFA; protected static final PredictionContextCache _sharedContextCache = @@ -122,108 +122,119 @@ public class Java8Parser extends Parser { RULE_postfixExpression = 232, RULE_postIncrementExpression = 233, RULE_postIncrementExpression_lf_postfixExpression = 234, RULE_postDecrementExpression = 235, RULE_postDecrementExpression_lf_postfixExpression = 236, RULE_castExpression = 237; - public static final String[] ruleNames = { - "literal", "type", "primitiveType", "numericType", "integralType", "floatingPointType", - "referenceType", "classOrInterfaceType", "classType", "classType_lf_classOrInterfaceType", - "classType_lfno_classOrInterfaceType", "interfaceType", "interfaceType_lf_classOrInterfaceType", - "interfaceType_lfno_classOrInterfaceType", "typeVariable", "arrayType", - "dims", "typeParameter", "typeParameterModifier", "typeBound", "additionalBound", - "typeArguments", "typeArgumentList", "typeArgument", "wildcard", "wildcardBounds", - "packageName", "typeName", "packageOrTypeName", "expressionName", "methodName", - "ambiguousName", "compilationUnit", "packageDeclaration", "packageModifier", - "importDeclaration", "singleTypeImportDeclaration", "typeImportOnDemandDeclaration", - "singleStaticImportDeclaration", "staticImportOnDemandDeclaration", "typeDeclaration", - "classDeclaration", "normalClassDeclaration", "classModifier", "typeParameters", - "typeParameterList", "superclass", "superinterfaces", "interfaceTypeList", - "classBody", "classBodyDeclaration", "classMemberDeclaration", "fieldDeclaration", - "fieldModifier", "variableDeclaratorList", "variableDeclarator", "variableDeclaratorId", - "variableInitializer", "unannType", "unannPrimitiveType", "unannReferenceType", - "unannClassOrInterfaceType", "unannClassType", "unannClassType_lf_unannClassOrInterfaceType", - "unannClassType_lfno_unannClassOrInterfaceType", "unannInterfaceType", - "unannInterfaceType_lf_unannClassOrInterfaceType", "unannInterfaceType_lfno_unannClassOrInterfaceType", - "unannTypeVariable", "unannArrayType", "methodDeclaration", "methodModifier", - "methodHeader", "result", "methodDeclarator", "formalParameterList", "formalParameters", - "formalParameter", "variableModifier", "lastFormalParameter", "receiverParameter", - "throws_", "exceptionTypeList", "exceptionType", "methodBody", "instanceInitializer", - "staticInitializer", "constructorDeclaration", "constructorModifier", - "constructorDeclarator", "simpleTypeName", "constructorBody", "explicitConstructorInvocation", - "enumDeclaration", "enumBody", "enumConstantList", "enumConstant", "enumConstantModifier", - "enumBodyDeclarations", "interfaceDeclaration", "normalInterfaceDeclaration", - "interfaceModifier", "extendsInterfaces", "interfaceBody", "interfaceMemberDeclaration", - "constantDeclaration", "constantModifier", "interfaceMethodDeclaration", - "interfaceMethodModifier", "annotationTypeDeclaration", "annotationTypeBody", - "annotationTypeMemberDeclaration", "annotationTypeElementDeclaration", - "annotationTypeElementModifier", "defaultValue", "annotation", "normalAnnotation", - "elementValuePairList", "elementValuePair", "elementValue", "elementValueArrayInitializer", - "elementValueList", "markerAnnotation", "singleElementAnnotation", "arrayInitializer", - "variableInitializerList", "block", "blockStatements", "blockStatement", - "localVariableDeclarationStatement", "unannTypeOrAuto", "localVariableDeclaration", - "statement", "statementNoShortIf", "statementWithoutTrailingSubstatement", - "emptyStatement", "labeledStatement", "labeledStatementNoShortIf", "expressionStatement", - "statementExpression", "ifThenStatement", "ifThenElseStatement", "ifThenElseStatementNoShortIf", - "assertStatement", "switchStatement", "switchBlock", "switchBlockStatementGroup", - "switchLabels", "switchLabel", "enumConstantName", "whileStatement", "whileStatementNoShortIf", - "doStatement", "forStatement", "forStatementNoShortIf", "basicForStatement", - "basicForStatementNoShortIf", "forInit", "forUpdate", "statementExpressionList", - "enhancedForStatement", "enhancedForStatementNoShortIf", "breakStatement", - "continueStatement", "returnStatement", "throwStatement", "synchronizedStatement", - "tryStatement", "catches", "catchClause", "catchFormalParameter", "catchType", - "finally_", "tryWithResourcesStatement", "resourceSpecification", "resourceList", - "resource", "primary", "primaryNoNewArray", "primaryNoNewArray_lf_arrayAccess", - "primaryNoNewArray_lfno_arrayAccess", "primaryNoNewArray_lf_primary", - "primaryNoNewArray_lf_primary_lf_arrayAccess_lf_primary", "primaryNoNewArray_lf_primary_lfno_arrayAccess_lf_primary", - "primaryNoNewArray_lfno_primary", "primaryNoNewArray_lfno_primary_lf_arrayAccess_lfno_primary", - "primaryNoNewArray_lfno_primary_lfno_arrayAccess_lfno_primary", "classInstanceCreationExpression", - "classInstanceCreationExpression_lf_primary", "classInstanceCreationExpression_lfno_primary", - "typeArgumentsOrDiamond", "fieldAccess", "fieldAccess_lf_primary", "fieldAccess_lfno_primary", - "arrayAccess", "arrayAccess_lf_primary", "arrayAccess_lfno_primary", "methodInvocation", - "methodInvocation_lf_primary", "methodInvocation_lfno_primary", "argumentList", - "methodReference", "methodReference_lf_primary", "methodReference_lfno_primary", - "arrayCreationExpression", "dimExprs", "dimExpr", "constantExpression", - "expression", "lambdaExpression", "lambdaParameters", "inferredFormalParameterList", - "lambdaBody", "assignmentExpression", "assignment", "leftHandSide", "assignmentOperator", - "conditionalExpression", "conditionalOrExpression", "conditionalAndExpression", - "inclusiveOrExpression", "exclusiveOrExpression", "andExpression", "equalityExpression", - "relationalExpression", "shiftExpression", "additiveExpression", "multiplicativeExpression", - "unaryExpression", "preIncrementExpression", "preDecrementExpression", - "unaryExpressionNotPlusMinus", "postfixExpression", "postIncrementExpression", - "postIncrementExpression_lf_postfixExpression", "postDecrementExpression", - "postDecrementExpression_lf_postfixExpression", "castExpression" - }; + private static String[] makeRuleNames() { + return new String[] { + "literal", "type", "primitiveType", "numericType", "integralType", "floatingPointType", + "referenceType", "classOrInterfaceType", "classType", "classType_lf_classOrInterfaceType", + "classType_lfno_classOrInterfaceType", "interfaceType", "interfaceType_lf_classOrInterfaceType", + "interfaceType_lfno_classOrInterfaceType", "typeVariable", "arrayType", + "dims", "typeParameter", "typeParameterModifier", "typeBound", "additionalBound", + "typeArguments", "typeArgumentList", "typeArgument", "wildcard", "wildcardBounds", + "packageName", "typeName", "packageOrTypeName", "expressionName", "methodName", + "ambiguousName", "compilationUnit", "packageDeclaration", "packageModifier", + "importDeclaration", "singleTypeImportDeclaration", "typeImportOnDemandDeclaration", + "singleStaticImportDeclaration", "staticImportOnDemandDeclaration", "typeDeclaration", + "classDeclaration", "normalClassDeclaration", "classModifier", "typeParameters", + "typeParameterList", "superclass", "superinterfaces", "interfaceTypeList", + "classBody", "classBodyDeclaration", "classMemberDeclaration", "fieldDeclaration", + "fieldModifier", "variableDeclaratorList", "variableDeclarator", "variableDeclaratorId", + "variableInitializer", "unannType", "unannPrimitiveType", "unannReferenceType", + "unannClassOrInterfaceType", "unannClassType", "unannClassType_lf_unannClassOrInterfaceType", + "unannClassType_lfno_unannClassOrInterfaceType", "unannInterfaceType", + "unannInterfaceType_lf_unannClassOrInterfaceType", "unannInterfaceType_lfno_unannClassOrInterfaceType", + "unannTypeVariable", "unannArrayType", "methodDeclaration", "methodModifier", + "methodHeader", "result", "methodDeclarator", "formalParameterList", + "formalParameters", "formalParameter", "variableModifier", "lastFormalParameter", + "receiverParameter", "throws_", "exceptionTypeList", "exceptionType", + "methodBody", "instanceInitializer", "staticInitializer", "constructorDeclaration", + "constructorModifier", "constructorDeclarator", "simpleTypeName", "constructorBody", + "explicitConstructorInvocation", "enumDeclaration", "enumBody", "enumConstantList", + "enumConstant", "enumConstantModifier", "enumBodyDeclarations", "interfaceDeclaration", + "normalInterfaceDeclaration", "interfaceModifier", "extendsInterfaces", + "interfaceBody", "interfaceMemberDeclaration", "constantDeclaration", + "constantModifier", "interfaceMethodDeclaration", "interfaceMethodModifier", + "annotationTypeDeclaration", "annotationTypeBody", "annotationTypeMemberDeclaration", + "annotationTypeElementDeclaration", "annotationTypeElementModifier", + "defaultValue", "annotation", "normalAnnotation", "elementValuePairList", + "elementValuePair", "elementValue", "elementValueArrayInitializer", "elementValueList", + "markerAnnotation", "singleElementAnnotation", "arrayInitializer", "variableInitializerList", + "block", "blockStatements", "blockStatement", "localVariableDeclarationStatement", + "unannTypeOrAuto", "localVariableDeclaration", "statement", "statementNoShortIf", + "statementWithoutTrailingSubstatement", "emptyStatement", "labeledStatement", + "labeledStatementNoShortIf", "expressionStatement", "statementExpression", + "ifThenStatement", "ifThenElseStatement", "ifThenElseStatementNoShortIf", + "assertStatement", "switchStatement", "switchBlock", "switchBlockStatementGroup", + "switchLabels", "switchLabel", "enumConstantName", "whileStatement", + "whileStatementNoShortIf", "doStatement", "forStatement", "forStatementNoShortIf", + "basicForStatement", "basicForStatementNoShortIf", "forInit", "forUpdate", + "statementExpressionList", "enhancedForStatement", "enhancedForStatementNoShortIf", + "breakStatement", "continueStatement", "returnStatement", "throwStatement", + "synchronizedStatement", "tryStatement", "catches", "catchClause", "catchFormalParameter", + "catchType", "finally_", "tryWithResourcesStatement", "resourceSpecification", + "resourceList", "resource", "primary", "primaryNoNewArray", "primaryNoNewArray_lf_arrayAccess", + "primaryNoNewArray_lfno_arrayAccess", "primaryNoNewArray_lf_primary", + "primaryNoNewArray_lf_primary_lf_arrayAccess_lf_primary", "primaryNoNewArray_lf_primary_lfno_arrayAccess_lf_primary", + "primaryNoNewArray_lfno_primary", "primaryNoNewArray_lfno_primary_lf_arrayAccess_lfno_primary", + "primaryNoNewArray_lfno_primary_lfno_arrayAccess_lfno_primary", "classInstanceCreationExpression", + "classInstanceCreationExpression_lf_primary", "classInstanceCreationExpression_lfno_primary", + "typeArgumentsOrDiamond", "fieldAccess", "fieldAccess_lf_primary", "fieldAccess_lfno_primary", + "arrayAccess", "arrayAccess_lf_primary", "arrayAccess_lfno_primary", + "methodInvocation", "methodInvocation_lf_primary", "methodInvocation_lfno_primary", + "argumentList", "methodReference", "methodReference_lf_primary", "methodReference_lfno_primary", + "arrayCreationExpression", "dimExprs", "dimExpr", "constantExpression", + "expression", "lambdaExpression", "lambdaParameters", "inferredFormalParameterList", + "lambdaBody", "assignmentExpression", "assignment", "leftHandSide", "assignmentOperator", + "conditionalExpression", "conditionalOrExpression", "conditionalAndExpression", + "inclusiveOrExpression", "exclusiveOrExpression", "andExpression", "equalityExpression", + "relationalExpression", "shiftExpression", "additiveExpression", "multiplicativeExpression", + "unaryExpression", "preIncrementExpression", "preDecrementExpression", + "unaryExpressionNotPlusMinus", "postfixExpression", "postIncrementExpression", + "postIncrementExpression_lf_postfixExpression", "postDecrementExpression", + "postDecrementExpression_lf_postfixExpression", "castExpression" + }; + } + public static final String[] ruleNames = makeRuleNames(); - private static final String[] _LITERAL_NAMES = { - null, "'var'", "'abstract'", "'assert'", "'boolean'", "'break'", "'byte'", - "'case'", "'catch'", "'char'", "'class'", "'const'", "'continue'", "'default'", - "'do'", "'double'", "'else'", "'enum'", "'extends'", "'final'", "'finally'", - "'float'", "'for'", "'if'", "'goto'", "'implements'", "'import'", "'instanceof'", - "'int'", "'interface'", "'long'", "'native'", "'new'", "'package'", "'private'", - "'protected'", "'public'", "'return'", "'short'", "'static'", "'strictfp'", - "'super'", "'switch'", "'synchronized'", "'this'", "'throw'", "'throws'", - "'transient'", "'try'", "'void'", "'volatile'", "'while'", null, null, - null, null, null, "'null'", "'('", "')'", "'{'", "'}'", "'['", "']'", - "';'", "','", "'.'", "'='", "'>'", "'<'", "'!'", "'~'", "'?'", "':'", - "'=='", "'<='", "'>='", "'!='", "'&&'", "'||'", "'++'", "'--'", "'+'", - "'-'", "'*'", "'/'", "'&'", "'|'", "'^'", "'%'", "'->'", "'::'", "'+='", - "'-='", "'*='", "'/='", "'&='", "'|='", "'^='", "'%='", "'<<='", "'>>='", - "'>>>='", null, "'@'", "'...'" - }; - private static final String[] _SYMBOLIC_NAMES = { - null, null, "ABSTRACT", "ASSERT", "BOOLEAN", "BREAK", "BYTE", "CASE", - "CATCH", "CHAR", "CLASS", "CONST", "CONTINUE", "DEFAULT", "DO", "DOUBLE", - "ELSE", "ENUM", "EXTENDS", "FINAL", "FINALLY", "FLOAT", "FOR", "IF", "GOTO", - "IMPLEMENTS", "IMPORT", "INSTANCEOF", "INT", "INTERFACE", "LONG", "NATIVE", - "NEW", "PACKAGE", "PRIVATE", "PROTECTED", "PUBLIC", "RETURN", "SHORT", - "STATIC", "STRICTFP", "SUPER", "SWITCH", "SYNCHRONIZED", "THIS", "THROW", - "THROWS", "TRANSIENT", "TRY", "VOID", "VOLATILE", "WHILE", "IntegerLiteral", - "FloatingPointLiteral", "BooleanLiteral", "CharacterLiteral", "StringLiteral", - "NullLiteral", "LPAREN", "RPAREN", "LBRACE", "RBRACE", "LBRACK", "RBRACK", - "SEMI", "COMMA", "DOT", "ASSIGN", "GT", "LT", "BANG", "TILDE", "QUESTION", - "COLON", "EQUAL", "LE", "GE", "NOTEQUAL", "AND", "OR", "INC", "DEC", "ADD", - "SUB", "MUL", "DIV", "BITAND", "BITOR", "CARET", "MOD", "ARROW", "COLONCOLON", - "ADD_ASSIGN", "SUB_ASSIGN", "MUL_ASSIGN", "DIV_ASSIGN", "AND_ASSIGN", - "OR_ASSIGN", "XOR_ASSIGN", "MOD_ASSIGN", "LSHIFT_ASSIGN", "RSHIFT_ASSIGN", - "URSHIFT_ASSIGN", "Identifier", "AT", "ELLIPSIS", "WS", "COMMENT", "LINE_COMMENT" - }; + private static String[] makeLiteralNames() { + return new String[] { + null, "'var'", "'abstract'", "'assert'", "'boolean'", "'break'", "'byte'", + "'case'", "'catch'", "'char'", "'class'", "'const'", "'continue'", "'default'", + "'do'", "'double'", "'else'", "'enum'", "'extends'", "'final'", "'finally'", + "'float'", "'for'", "'if'", "'goto'", "'implements'", "'import'", "'instanceof'", + "'int'", "'interface'", "'long'", "'native'", "'new'", "'package'", "'private'", + "'protected'", "'public'", "'return'", "'short'", "'static'", "'strictfp'", + "'super'", "'switch'", "'synchronized'", "'this'", "'throw'", "'throws'", + "'transient'", "'try'", "'void'", "'volatile'", "'while'", null, null, + null, null, null, "'null'", "'('", "')'", "'{'", "'}'", "'['", "']'", + "';'", "','", "'.'", "'='", "'>'", "'<'", "'!'", "'~'", "'?'", "':'", + "'=='", "'<='", "'>='", "'!='", "'&&'", "'||'", "'++'", "'--'", "'+'", + "'-'", "'*'", "'/'", "'&'", "'|'", "'^'", "'%'", "'->'", "'::'", "'+='", + "'-='", "'*='", "'/='", "'&='", "'|='", "'^='", "'%='", "'<<='", "'>>='", + "'>>>='", null, "'@'", "'...'" + }; + } + private static final String[] _LITERAL_NAMES = makeLiteralNames(); + private static String[] makeSymbolicNames() { + return new String[] { + null, null, "ABSTRACT", "ASSERT", "BOOLEAN", "BREAK", "BYTE", "CASE", + "CATCH", "CHAR", "CLASS", "CONST", "CONTINUE", "DEFAULT", "DO", "DOUBLE", + "ELSE", "ENUM", "EXTENDS", "FINAL", "FINALLY", "FLOAT", "FOR", "IF", + "GOTO", "IMPLEMENTS", "IMPORT", "INSTANCEOF", "INT", "INTERFACE", "LONG", + "NATIVE", "NEW", "PACKAGE", "PRIVATE", "PROTECTED", "PUBLIC", "RETURN", + "SHORT", "STATIC", "STRICTFP", "SUPER", "SWITCH", "SYNCHRONIZED", "THIS", + "THROW", "THROWS", "TRANSIENT", "TRY", "VOID", "VOLATILE", "WHILE", "IntegerLiteral", + "FloatingPointLiteral", "BooleanLiteral", "CharacterLiteral", "StringLiteral", + "NullLiteral", "LPAREN", "RPAREN", "LBRACE", "RBRACE", "LBRACK", "RBRACK", + "SEMI", "COMMA", "DOT", "ASSIGN", "GT", "LT", "BANG", "TILDE", "QUESTION", + "COLON", "EQUAL", "LE", "GE", "NOTEQUAL", "AND", "OR", "INC", "DEC", + "ADD", "SUB", "MUL", "DIV", "BITAND", "BITOR", "CARET", "MOD", "ARROW", + "COLONCOLON", "ADD_ASSIGN", "SUB_ASSIGN", "MUL_ASSIGN", "DIV_ASSIGN", + "AND_ASSIGN", "OR_ASSIGN", "XOR_ASSIGN", "MOD_ASSIGN", "LSHIFT_ASSIGN", + "RSHIFT_ASSIGN", "URSHIFT_ASSIGN", "Identifier", "AT", "ELLIPSIS", "WS", + "COMMENT", "LINE_COMMENT" + }; + } + private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames(); public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); /** @@ -273,6 +284,7 @@ public class Java8Parser extends Parser { super(input); _interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); } + public static class LiteralContext extends ParserRuleContext { public TerminalNode IntegerLiteral() { return getToken(Java8Parser.IntegerLiteral, 0); } public TerminalNode FloatingPointLiteral() { return getToken(Java8Parser.FloatingPointLiteral, 0); } @@ -389,6 +401,7 @@ public class Java8Parser extends Parser { public AnnotationContext annotation(int i) { return getRuleContext(AnnotationContext.class,i); } + public TerminalNode BOOLEAN() { return getToken(Java8Parser.BOOLEAN, 0); } public PrimitiveTypeContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -529,6 +542,11 @@ public class Java8Parser extends Parser { } public static class IntegralTypeContext extends ParserRuleContext { + public TerminalNode BYTE() { return getToken(Java8Parser.BYTE, 0); } + public TerminalNode SHORT() { return getToken(Java8Parser.SHORT, 0); } + public TerminalNode INT() { return getToken(Java8Parser.INT, 0); } + public TerminalNode LONG() { return getToken(Java8Parser.LONG, 0); } + public TerminalNode CHAR() { return getToken(Java8Parser.CHAR, 0); } public IntegralTypeContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -574,6 +592,8 @@ public class Java8Parser extends Parser { } public static class FloatingPointTypeContext extends ParserRuleContext { + public TerminalNode FLOAT() { return getToken(Java8Parser.FLOAT, 0); } + public TerminalNode DOUBLE() { return getToken(Java8Parser.DOUBLE, 0); } public FloatingPointTypeContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -736,7 +756,7 @@ public class Java8Parser extends Parser { setState(518); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,7,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { @@ -776,6 +796,7 @@ public class Java8Parser extends Parser { public ClassOrInterfaceTypeContext classOrInterfaceType() { return getRuleContext(ClassOrInterfaceTypeContext.class,0); } + public TerminalNode DOT() { return getToken(Java8Parser.DOT, 0); } public ClassTypeContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -878,6 +899,7 @@ public class Java8Parser extends Parser { } public static class ClassType_lf_classOrInterfaceTypeContext extends ParserRuleContext { + public TerminalNode DOT() { return getToken(Java8Parser.DOT, 0); } public TerminalNode Identifier() { return getToken(Java8Parser.Identifier, 0); } public List annotation() { return getRuleContexts(AnnotationContext.class); @@ -1271,6 +1293,14 @@ public class Java8Parser extends Parser { } public static class DimsContext extends ParserRuleContext { + public List LBRACK() { return getTokens(Java8Parser.LBRACK); } + public TerminalNode LBRACK(int i) { + return getToken(Java8Parser.LBRACK, i); + } + public List RBRACK() { return getTokens(Java8Parser.RBRACK); } + public TerminalNode RBRACK(int i) { + return getToken(Java8Parser.RBRACK, i); + } public List annotation() { return getRuleContexts(AnnotationContext.class); } @@ -1320,7 +1350,7 @@ public class Java8Parser extends Parser { setState(609); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,21,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { @@ -1473,6 +1503,7 @@ public class Java8Parser extends Parser { } public static class TypeBoundContext extends ParserRuleContext { + public TerminalNode EXTENDS() { return getToken(Java8Parser.EXTENDS, 0); } public TypeVariableContext typeVariable() { return getRuleContext(TypeVariableContext.class,0); } @@ -1553,6 +1584,7 @@ public class Java8Parser extends Parser { } public static class AdditionalBoundContext extends ParserRuleContext { + public TerminalNode BITAND() { return getToken(Java8Parser.BITAND, 0); } public InterfaceTypeContext interfaceType() { return getRuleContext(InterfaceTypeContext.class,0); } @@ -1594,9 +1626,11 @@ public class Java8Parser extends Parser { } public static class TypeArgumentsContext extends ParserRuleContext { + public TerminalNode LT() { return getToken(Java8Parser.LT, 0); } public TypeArgumentListContext typeArgumentList() { return getRuleContext(TypeArgumentListContext.class,0); } + public TerminalNode GT() { return getToken(Java8Parser.GT, 0); } public TypeArgumentsContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -1643,6 +1677,10 @@ public class Java8Parser extends Parser { public TypeArgumentContext typeArgument(int i) { return getRuleContext(TypeArgumentContext.class,i); } + public List COMMA() { return getTokens(Java8Parser.COMMA); } + public TerminalNode COMMA(int i) { + return getToken(Java8Parser.COMMA, i); + } public TypeArgumentListContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -1751,6 +1789,7 @@ public class Java8Parser extends Parser { } public static class WildcardContext extends ParserRuleContext { + public TerminalNode QUESTION() { return getToken(Java8Parser.QUESTION, 0); } public List annotation() { return getRuleContexts(AnnotationContext.class); } @@ -1821,9 +1860,11 @@ public class Java8Parser extends Parser { } public static class WildcardBoundsContext extends ParserRuleContext { + public TerminalNode EXTENDS() { return getToken(Java8Parser.EXTENDS, 0); } public ReferenceTypeContext referenceType() { return getRuleContext(ReferenceTypeContext.class,0); } + public TerminalNode SUPER() { return getToken(Java8Parser.SUPER, 0); } public WildcardBoundsContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -1883,6 +1924,7 @@ public class Java8Parser extends Parser { public PackageNameContext packageName() { return getRuleContext(PackageNameContext.class,0); } + public TerminalNode DOT() { return getToken(Java8Parser.DOT, 0); } public PackageNameContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -1920,7 +1962,7 @@ public class Java8Parser extends Parser { setState(679); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,31,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; @@ -1959,6 +2001,7 @@ public class Java8Parser extends Parser { public PackageOrTypeNameContext packageOrTypeName() { return getRuleContext(PackageOrTypeNameContext.class,0); } + public TerminalNode DOT() { return getToken(Java8Parser.DOT, 0); } public TypeNameContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -2016,6 +2059,7 @@ public class Java8Parser extends Parser { public PackageOrTypeNameContext packageOrTypeName() { return getRuleContext(PackageOrTypeNameContext.class,0); } + public TerminalNode DOT() { return getToken(Java8Parser.DOT, 0); } public PackageOrTypeNameContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -2053,7 +2097,7 @@ public class Java8Parser extends Parser { setState(697); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,33,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; @@ -2092,6 +2136,7 @@ public class Java8Parser extends Parser { public AmbiguousNameContext ambiguousName() { return getRuleContext(AmbiguousNameContext.class,0); } + public TerminalNode DOT() { return getToken(Java8Parser.DOT, 0); } public ExpressionNameContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -2186,6 +2231,7 @@ public class Java8Parser extends Parser { public AmbiguousNameContext ambiguousName() { return getRuleContext(AmbiguousNameContext.class,0); } + public TerminalNode DOT() { return getToken(Java8Parser.DOT, 0); } public AmbiguousNameContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -2223,7 +2269,7 @@ public class Java8Parser extends Parser { setState(717); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,35,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; @@ -2349,16 +2395,22 @@ public class Java8Parser extends Parser { } public static class PackageDeclarationContext extends ParserRuleContext { + public TerminalNode PACKAGE() { return getToken(Java8Parser.PACKAGE, 0); } public List Identifier() { return getTokens(Java8Parser.Identifier); } public TerminalNode Identifier(int i) { return getToken(Java8Parser.Identifier, i); } + public TerminalNode SEMI() { return getToken(Java8Parser.SEMI, 0); } public List packageModifier() { return getRuleContexts(PackageModifierContext.class); } public PackageModifierContext packageModifier(int i) { return getRuleContext(PackageModifierContext.class,i); } + public List DOT() { return getTokens(Java8Parser.DOT); } + public TerminalNode DOT(int i) { + return getToken(Java8Parser.DOT, i); + } public PackageDeclarationContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -2544,9 +2596,11 @@ public class Java8Parser extends Parser { } public static class SingleTypeImportDeclarationContext extends ParserRuleContext { + public TerminalNode IMPORT() { return getToken(Java8Parser.IMPORT, 0); } public TypeNameContext typeName() { return getRuleContext(TypeNameContext.class,0); } + public TerminalNode SEMI() { return getToken(Java8Parser.SEMI, 0); } public SingleTypeImportDeclarationContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -2587,9 +2641,13 @@ public class Java8Parser extends Parser { } public static class TypeImportOnDemandDeclarationContext extends ParserRuleContext { + public TerminalNode IMPORT() { return getToken(Java8Parser.IMPORT, 0); } public PackageOrTypeNameContext packageOrTypeName() { return getRuleContext(PackageOrTypeNameContext.class,0); } + public TerminalNode DOT() { return getToken(Java8Parser.DOT, 0); } + public TerminalNode MUL() { return getToken(Java8Parser.MUL, 0); } + public TerminalNode SEMI() { return getToken(Java8Parser.SEMI, 0); } public TypeImportOnDemandDeclarationContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -2634,10 +2692,14 @@ public class Java8Parser extends Parser { } public static class SingleStaticImportDeclarationContext extends ParserRuleContext { + public TerminalNode IMPORT() { return getToken(Java8Parser.IMPORT, 0); } + public TerminalNode STATIC() { return getToken(Java8Parser.STATIC, 0); } public TypeNameContext typeName() { return getRuleContext(TypeNameContext.class,0); } + public TerminalNode DOT() { return getToken(Java8Parser.DOT, 0); } public TerminalNode Identifier() { return getToken(Java8Parser.Identifier, 0); } + public TerminalNode SEMI() { return getToken(Java8Parser.SEMI, 0); } public SingleStaticImportDeclarationContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -2684,9 +2746,14 @@ public class Java8Parser extends Parser { } public static class StaticImportOnDemandDeclarationContext extends ParserRuleContext { + public TerminalNode IMPORT() { return getToken(Java8Parser.IMPORT, 0); } + public TerminalNode STATIC() { return getToken(Java8Parser.STATIC, 0); } public TypeNameContext typeName() { return getRuleContext(TypeNameContext.class,0); } + public TerminalNode DOT() { return getToken(Java8Parser.DOT, 0); } + public TerminalNode MUL() { return getToken(Java8Parser.MUL, 0); } + public TerminalNode SEMI() { return getToken(Java8Parser.SEMI, 0); } public StaticImportOnDemandDeclarationContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -2739,6 +2806,7 @@ public class Java8Parser extends Parser { public InterfaceDeclarationContext interfaceDeclaration() { return getRuleContext(InterfaceDeclarationContext.class,0); } + public TerminalNode SEMI() { return getToken(Java8Parser.SEMI, 0); } public TypeDeclarationContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -2850,6 +2918,7 @@ public class Java8Parser extends Parser { } public static class NormalClassDeclarationContext extends ParserRuleContext { + public TerminalNode CLASS() { return getToken(Java8Parser.CLASS, 0); } public TerminalNode Identifier() { return getToken(Java8Parser.Identifier, 0); } public ClassBodyContext classBody() { return getRuleContext(ClassBodyContext.class,0); @@ -2957,6 +3026,13 @@ public class Java8Parser extends Parser { public AnnotationContext annotation() { return getRuleContext(AnnotationContext.class,0); } + public TerminalNode PUBLIC() { return getToken(Java8Parser.PUBLIC, 0); } + public TerminalNode PROTECTED() { return getToken(Java8Parser.PROTECTED, 0); } + public TerminalNode PRIVATE() { return getToken(Java8Parser.PRIVATE, 0); } + public TerminalNode ABSTRACT() { return getToken(Java8Parser.ABSTRACT, 0); } + public TerminalNode STATIC() { return getToken(Java8Parser.STATIC, 0); } + public TerminalNode FINAL() { return getToken(Java8Parser.FINAL, 0); } + public TerminalNode STRICTFP() { return getToken(Java8Parser.STRICTFP, 0); } public ClassModifierContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -3050,9 +3126,11 @@ public class Java8Parser extends Parser { } public static class TypeParametersContext extends ParserRuleContext { + public TerminalNode LT() { return getToken(Java8Parser.LT, 0); } public TypeParameterListContext typeParameterList() { return getRuleContext(TypeParameterListContext.class,0); } + public TerminalNode GT() { return getToken(Java8Parser.GT, 0); } public TypeParametersContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -3099,6 +3177,10 @@ public class Java8Parser extends Parser { public TypeParameterContext typeParameter(int i) { return getRuleContext(TypeParameterContext.class,i); } + public List COMMA() { return getTokens(Java8Parser.COMMA); } + public TerminalNode COMMA(int i) { + return getToken(Java8Parser.COMMA, i); + } public TypeParameterListContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -3152,6 +3234,7 @@ public class Java8Parser extends Parser { } public static class SuperclassContext extends ParserRuleContext { + public TerminalNode EXTENDS() { return getToken(Java8Parser.EXTENDS, 0); } public ClassTypeContext classType() { return getRuleContext(ClassTypeContext.class,0); } @@ -3193,6 +3276,7 @@ public class Java8Parser extends Parser { } public static class SuperinterfacesContext extends ParserRuleContext { + public TerminalNode IMPLEMENTS() { return getToken(Java8Parser.IMPLEMENTS, 0); } public InterfaceTypeListContext interfaceTypeList() { return getRuleContext(InterfaceTypeListContext.class,0); } @@ -3240,6 +3324,10 @@ public class Java8Parser extends Parser { public InterfaceTypeContext interfaceType(int i) { return getRuleContext(InterfaceTypeContext.class,i); } + public List COMMA() { return getTokens(Java8Parser.COMMA); } + public TerminalNode COMMA(int i) { + return getToken(Java8Parser.COMMA, i); + } public InterfaceTypeListContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -3293,6 +3381,8 @@ public class Java8Parser extends Parser { } public static class ClassBodyContext extends ParserRuleContext { + public TerminalNode LBRACE() { return getToken(Java8Parser.LBRACE, 0); } + public TerminalNode RBRACE() { return getToken(Java8Parser.RBRACE, 0); } public List classBodyDeclaration() { return getRuleContexts(ClassBodyDeclarationContext.class); } @@ -3429,6 +3519,7 @@ public class Java8Parser extends Parser { public InterfaceDeclarationContext interfaceDeclaration() { return getRuleContext(InterfaceDeclarationContext.class,0); } + public TerminalNode SEMI() { return getToken(Java8Parser.SEMI, 0); } public ClassMemberDeclarationContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -3502,6 +3593,7 @@ public class Java8Parser extends Parser { public VariableDeclaratorListContext variableDeclaratorList() { return getRuleContext(VariableDeclaratorListContext.class,0); } + public TerminalNode SEMI() { return getToken(Java8Parser.SEMI, 0); } public List fieldModifier() { return getRuleContexts(FieldModifierContext.class); } @@ -3577,6 +3669,13 @@ public class Java8Parser extends Parser { public AnnotationContext annotation() { return getRuleContext(AnnotationContext.class,0); } + public TerminalNode PUBLIC() { return getToken(Java8Parser.PUBLIC, 0); } + public TerminalNode PROTECTED() { return getToken(Java8Parser.PROTECTED, 0); } + public TerminalNode PRIVATE() { return getToken(Java8Parser.PRIVATE, 0); } + public TerminalNode STATIC() { return getToken(Java8Parser.STATIC, 0); } + public TerminalNode FINAL() { return getToken(Java8Parser.FINAL, 0); } + public TerminalNode TRANSIENT() { return getToken(Java8Parser.TRANSIENT, 0); } + public TerminalNode VOLATILE() { return getToken(Java8Parser.VOLATILE, 0); } public FieldModifierContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -3676,6 +3775,10 @@ public class Java8Parser extends Parser { public VariableDeclaratorContext variableDeclarator(int i) { return getRuleContext(VariableDeclaratorContext.class,i); } + public List COMMA() { return getTokens(Java8Parser.COMMA); } + public TerminalNode COMMA(int i) { + return getToken(Java8Parser.COMMA, i); + } public VariableDeclaratorListContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -3732,6 +3835,7 @@ public class Java8Parser extends Parser { public VariableDeclaratorIdContext variableDeclaratorId() { return getRuleContext(VariableDeclaratorIdContext.class,0); } + public TerminalNode ASSIGN() { return getToken(Java8Parser.ASSIGN, 0); } public VariableInitializerContext variableInitializer() { return getRuleContext(VariableInitializerContext.class,0); } @@ -3976,6 +4080,7 @@ public class Java8Parser extends Parser { public NumericTypeContext numericType() { return getRuleContext(NumericTypeContext.class,0); } + public TerminalNode BOOLEAN() { return getToken(Java8Parser.BOOLEAN, 0); } public UnannPrimitiveTypeContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -4156,7 +4261,7 @@ public class Java8Parser extends Parser { setState(935); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,66,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { setState(933); @@ -4202,6 +4307,7 @@ public class Java8Parser extends Parser { public UnannClassOrInterfaceTypeContext unannClassOrInterfaceType() { return getRuleContext(UnannClassOrInterfaceTypeContext.class,0); } + public TerminalNode DOT() { return getToken(Java8Parser.DOT, 0); } public List annotation() { return getRuleContexts(AnnotationContext.class); } @@ -4296,6 +4402,7 @@ public class Java8Parser extends Parser { } public static class UnannClassType_lf_unannClassOrInterfaceTypeContext extends ParserRuleContext { + public TerminalNode DOT() { return getToken(Java8Parser.DOT, 0); } public TerminalNode Identifier() { return getToken(Java8Parser.Identifier, 0); } public List annotation() { return getRuleContexts(AnnotationContext.class); @@ -4716,6 +4823,15 @@ public class Java8Parser extends Parser { public AnnotationContext annotation() { return getRuleContext(AnnotationContext.class,0); } + public TerminalNode PUBLIC() { return getToken(Java8Parser.PUBLIC, 0); } + public TerminalNode PROTECTED() { return getToken(Java8Parser.PROTECTED, 0); } + public TerminalNode PRIVATE() { return getToken(Java8Parser.PRIVATE, 0); } + public TerminalNode ABSTRACT() { return getToken(Java8Parser.ABSTRACT, 0); } + public TerminalNode STATIC() { return getToken(Java8Parser.STATIC, 0); } + public TerminalNode FINAL() { return getToken(Java8Parser.FINAL, 0); } + public TerminalNode SYNCHRONIZED() { return getToken(Java8Parser.SYNCHRONIZED, 0); } + public TerminalNode NATIVE() { return getToken(Java8Parser.NATIVE, 0); } + public TerminalNode STRICTFP() { return getToken(Java8Parser.STRICTFP, 0); } public MethodModifierContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -4961,6 +5077,7 @@ public class Java8Parser extends Parser { public UnannTypeContext unannType() { return getRuleContext(UnannTypeContext.class,0); } + public TerminalNode VOID() { return getToken(Java8Parser.VOID, 0); } public ResultContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -5021,6 +5138,8 @@ public class Java8Parser extends Parser { public static class MethodDeclaratorContext extends ParserRuleContext { public TerminalNode Identifier() { return getToken(Java8Parser.Identifier, 0); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public FormalParameterListContext formalParameterList() { return getRuleContext(FormalParameterListContext.class,0); } @@ -5091,6 +5210,7 @@ public class Java8Parser extends Parser { public FormalParametersContext formalParameters() { return getRuleContext(FormalParametersContext.class,0); } + public TerminalNode COMMA() { return getToken(Java8Parser.COMMA, 0); } public LastFormalParameterContext lastFormalParameter() { return getRuleContext(LastFormalParameterContext.class,0); } @@ -5153,6 +5273,10 @@ public class Java8Parser extends Parser { public FormalParameterContext formalParameter(int i) { return getRuleContext(FormalParameterContext.class,i); } + public List COMMA() { return getTokens(Java8Parser.COMMA); } + public TerminalNode COMMA(int i) { + return getToken(Java8Parser.COMMA, i); + } public ReceiverParameterContext receiverParameter() { return getRuleContext(ReceiverParameterContext.class,0); } @@ -5186,7 +5310,7 @@ public class Java8Parser extends Parser { setState(1059); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,87,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { @@ -5211,7 +5335,7 @@ public class Java8Parser extends Parser { setState(1067); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,88,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { @@ -5318,6 +5442,7 @@ public class Java8Parser extends Parser { public AnnotationContext annotation() { return getRuleContext(AnnotationContext.class,0); } + public TerminalNode FINAL() { return getToken(Java8Parser.FINAL, 0); } public VariableModifierContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -5372,6 +5497,7 @@ public class Java8Parser extends Parser { public UnannTypeContext unannType() { return getRuleContext(UnannTypeContext.class,0); } + public TerminalNode ELLIPSIS() { return getToken(Java8Parser.ELLIPSIS, 0); } public VariableDeclaratorIdContext variableDeclaratorId() { return getRuleContext(VariableDeclaratorIdContext.class,0); } @@ -5475,6 +5601,7 @@ public class Java8Parser extends Parser { public UnannTypeContext unannType() { return getRuleContext(UnannTypeContext.class,0); } + public TerminalNode THIS() { return getToken(Java8Parser.THIS, 0); } public List annotation() { return getRuleContexts(AnnotationContext.class); } @@ -5482,6 +5609,7 @@ public class Java8Parser extends Parser { return getRuleContext(AnnotationContext.class,i); } public TerminalNode Identifier() { return getToken(Java8Parser.Identifier, 0); } + public TerminalNode DOT() { return getToken(Java8Parser.DOT, 0); } public ReceiverParameterContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -5547,6 +5675,7 @@ public class Java8Parser extends Parser { } public static class Throws_Context extends ParserRuleContext { + public TerminalNode THROWS() { return getToken(Java8Parser.THROWS, 0); } public ExceptionTypeListContext exceptionTypeList() { return getRuleContext(ExceptionTypeListContext.class,0); } @@ -5594,6 +5723,10 @@ public class Java8Parser extends Parser { public ExceptionTypeContext exceptionType(int i) { return getRuleContext(ExceptionTypeContext.class,i); } + public List COMMA() { return getTokens(Java8Parser.COMMA); } + public TerminalNode COMMA(int i) { + return getToken(Java8Parser.COMMA, i); + } public ExceptionTypeListContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -5705,6 +5838,7 @@ public class Java8Parser extends Parser { public BlockContext block() { return getRuleContext(BlockContext.class,0); } + public TerminalNode SEMI() { return getToken(Java8Parser.SEMI, 0); } public MethodBodyContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -5795,6 +5929,7 @@ public class Java8Parser extends Parser { } public static class StaticInitializerContext extends ParserRuleContext { + public TerminalNode STATIC() { return getToken(Java8Parser.STATIC, 0); } public BlockContext block() { return getRuleContext(BlockContext.class,0); } @@ -5917,6 +6052,9 @@ public class Java8Parser extends Parser { public AnnotationContext annotation() { return getRuleContext(AnnotationContext.class,0); } + public TerminalNode PUBLIC() { return getToken(Java8Parser.PUBLIC, 0); } + public TerminalNode PROTECTED() { return getToken(Java8Parser.PROTECTED, 0); } + public TerminalNode PRIVATE() { return getToken(Java8Parser.PRIVATE, 0); } public ConstructorModifierContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -5985,6 +6123,8 @@ public class Java8Parser extends Parser { public SimpleTypeNameContext simpleTypeName() { return getRuleContext(SimpleTypeNameContext.class,0); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public TypeParametersContext typeParameters() { return getRuleContext(TypeParametersContext.class,0); } @@ -6089,6 +6229,8 @@ public class Java8Parser extends Parser { } public static class ConstructorBodyContext extends ParserRuleContext { + public TerminalNode LBRACE() { return getToken(Java8Parser.LBRACE, 0); } + public TerminalNode RBRACE() { return getToken(Java8Parser.RBRACE, 0); } public ExplicitConstructorInvocationContext explicitConstructorInvocation() { return getRuleContext(ExplicitConstructorInvocationContext.class,0); } @@ -6154,15 +6296,21 @@ public class Java8Parser extends Parser { } public static class ExplicitConstructorInvocationContext extends ParserRuleContext { + public TerminalNode THIS() { return getToken(Java8Parser.THIS, 0); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } + public TerminalNode SEMI() { return getToken(Java8Parser.SEMI, 0); } public TypeArgumentsContext typeArguments() { return getRuleContext(TypeArgumentsContext.class,0); } public ArgumentListContext argumentList() { return getRuleContext(ArgumentListContext.class,0); } + public TerminalNode SUPER() { return getToken(Java8Parser.SUPER, 0); } public ExpressionNameContext expressionName() { return getRuleContext(ExpressionNameContext.class,0); } + public TerminalNode DOT() { return getToken(Java8Parser.DOT, 0); } public PrimaryContext primary() { return getRuleContext(PrimaryContext.class,0); } @@ -6342,6 +6490,7 @@ public class Java8Parser extends Parser { } public static class EnumDeclarationContext extends ParserRuleContext { + public TerminalNode ENUM() { return getToken(Java8Parser.ENUM, 0); } public TerminalNode Identifier() { return getToken(Java8Parser.Identifier, 0); } public EnumBodyContext enumBody() { return getRuleContext(EnumBodyContext.class,0); @@ -6420,9 +6569,12 @@ public class Java8Parser extends Parser { } public static class EnumBodyContext extends ParserRuleContext { + public TerminalNode LBRACE() { return getToken(Java8Parser.LBRACE, 0); } + public TerminalNode RBRACE() { return getToken(Java8Parser.RBRACE, 0); } public EnumConstantListContext enumConstantList() { return getRuleContext(EnumConstantListContext.class,0); } + public TerminalNode COMMA() { return getToken(Java8Parser.COMMA, 0); } public EnumBodyDeclarationsContext enumBodyDeclarations() { return getRuleContext(EnumBodyDeclarationsContext.class,0); } @@ -6501,6 +6653,10 @@ public class Java8Parser extends Parser { public EnumConstantContext enumConstant(int i) { return getRuleContext(EnumConstantContext.class,i); } + public List COMMA() { return getTokens(Java8Parser.COMMA); } + public TerminalNode COMMA(int i) { + return getToken(Java8Parser.COMMA, i); + } public EnumConstantListContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -6527,7 +6683,7 @@ public class Java8Parser extends Parser { setState(1260); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,122,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { @@ -6563,6 +6719,8 @@ public class Java8Parser extends Parser { public EnumConstantModifierContext enumConstantModifier(int i) { return getRuleContext(EnumConstantModifierContext.class,i); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public ClassBodyContext classBody() { return getRuleContext(ClassBodyContext.class,0); } @@ -6691,6 +6849,7 @@ public class Java8Parser extends Parser { } public static class EnumBodyDeclarationsContext extends ParserRuleContext { + public TerminalNode SEMI() { return getToken(Java8Parser.SEMI, 0); } public List classBodyDeclaration() { return getRuleContexts(ClassBodyDeclarationContext.class); } @@ -6803,6 +6962,7 @@ public class Java8Parser extends Parser { } public static class NormalInterfaceDeclarationContext extends ParserRuleContext { + public TerminalNode INTERFACE() { return getToken(Java8Parser.INTERFACE, 0); } public TerminalNode Identifier() { return getToken(Java8Parser.Identifier, 0); } public InterfaceBodyContext interfaceBody() { return getRuleContext(InterfaceBodyContext.class,0); @@ -6897,6 +7057,12 @@ public class Java8Parser extends Parser { public AnnotationContext annotation() { return getRuleContext(AnnotationContext.class,0); } + public TerminalNode PUBLIC() { return getToken(Java8Parser.PUBLIC, 0); } + public TerminalNode PROTECTED() { return getToken(Java8Parser.PROTECTED, 0); } + public TerminalNode PRIVATE() { return getToken(Java8Parser.PRIVATE, 0); } + public TerminalNode ABSTRACT() { return getToken(Java8Parser.ABSTRACT, 0); } + public TerminalNode STATIC() { return getToken(Java8Parser.STATIC, 0); } + public TerminalNode STRICTFP() { return getToken(Java8Parser.STRICTFP, 0); } public InterfaceModifierContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -6983,6 +7149,7 @@ public class Java8Parser extends Parser { } public static class ExtendsInterfacesContext extends ParserRuleContext { + public TerminalNode EXTENDS() { return getToken(Java8Parser.EXTENDS, 0); } public InterfaceTypeListContext interfaceTypeList() { return getRuleContext(InterfaceTypeListContext.class,0); } @@ -7024,6 +7191,8 @@ public class Java8Parser extends Parser { } public static class InterfaceBodyContext extends ParserRuleContext { + public TerminalNode LBRACE() { return getToken(Java8Parser.LBRACE, 0); } + public TerminalNode RBRACE() { return getToken(Java8Parser.RBRACE, 0); } public List interfaceMemberDeclaration() { return getRuleContexts(InterfaceMemberDeclarationContext.class); } @@ -7095,6 +7264,7 @@ public class Java8Parser extends Parser { public InterfaceDeclarationContext interfaceDeclaration() { return getRuleContext(InterfaceDeclarationContext.class,0); } + public TerminalNode SEMI() { return getToken(Java8Parser.SEMI, 0); } public InterfaceMemberDeclarationContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -7171,6 +7341,7 @@ public class Java8Parser extends Parser { public VariableDeclaratorListContext variableDeclaratorList() { return getRuleContext(VariableDeclaratorListContext.class,0); } + public TerminalNode SEMI() { return getToken(Java8Parser.SEMI, 0); } public List constantModifier() { return getRuleContexts(ConstantModifierContext.class); } @@ -7235,6 +7406,9 @@ public class Java8Parser extends Parser { public AnnotationContext annotation() { return getRuleContext(AnnotationContext.class,0); } + public TerminalNode PUBLIC() { return getToken(Java8Parser.PUBLIC, 0); } + public TerminalNode STATIC() { return getToken(Java8Parser.STATIC, 0); } + public TerminalNode FINAL() { return getToken(Java8Parser.FINAL, 0); } public ConstantModifierContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -7368,6 +7542,11 @@ public class Java8Parser extends Parser { public AnnotationContext annotation() { return getRuleContext(AnnotationContext.class,0); } + public TerminalNode PUBLIC() { return getToken(Java8Parser.PUBLIC, 0); } + public TerminalNode ABSTRACT() { return getToken(Java8Parser.ABSTRACT, 0); } + public TerminalNode DEFAULT() { return getToken(Java8Parser.DEFAULT, 0); } + public TerminalNode STATIC() { return getToken(Java8Parser.STATIC, 0); } + public TerminalNode STRICTFP() { return getToken(Java8Parser.STRICTFP, 0); } public InterfaceMethodModifierContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -7447,6 +7626,8 @@ public class Java8Parser extends Parser { } public static class AnnotationTypeDeclarationContext extends ParserRuleContext { + public TerminalNode AT() { return getToken(Java8Parser.AT, 0); } + public TerminalNode INTERFACE() { return getToken(Java8Parser.INTERFACE, 0); } public TerminalNode Identifier() { return getToken(Java8Parser.Identifier, 0); } public AnnotationTypeBodyContext annotationTypeBody() { return getRuleContext(AnnotationTypeBodyContext.class,0); @@ -7481,7 +7662,7 @@ public class Java8Parser extends Parser { setState(1373); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,139,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { @@ -7516,6 +7697,8 @@ public class Java8Parser extends Parser { } public static class AnnotationTypeBodyContext extends ParserRuleContext { + public TerminalNode LBRACE() { return getToken(Java8Parser.LBRACE, 0); } + public TerminalNode RBRACE() { return getToken(Java8Parser.RBRACE, 0); } public List annotationTypeMemberDeclaration() { return getRuleContexts(AnnotationTypeMemberDeclarationContext.class); } @@ -7587,6 +7770,7 @@ public class Java8Parser extends Parser { public InterfaceDeclarationContext interfaceDeclaration() { return getRuleContext(InterfaceDeclarationContext.class,0); } + public TerminalNode SEMI() { return getToken(Java8Parser.SEMI, 0); } public AnnotationTypeMemberDeclarationContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -7661,6 +7845,9 @@ public class Java8Parser extends Parser { return getRuleContext(UnannTypeContext.class,0); } public TerminalNode Identifier() { return getToken(Java8Parser.Identifier, 0); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } + public TerminalNode SEMI() { return getToken(Java8Parser.SEMI, 0); } public List annotationTypeElementModifier() { return getRuleContexts(AnnotationTypeElementModifierContext.class); } @@ -7755,6 +7942,8 @@ public class Java8Parser extends Parser { public AnnotationContext annotation() { return getRuleContext(AnnotationContext.class,0); } + public TerminalNode PUBLIC() { return getToken(Java8Parser.PUBLIC, 0); } + public TerminalNode ABSTRACT() { return getToken(Java8Parser.ABSTRACT, 0); } public AnnotationTypeElementModifierContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -7813,6 +8002,7 @@ public class Java8Parser extends Parser { } public static class DefaultValueContext extends ParserRuleContext { + public TerminalNode DEFAULT() { return getToken(Java8Parser.DEFAULT, 0); } public ElementValueContext elementValue() { return getRuleContext(ElementValueContext.class,0); } @@ -7919,9 +8109,12 @@ public class Java8Parser extends Parser { } public static class NormalAnnotationContext extends ParserRuleContext { + public TerminalNode AT() { return getToken(Java8Parser.AT, 0); } public TypeNameContext typeName() { return getRuleContext(TypeNameContext.class,0); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public ElementValuePairListContext elementValuePairList() { return getRuleContext(ElementValuePairListContext.class,0); } @@ -7984,6 +8177,10 @@ public class Java8Parser extends Parser { public ElementValuePairContext elementValuePair(int i) { return getRuleContext(ElementValuePairContext.class,i); } + public List COMMA() { return getTokens(Java8Parser.COMMA); } + public TerminalNode COMMA(int i) { + return getToken(Java8Parser.COMMA, i); + } public ElementValuePairListContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -8038,6 +8235,7 @@ public class Java8Parser extends Parser { public static class ElementValuePairContext extends ParserRuleContext { public TerminalNode Identifier() { return getToken(Java8Parser.Identifier, 0); } + public TerminalNode ASSIGN() { return getToken(Java8Parser.ASSIGN, 0); } public ElementValueContext elementValue() { return getRuleContext(ElementValueContext.class,0); } @@ -8146,9 +8344,12 @@ public class Java8Parser extends Parser { } public static class ElementValueArrayInitializerContext extends ParserRuleContext { + public TerminalNode LBRACE() { return getToken(Java8Parser.LBRACE, 0); } + public TerminalNode RBRACE() { return getToken(Java8Parser.RBRACE, 0); } public ElementValueListContext elementValueList() { return getRuleContext(ElementValueListContext.class,0); } + public TerminalNode COMMA() { return getToken(Java8Parser.COMMA, 0); } public ElementValueArrayInitializerContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -8214,6 +8415,10 @@ public class Java8Parser extends Parser { public ElementValueContext elementValue(int i) { return getRuleContext(ElementValueContext.class,i); } + public List COMMA() { return getTokens(Java8Parser.COMMA); } + public TerminalNode COMMA(int i) { + return getToken(Java8Parser.COMMA, i); + } public ElementValueListContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -8240,7 +8445,7 @@ public class Java8Parser extends Parser { setState(1467); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,152,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { @@ -8269,6 +8474,7 @@ public class Java8Parser extends Parser { } public static class MarkerAnnotationContext extends ParserRuleContext { + public TerminalNode AT() { return getToken(Java8Parser.AT, 0); } public TypeNameContext typeName() { return getRuleContext(TypeNameContext.class,0); } @@ -8310,12 +8516,15 @@ public class Java8Parser extends Parser { } public static class SingleElementAnnotationContext extends ParserRuleContext { + public TerminalNode AT() { return getToken(Java8Parser.AT, 0); } public TypeNameContext typeName() { return getRuleContext(TypeNameContext.class,0); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } public ElementValueContext elementValue() { return getRuleContext(ElementValueContext.class,0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public SingleElementAnnotationContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -8360,9 +8569,12 @@ public class Java8Parser extends Parser { } public static class ArrayInitializerContext extends ParserRuleContext { + public TerminalNode LBRACE() { return getToken(Java8Parser.LBRACE, 0); } + public TerminalNode RBRACE() { return getToken(Java8Parser.RBRACE, 0); } public VariableInitializerListContext variableInitializerList() { return getRuleContext(VariableInitializerListContext.class,0); } + public TerminalNode COMMA() { return getToken(Java8Parser.COMMA, 0); } public ArrayInitializerContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -8428,6 +8640,10 @@ public class Java8Parser extends Parser { public VariableInitializerContext variableInitializer(int i) { return getRuleContext(VariableInitializerContext.class,i); } + public List COMMA() { return getTokens(Java8Parser.COMMA); } + public TerminalNode COMMA(int i) { + return getToken(Java8Parser.COMMA, i); + } public VariableInitializerListContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -8454,7 +8670,7 @@ public class Java8Parser extends Parser { setState(1493); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,155,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { @@ -8483,6 +8699,8 @@ public class Java8Parser extends Parser { } public static class BlockContext extends ParserRuleContext { + public TerminalNode LBRACE() { return getToken(Java8Parser.LBRACE, 0); } + public TerminalNode RBRACE() { return getToken(Java8Parser.RBRACE, 0); } public BlockStatementsContext blockStatements() { return getRuleContext(BlockStatementsContext.class,0); } @@ -8660,6 +8878,7 @@ public class Java8Parser extends Parser { public LocalVariableDeclarationContext localVariableDeclaration() { return getRuleContext(LocalVariableDeclarationContext.class,0); } + public TerminalNode SEMI() { return getToken(Java8Parser.SEMI, 0); } public LocalVariableDeclarationStatementContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -9184,6 +9403,7 @@ public class Java8Parser extends Parser { } public static class EmptyStatementContext extends ParserRuleContext { + public TerminalNode SEMI() { return getToken(Java8Parser.SEMI, 0); } public EmptyStatementContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -9221,6 +9441,7 @@ public class Java8Parser extends Parser { public static class LabeledStatementContext extends ParserRuleContext { public TerminalNode Identifier() { return getToken(Java8Parser.Identifier, 0); } + public TerminalNode COLON() { return getToken(Java8Parser.COLON, 0); } public StatementContext statement() { return getRuleContext(StatementContext.class,0); } @@ -9265,6 +9486,7 @@ public class Java8Parser extends Parser { public static class LabeledStatementNoShortIfContext extends ParserRuleContext { public TerminalNode Identifier() { return getToken(Java8Parser.Identifier, 0); } + public TerminalNode COLON() { return getToken(Java8Parser.COLON, 0); } public StatementNoShortIfContext statementNoShortIf() { return getRuleContext(StatementNoShortIfContext.class,0); } @@ -9311,6 +9533,7 @@ public class Java8Parser extends Parser { public StatementExpressionContext statementExpression() { return getRuleContext(StatementExpressionContext.class,0); } + public TerminalNode SEMI() { return getToken(Java8Parser.SEMI, 0); } public ExpressionStatementContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -9454,9 +9677,12 @@ public class Java8Parser extends Parser { } public static class IfThenStatementContext extends ParserRuleContext { + public TerminalNode IF() { return getToken(Java8Parser.IF, 0); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } public ExpressionContext expression() { return getRuleContext(ExpressionContext.class,0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public StatementContext statement() { return getRuleContext(StatementContext.class,0); } @@ -9504,12 +9730,16 @@ public class Java8Parser extends Parser { } public static class IfThenElseStatementContext extends ParserRuleContext { + public TerminalNode IF() { return getToken(Java8Parser.IF, 0); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } public ExpressionContext expression() { return getRuleContext(ExpressionContext.class,0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public StatementNoShortIfContext statementNoShortIf() { return getRuleContext(StatementNoShortIfContext.class,0); } + public TerminalNode ELSE() { return getToken(Java8Parser.ELSE, 0); } public StatementContext statement() { return getRuleContext(StatementContext.class,0); } @@ -9561,15 +9791,19 @@ public class Java8Parser extends Parser { } public static class IfThenElseStatementNoShortIfContext extends ParserRuleContext { + public TerminalNode IF() { return getToken(Java8Parser.IF, 0); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } public ExpressionContext expression() { return getRuleContext(ExpressionContext.class,0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public List statementNoShortIf() { return getRuleContexts(StatementNoShortIfContext.class); } public StatementNoShortIfContext statementNoShortIf(int i) { return getRuleContext(StatementNoShortIfContext.class,i); } + public TerminalNode ELSE() { return getToken(Java8Parser.ELSE, 0); } public IfThenElseStatementNoShortIfContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -9618,12 +9852,15 @@ public class Java8Parser extends Parser { } public static class AssertStatementContext extends ParserRuleContext { + public TerminalNode ASSERT() { return getToken(Java8Parser.ASSERT, 0); } public List expression() { return getRuleContexts(ExpressionContext.class); } public ExpressionContext expression(int i) { return getRuleContext(ExpressionContext.class,i); } + public TerminalNode SEMI() { return getToken(Java8Parser.SEMI, 0); } + public TerminalNode COLON() { return getToken(Java8Parser.COLON, 0); } public AssertStatementContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -9685,9 +9922,12 @@ public class Java8Parser extends Parser { } public static class SwitchStatementContext extends ParserRuleContext { + public TerminalNode SWITCH() { return getToken(Java8Parser.SWITCH, 0); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } public ExpressionContext expression() { return getRuleContext(ExpressionContext.class,0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public SwitchBlockContext switchBlock() { return getRuleContext(SwitchBlockContext.class,0); } @@ -9735,6 +9975,8 @@ public class Java8Parser extends Parser { } public static class SwitchBlockContext extends ParserRuleContext { + public TerminalNode LBRACE() { return getToken(Java8Parser.LBRACE, 0); } + public TerminalNode RBRACE() { return getToken(Java8Parser.RBRACE, 0); } public List switchBlockStatementGroup() { return getRuleContexts(SwitchBlockStatementGroupContext.class); } @@ -9774,7 +10016,7 @@ public class Java8Parser extends Parser { setState(1625); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,166,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { @@ -9918,12 +10160,15 @@ public class Java8Parser extends Parser { } public static class SwitchLabelContext extends ParserRuleContext { + public TerminalNode CASE() { return getToken(Java8Parser.CASE, 0); } public ConstantExpressionContext constantExpression() { return getRuleContext(ConstantExpressionContext.class,0); } + public TerminalNode COLON() { return getToken(Java8Parser.COLON, 0); } public EnumConstantNameContext enumConstantName() { return getRuleContext(EnumConstantNameContext.class,0); } + public TerminalNode DEFAULT() { return getToken(Java8Parser.DEFAULT, 0); } public SwitchLabelContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -10027,9 +10272,12 @@ public class Java8Parser extends Parser { } public static class WhileStatementContext extends ParserRuleContext { + public TerminalNode WHILE() { return getToken(Java8Parser.WHILE, 0); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } public ExpressionContext expression() { return getRuleContext(ExpressionContext.class,0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public StatementContext statement() { return getRuleContext(StatementContext.class,0); } @@ -10077,9 +10325,12 @@ public class Java8Parser extends Parser { } public static class WhileStatementNoShortIfContext extends ParserRuleContext { + public TerminalNode WHILE() { return getToken(Java8Parser.WHILE, 0); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } public ExpressionContext expression() { return getRuleContext(ExpressionContext.class,0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public StatementNoShortIfContext statementNoShortIf() { return getRuleContext(StatementNoShortIfContext.class,0); } @@ -10127,12 +10378,17 @@ public class Java8Parser extends Parser { } public static class DoStatementContext extends ParserRuleContext { + public TerminalNode DO() { return getToken(Java8Parser.DO, 0); } public StatementContext statement() { return getRuleContext(StatementContext.class,0); } + public TerminalNode WHILE() { return getToken(Java8Parser.WHILE, 0); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } public ExpressionContext expression() { return getRuleContext(ExpressionContext.class,0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } + public TerminalNode SEMI() { return getToken(Java8Parser.SEMI, 0); } public DoStatementContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -10291,6 +10547,13 @@ public class Java8Parser extends Parser { } public static class BasicForStatementContext extends ParserRuleContext { + public TerminalNode FOR() { return getToken(Java8Parser.FOR, 0); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } + public List SEMI() { return getTokens(Java8Parser.SEMI); } + public TerminalNode SEMI(int i) { + return getToken(Java8Parser.SEMI, i); + } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public StatementContext statement() { return getRuleContext(StatementContext.class,0); } @@ -10380,6 +10643,13 @@ public class Java8Parser extends Parser { } public static class BasicForStatementNoShortIfContext extends ParserRuleContext { + public TerminalNode FOR() { return getToken(Java8Parser.FOR, 0); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } + public List SEMI() { return getTokens(Java8Parser.SEMI); } + public TerminalNode SEMI(int i) { + return getToken(Java8Parser.SEMI, i); + } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public StatementNoShortIfContext statementNoShortIf() { return getRuleContext(StatementNoShortIfContext.class,0); } @@ -10569,6 +10839,10 @@ public class Java8Parser extends Parser { public StatementExpressionContext statementExpression(int i) { return getRuleContext(StatementExpressionContext.class,i); } + public List COMMA() { return getTokens(Java8Parser.COMMA); } + public TerminalNode COMMA(int i) { + return getToken(Java8Parser.COMMA, i); + } public StatementExpressionListContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -10622,15 +10896,19 @@ public class Java8Parser extends Parser { } public static class EnhancedForStatementContext extends ParserRuleContext { + public TerminalNode FOR() { return getToken(Java8Parser.FOR, 0); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } public UnannTypeContext unannType() { return getRuleContext(UnannTypeContext.class,0); } public VariableDeclaratorIdContext variableDeclaratorId() { return getRuleContext(VariableDeclaratorIdContext.class,0); } + public TerminalNode COLON() { return getToken(Java8Parser.COLON, 0); } public ExpressionContext expression() { return getRuleContext(ExpressionContext.class,0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public StatementContext statement() { return getRuleContext(StatementContext.class,0); } @@ -10705,15 +10983,19 @@ public class Java8Parser extends Parser { } public static class EnhancedForStatementNoShortIfContext extends ParserRuleContext { + public TerminalNode FOR() { return getToken(Java8Parser.FOR, 0); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } public UnannTypeContext unannType() { return getRuleContext(UnannTypeContext.class,0); } public VariableDeclaratorIdContext variableDeclaratorId() { return getRuleContext(VariableDeclaratorIdContext.class,0); } + public TerminalNode COLON() { return getToken(Java8Parser.COLON, 0); } public ExpressionContext expression() { return getRuleContext(ExpressionContext.class,0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public StatementNoShortIfContext statementNoShortIf() { return getRuleContext(StatementNoShortIfContext.class,0); } @@ -10788,6 +11070,8 @@ public class Java8Parser extends Parser { } public static class BreakStatementContext extends ParserRuleContext { + public TerminalNode BREAK() { return getToken(Java8Parser.BREAK, 0); } + public TerminalNode SEMI() { return getToken(Java8Parser.SEMI, 0); } public TerminalNode Identifier() { return getToken(Java8Parser.Identifier, 0); } public BreakStatementContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); @@ -10838,6 +11122,8 @@ public class Java8Parser extends Parser { } public static class ContinueStatementContext extends ParserRuleContext { + public TerminalNode CONTINUE() { return getToken(Java8Parser.CONTINUE, 0); } + public TerminalNode SEMI() { return getToken(Java8Parser.SEMI, 0); } public TerminalNode Identifier() { return getToken(Java8Parser.Identifier, 0); } public ContinueStatementContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); @@ -10888,6 +11174,8 @@ public class Java8Parser extends Parser { } public static class ReturnStatementContext extends ParserRuleContext { + public TerminalNode RETURN() { return getToken(Java8Parser.RETURN, 0); } + public TerminalNode SEMI() { return getToken(Java8Parser.SEMI, 0); } public ExpressionContext expression() { return getRuleContext(ExpressionContext.class,0); } @@ -10940,9 +11228,11 @@ public class Java8Parser extends Parser { } public static class ThrowStatementContext extends ParserRuleContext { + public TerminalNode THROW() { return getToken(Java8Parser.THROW, 0); } public ExpressionContext expression() { return getRuleContext(ExpressionContext.class,0); } + public TerminalNode SEMI() { return getToken(Java8Parser.SEMI, 0); } public ThrowStatementContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -10983,9 +11273,12 @@ public class Java8Parser extends Parser { } public static class SynchronizedStatementContext extends ParserRuleContext { + public TerminalNode SYNCHRONIZED() { return getToken(Java8Parser.SYNCHRONIZED, 0); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } public ExpressionContext expression() { return getRuleContext(ExpressionContext.class,0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public BlockContext block() { return getRuleContext(BlockContext.class,0); } @@ -11033,6 +11326,7 @@ public class Java8Parser extends Parser { } public static class TryStatementContext extends ParserRuleContext { + public TerminalNode TRY() { return getToken(Java8Parser.TRY, 0); } public BlockContext block() { return getRuleContext(BlockContext.class,0); } @@ -11177,9 +11471,12 @@ public class Java8Parser extends Parser { } public static class CatchClauseContext extends ParserRuleContext { + public TerminalNode CATCH() { return getToken(Java8Parser.CATCH, 0); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } public CatchFormalParameterContext catchFormalParameter() { return getRuleContext(CatchFormalParameterContext.class,0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public BlockContext block() { return getRuleContext(BlockContext.class,0); } @@ -11295,6 +11592,10 @@ public class Java8Parser extends Parser { public UnannClassTypeContext unannClassType() { return getRuleContext(UnannClassTypeContext.class,0); } + public List BITOR() { return getTokens(Java8Parser.BITOR); } + public TerminalNode BITOR(int i) { + return getToken(Java8Parser.BITOR, i); + } public List classType() { return getRuleContexts(ClassTypeContext.class); } @@ -11354,6 +11655,7 @@ public class Java8Parser extends Parser { } public static class Finally_Context extends ParserRuleContext { + public TerminalNode FINALLY() { return getToken(Java8Parser.FINALLY, 0); } public BlockContext block() { return getRuleContext(BlockContext.class,0); } @@ -11395,6 +11697,7 @@ public class Java8Parser extends Parser { } public static class TryWithResourcesStatementContext extends ParserRuleContext { + public TerminalNode TRY() { return getToken(Java8Parser.TRY, 0); } public ResourceSpecificationContext resourceSpecification() { return getRuleContext(ResourceSpecificationContext.class,0); } @@ -11468,9 +11771,12 @@ public class Java8Parser extends Parser { } public static class ResourceSpecificationContext extends ParserRuleContext { + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } public ResourceListContext resourceList() { return getRuleContext(ResourceListContext.class,0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } + public TerminalNode SEMI() { return getToken(Java8Parser.SEMI, 0); } public ResourceSpecificationContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -11528,6 +11834,10 @@ public class Java8Parser extends Parser { public ResourceContext resource(int i) { return getRuleContext(ResourceContext.class,i); } + public List SEMI() { return getTokens(Java8Parser.SEMI); } + public TerminalNode SEMI(int i) { + return getToken(Java8Parser.SEMI, i); + } public ResourceListContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -11554,7 +11864,7 @@ public class Java8Parser extends Parser { setState(1860); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,193,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { @@ -11589,6 +11899,7 @@ public class Java8Parser extends Parser { public VariableDeclaratorIdContext variableDeclaratorId() { return getRuleContext(VariableDeclaratorIdContext.class,0); } + public TerminalNode ASSIGN() { return getToken(Java8Parser.ASSIGN, 0); } public ExpressionContext expression() { return getRuleContext(ExpressionContext.class,0); } @@ -11707,7 +12018,7 @@ public class Java8Parser extends Parser { setState(1881); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,196,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { @@ -11740,9 +12051,23 @@ public class Java8Parser extends Parser { public TypeNameContext typeName() { return getRuleContext(TypeNameContext.class,0); } + public TerminalNode DOT() { return getToken(Java8Parser.DOT, 0); } + public TerminalNode CLASS() { return getToken(Java8Parser.CLASS, 0); } + public List LBRACK() { return getTokens(Java8Parser.LBRACK); } + public TerminalNode LBRACK(int i) { + return getToken(Java8Parser.LBRACK, i); + } + public List RBRACK() { return getTokens(Java8Parser.RBRACK); } + public TerminalNode RBRACK(int i) { + return getToken(Java8Parser.RBRACK, i); + } + public TerminalNode VOID() { return getToken(Java8Parser.VOID, 0); } + public TerminalNode THIS() { return getToken(Java8Parser.THIS, 0); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } public ExpressionContext expression() { return getRuleContext(ExpressionContext.class,0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public ClassInstanceCreationExpressionContext classInstanceCreationExpression() { return getRuleContext(ClassInstanceCreationExpressionContext.class,0); } @@ -11943,9 +12268,23 @@ public class Java8Parser extends Parser { public TypeNameContext typeName() { return getRuleContext(TypeNameContext.class,0); } + public TerminalNode DOT() { return getToken(Java8Parser.DOT, 0); } + public TerminalNode CLASS() { return getToken(Java8Parser.CLASS, 0); } + public List LBRACK() { return getTokens(Java8Parser.LBRACK); } + public TerminalNode LBRACK(int i) { + return getToken(Java8Parser.LBRACK, i); + } + public List RBRACK() { return getTokens(Java8Parser.RBRACK); } + public TerminalNode RBRACK(int i) { + return getToken(Java8Parser.RBRACK, i); + } + public TerminalNode VOID() { return getToken(Java8Parser.VOID, 0); } + public TerminalNode THIS() { return getToken(Java8Parser.THIS, 0); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } public ExpressionContext expression() { return getRuleContext(ExpressionContext.class,0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public ClassInstanceCreationExpressionContext classInstanceCreationExpression() { return getRuleContext(ClassInstanceCreationExpressionContext.class,0); } @@ -12296,12 +12635,26 @@ public class Java8Parser extends Parser { public TypeNameContext typeName() { return getRuleContext(TypeNameContext.class,0); } + public TerminalNode DOT() { return getToken(Java8Parser.DOT, 0); } + public TerminalNode CLASS() { return getToken(Java8Parser.CLASS, 0); } + public List LBRACK() { return getTokens(Java8Parser.LBRACK); } + public TerminalNode LBRACK(int i) { + return getToken(Java8Parser.LBRACK, i); + } + public List RBRACK() { return getTokens(Java8Parser.RBRACK); } + public TerminalNode RBRACK(int i) { + return getToken(Java8Parser.RBRACK, i); + } public UnannPrimitiveTypeContext unannPrimitiveType() { return getRuleContext(UnannPrimitiveTypeContext.class,0); } + public TerminalNode VOID() { return getToken(Java8Parser.VOID, 0); } + public TerminalNode THIS() { return getToken(Java8Parser.THIS, 0); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } public ExpressionContext expression() { return getRuleContext(ExpressionContext.class,0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public ClassInstanceCreationExpression_lfno_primaryContext classInstanceCreationExpression_lfno_primary() { return getRuleContext(ClassInstanceCreationExpression_lfno_primaryContext.class,0); } @@ -12529,12 +12882,26 @@ public class Java8Parser extends Parser { public TypeNameContext typeName() { return getRuleContext(TypeNameContext.class,0); } + public TerminalNode DOT() { return getToken(Java8Parser.DOT, 0); } + public TerminalNode CLASS() { return getToken(Java8Parser.CLASS, 0); } + public List LBRACK() { return getTokens(Java8Parser.LBRACK); } + public TerminalNode LBRACK(int i) { + return getToken(Java8Parser.LBRACK, i); + } + public List RBRACK() { return getTokens(Java8Parser.RBRACK); } + public TerminalNode RBRACK(int i) { + return getToken(Java8Parser.RBRACK, i); + } public UnannPrimitiveTypeContext unannPrimitiveType() { return getRuleContext(UnannPrimitiveTypeContext.class,0); } + public TerminalNode VOID() { return getToken(Java8Parser.VOID, 0); } + public TerminalNode THIS() { return getToken(Java8Parser.THIS, 0); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } public ExpressionContext expression() { return getRuleContext(ExpressionContext.class,0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public ClassInstanceCreationExpression_lfno_primaryContext classInstanceCreationExpression_lfno_primary() { return getRuleContext(ClassInstanceCreationExpression_lfno_primaryContext.class,0); } @@ -12712,10 +13079,13 @@ public class Java8Parser extends Parser { } public static class ClassInstanceCreationExpressionContext extends ParserRuleContext { + public TerminalNode NEW() { return getToken(Java8Parser.NEW, 0); } public List Identifier() { return getTokens(Java8Parser.Identifier); } public TerminalNode Identifier(int i) { return getToken(Java8Parser.Identifier, i); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public TypeArgumentsContext typeArguments() { return getRuleContext(TypeArgumentsContext.class,0); } @@ -12725,6 +13095,10 @@ public class Java8Parser extends Parser { public AnnotationContext annotation(int i) { return getRuleContext(AnnotationContext.class,i); } + public List DOT() { return getTokens(Java8Parser.DOT); } + public TerminalNode DOT(int i) { + return getToken(Java8Parser.DOT, i); + } public TypeArgumentsOrDiamondContext typeArgumentsOrDiamond() { return getRuleContext(TypeArgumentsOrDiamondContext.class,0); } @@ -13015,7 +13389,11 @@ public class Java8Parser extends Parser { } public static class ClassInstanceCreationExpression_lf_primaryContext extends ParserRuleContext { + public TerminalNode DOT() { return getToken(Java8Parser.DOT, 0); } + public TerminalNode NEW() { return getToken(Java8Parser.NEW, 0); } public TerminalNode Identifier() { return getToken(Java8Parser.Identifier, 0); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public TypeArgumentsContext typeArguments() { return getRuleContext(TypeArgumentsContext.class,0); } @@ -13133,10 +13511,13 @@ public class Java8Parser extends Parser { } public static class ClassInstanceCreationExpression_lfno_primaryContext extends ParserRuleContext { + public TerminalNode NEW() { return getToken(Java8Parser.NEW, 0); } public List Identifier() { return getTokens(Java8Parser.Identifier); } public TerminalNode Identifier(int i) { return getToken(Java8Parser.Identifier, i); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public TypeArgumentsContext typeArguments() { return getRuleContext(TypeArgumentsContext.class,0); } @@ -13146,6 +13527,10 @@ public class Java8Parser extends Parser { public AnnotationContext annotation(int i) { return getRuleContext(AnnotationContext.class,i); } + public List DOT() { return getTokens(Java8Parser.DOT); } + public TerminalNode DOT(int i) { + return getToken(Java8Parser.DOT, i); + } public TypeArgumentsOrDiamondContext typeArgumentsOrDiamond() { return getRuleContext(TypeArgumentsOrDiamondContext.class,0); } @@ -13367,6 +13752,8 @@ public class Java8Parser extends Parser { public TypeArgumentsContext typeArguments() { return getRuleContext(TypeArgumentsContext.class,0); } + public TerminalNode LT() { return getToken(Java8Parser.LT, 0); } + public TerminalNode GT() { return getToken(Java8Parser.GT, 0); } public TypeArgumentsOrDiamondContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -13421,7 +13808,12 @@ public class Java8Parser extends Parser { public PrimaryContext primary() { return getRuleContext(PrimaryContext.class,0); } + public List DOT() { return getTokens(Java8Parser.DOT); } + public TerminalNode DOT(int i) { + return getToken(Java8Parser.DOT, i); + } public TerminalNode Identifier() { return getToken(Java8Parser.Identifier, 0); } + public TerminalNode SUPER() { return getToken(Java8Parser.SUPER, 0); } public TypeNameContext typeName() { return getRuleContext(TypeNameContext.class,0); } @@ -13497,6 +13889,7 @@ public class Java8Parser extends Parser { } public static class FieldAccess_lf_primaryContext extends ParserRuleContext { + public TerminalNode DOT() { return getToken(Java8Parser.DOT, 0); } public TerminalNode Identifier() { return getToken(Java8Parser.Identifier, 0); } public FieldAccess_lf_primaryContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); @@ -13536,6 +13929,11 @@ public class Java8Parser extends Parser { } public static class FieldAccess_lfno_primaryContext extends ParserRuleContext { + public TerminalNode SUPER() { return getToken(Java8Parser.SUPER, 0); } + public List DOT() { return getTokens(Java8Parser.DOT); } + public TerminalNode DOT(int i) { + return getToken(Java8Parser.DOT, i); + } public TerminalNode Identifier() { return getToken(Java8Parser.Identifier, 0); } public TypeNameContext typeName() { return getRuleContext(TypeNameContext.class,0); @@ -13606,12 +14004,20 @@ public class Java8Parser extends Parser { public ExpressionNameContext expressionName() { return getRuleContext(ExpressionNameContext.class,0); } + public List LBRACK() { return getTokens(Java8Parser.LBRACK); } + public TerminalNode LBRACK(int i) { + return getToken(Java8Parser.LBRACK, i); + } public List expression() { return getRuleContexts(ExpressionContext.class); } public ExpressionContext expression(int i) { return getRuleContext(ExpressionContext.class,i); } + public List RBRACK() { return getTokens(Java8Parser.RBRACK); } + public TerminalNode RBRACK(int i) { + return getToken(Java8Parser.RBRACK, i); + } public PrimaryNoNewArray_lfno_arrayAccessContext primaryNoNewArray_lfno_arrayAccess() { return getRuleContext(PrimaryNoNewArray_lfno_arrayAccessContext.class,0); } @@ -13707,12 +14113,20 @@ public class Java8Parser extends Parser { public PrimaryNoNewArray_lf_primary_lfno_arrayAccess_lf_primaryContext primaryNoNewArray_lf_primary_lfno_arrayAccess_lf_primary() { return getRuleContext(PrimaryNoNewArray_lf_primary_lfno_arrayAccess_lf_primaryContext.class,0); } + public List LBRACK() { return getTokens(Java8Parser.LBRACK); } + public TerminalNode LBRACK(int i) { + return getToken(Java8Parser.LBRACK, i); + } public List expression() { return getRuleContexts(ExpressionContext.class); } public ExpressionContext expression(int i) { return getRuleContext(ExpressionContext.class,i); } + public List RBRACK() { return getTokens(Java8Parser.RBRACK); } + public TerminalNode RBRACK(int i) { + return getToken(Java8Parser.RBRACK, i); + } public List primaryNoNewArray_lf_primary_lf_arrayAccess_lf_primary() { return getRuleContexts(PrimaryNoNewArray_lf_primary_lf_arrayAccess_lf_primaryContext.class); } @@ -13753,7 +14167,7 @@ public class Java8Parser extends Parser { setState(2284); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,250,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { @@ -13789,12 +14203,20 @@ public class Java8Parser extends Parser { public ExpressionNameContext expressionName() { return getRuleContext(ExpressionNameContext.class,0); } + public List LBRACK() { return getTokens(Java8Parser.LBRACK); } + public TerminalNode LBRACK(int i) { + return getToken(Java8Parser.LBRACK, i); + } public List expression() { return getRuleContexts(ExpressionContext.class); } public ExpressionContext expression(int i) { return getRuleContext(ExpressionContext.class,i); } + public List RBRACK() { return getTokens(Java8Parser.RBRACK); } + public TerminalNode RBRACK(int i) { + return getToken(Java8Parser.RBRACK, i); + } public PrimaryNoNewArray_lfno_primary_lfno_arrayAccess_lfno_primaryContext primaryNoNewArray_lfno_primary_lfno_arrayAccess_lfno_primary() { return getRuleContext(PrimaryNoNewArray_lfno_primary_lfno_arrayAccess_lfno_primaryContext.class,0); } @@ -13856,7 +14278,7 @@ public class Java8Parser extends Parser { setState(2306); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,252,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { @@ -13892,12 +14314,18 @@ public class Java8Parser extends Parser { public MethodNameContext methodName() { return getRuleContext(MethodNameContext.class,0); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public ArgumentListContext argumentList() { return getRuleContext(ArgumentListContext.class,0); } public TypeNameContext typeName() { return getRuleContext(TypeNameContext.class,0); } + public List DOT() { return getTokens(Java8Parser.DOT); } + public TerminalNode DOT(int i) { + return getToken(Java8Parser.DOT, i); + } public TerminalNode Identifier() { return getToken(Java8Parser.Identifier, 0); } public TypeArgumentsContext typeArguments() { return getRuleContext(TypeArgumentsContext.class,0); @@ -13908,6 +14336,7 @@ public class Java8Parser extends Parser { public PrimaryContext primary() { return getRuleContext(PrimaryContext.class,0); } + public TerminalNode SUPER() { return getToken(Java8Parser.SUPER, 0); } public MethodInvocationContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -14144,7 +14573,10 @@ public class Java8Parser extends Parser { } public static class MethodInvocation_lf_primaryContext extends ParserRuleContext { + public TerminalNode DOT() { return getToken(Java8Parser.DOT, 0); } public TerminalNode Identifier() { return getToken(Java8Parser.Identifier, 0); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public TypeArgumentsContext typeArguments() { return getRuleContext(TypeArgumentsContext.class,0); } @@ -14217,12 +14649,18 @@ public class Java8Parser extends Parser { public MethodNameContext methodName() { return getRuleContext(MethodNameContext.class,0); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public ArgumentListContext argumentList() { return getRuleContext(ArgumentListContext.class,0); } public TypeNameContext typeName() { return getRuleContext(TypeNameContext.class,0); } + public List DOT() { return getTokens(Java8Parser.DOT); } + public TerminalNode DOT(int i) { + return getToken(Java8Parser.DOT, i); + } public TerminalNode Identifier() { return getToken(Java8Parser.Identifier, 0); } public TypeArgumentsContext typeArguments() { return getRuleContext(TypeArgumentsContext.class,0); @@ -14230,6 +14668,7 @@ public class Java8Parser extends Parser { public ExpressionNameContext expressionName() { return getRuleContext(ExpressionNameContext.class,0); } + public TerminalNode SUPER() { return getToken(Java8Parser.SUPER, 0); } public MethodInvocation_lfno_primaryContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -14437,6 +14876,10 @@ public class Java8Parser extends Parser { public ExpressionContext expression(int i) { return getRuleContext(ExpressionContext.class,i); } + public List COMMA() { return getTokens(Java8Parser.COMMA); } + public TerminalNode COMMA(int i) { + return getToken(Java8Parser.COMMA, i); + } public ArgumentListContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -14493,6 +14936,7 @@ public class Java8Parser extends Parser { public ExpressionNameContext expressionName() { return getRuleContext(ExpressionNameContext.class,0); } + public TerminalNode COLONCOLON() { return getToken(Java8Parser.COLONCOLON, 0); } public TerminalNode Identifier() { return getToken(Java8Parser.Identifier, 0); } public TypeArgumentsContext typeArguments() { return getRuleContext(TypeArgumentsContext.class,0); @@ -14503,12 +14947,15 @@ public class Java8Parser extends Parser { public PrimaryContext primary() { return getRuleContext(PrimaryContext.class,0); } + public TerminalNode SUPER() { return getToken(Java8Parser.SUPER, 0); } public TypeNameContext typeName() { return getRuleContext(TypeNameContext.class,0); } + public TerminalNode DOT() { return getToken(Java8Parser.DOT, 0); } public ClassTypeContext classType() { return getRuleContext(ClassTypeContext.class,0); } + public TerminalNode NEW() { return getToken(Java8Parser.NEW, 0); } public ArrayTypeContext arrayType() { return getRuleContext(ArrayTypeContext.class,0); } @@ -14689,6 +15136,7 @@ public class Java8Parser extends Parser { } public static class MethodReference_lf_primaryContext extends ParserRuleContext { + public TerminalNode COLONCOLON() { return getToken(Java8Parser.COLONCOLON, 0); } public TerminalNode Identifier() { return getToken(Java8Parser.Identifier, 0); } public TypeArgumentsContext typeArguments() { return getRuleContext(TypeArgumentsContext.class,0); @@ -14745,6 +15193,7 @@ public class Java8Parser extends Parser { public ExpressionNameContext expressionName() { return getRuleContext(ExpressionNameContext.class,0); } + public TerminalNode COLONCOLON() { return getToken(Java8Parser.COLONCOLON, 0); } public TerminalNode Identifier() { return getToken(Java8Parser.Identifier, 0); } public TypeArgumentsContext typeArguments() { return getRuleContext(TypeArgumentsContext.class,0); @@ -14752,12 +15201,15 @@ public class Java8Parser extends Parser { public ReferenceTypeContext referenceType() { return getRuleContext(ReferenceTypeContext.class,0); } + public TerminalNode SUPER() { return getToken(Java8Parser.SUPER, 0); } public TypeNameContext typeName() { return getRuleContext(TypeNameContext.class,0); } + public TerminalNode DOT() { return getToken(Java8Parser.DOT, 0); } public ClassTypeContext classType() { return getRuleContext(ClassTypeContext.class,0); } + public TerminalNode NEW() { return getToken(Java8Parser.NEW, 0); } public ArrayTypeContext arrayType() { return getRuleContext(ArrayTypeContext.class,0); } @@ -14917,6 +15369,7 @@ public class Java8Parser extends Parser { } public static class ArrayCreationExpressionContext extends ParserRuleContext { + public TerminalNode NEW() { return getToken(Java8Parser.NEW, 0); } public PrimitiveTypeContext primitiveType() { return getRuleContext(PrimitiveTypeContext.class,0); } @@ -15067,7 +15520,7 @@ public class Java8Parser extends Parser { setState(2581); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,295,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { @@ -15094,9 +15547,11 @@ public class Java8Parser extends Parser { } public static class DimExprContext extends ParserRuleContext { + public TerminalNode LBRACK() { return getToken(Java8Parser.LBRACK, 0); } public ExpressionContext expression() { return getRuleContext(ExpressionContext.class,0); } + public TerminalNode RBRACK() { return getToken(Java8Parser.RBRACK, 0); } public List annotation() { return getRuleContexts(AnnotationContext.class); } @@ -15255,6 +15710,7 @@ public class Java8Parser extends Parser { public LambdaParametersContext lambdaParameters() { return getRuleContext(LambdaParametersContext.class,0); } + public TerminalNode ARROW() { return getToken(Java8Parser.ARROW, 0); } public LambdaBodyContext lambdaBody() { return getRuleContext(LambdaBodyContext.class,0); } @@ -15299,6 +15755,8 @@ public class Java8Parser extends Parser { public static class LambdaParametersContext extends ParserRuleContext { public TerminalNode Identifier() { return getToken(Java8Parser.Identifier, 0); } + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public FormalParameterListContext formalParameterList() { return getRuleContext(FormalParameterListContext.class,0); } @@ -15370,6 +15828,10 @@ public class Java8Parser extends Parser { public TerminalNode Identifier(int i) { return getToken(Java8Parser.Identifier, i); } + public List COMMA() { return getTokens(Java8Parser.COMMA); } + public TerminalNode COMMA(int i) { + return getToken(Java8Parser.COMMA, i); + } public InferredFormalParameterListContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -15675,6 +16137,18 @@ public class Java8Parser extends Parser { } public static class AssignmentOperatorContext extends ParserRuleContext { + public TerminalNode ASSIGN() { return getToken(Java8Parser.ASSIGN, 0); } + public TerminalNode MUL_ASSIGN() { return getToken(Java8Parser.MUL_ASSIGN, 0); } + public TerminalNode DIV_ASSIGN() { return getToken(Java8Parser.DIV_ASSIGN, 0); } + public TerminalNode MOD_ASSIGN() { return getToken(Java8Parser.MOD_ASSIGN, 0); } + public TerminalNode ADD_ASSIGN() { return getToken(Java8Parser.ADD_ASSIGN, 0); } + public TerminalNode SUB_ASSIGN() { return getToken(Java8Parser.SUB_ASSIGN, 0); } + public TerminalNode LSHIFT_ASSIGN() { return getToken(Java8Parser.LSHIFT_ASSIGN, 0); } + public TerminalNode RSHIFT_ASSIGN() { return getToken(Java8Parser.RSHIFT_ASSIGN, 0); } + public TerminalNode URSHIFT_ASSIGN() { return getToken(Java8Parser.URSHIFT_ASSIGN, 0); } + public TerminalNode AND_ASSIGN() { return getToken(Java8Parser.AND_ASSIGN, 0); } + public TerminalNode XOR_ASSIGN() { return getToken(Java8Parser.XOR_ASSIGN, 0); } + public TerminalNode OR_ASSIGN() { return getToken(Java8Parser.OR_ASSIGN, 0); } public AssignmentOperatorContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -15723,9 +16197,11 @@ public class Java8Parser extends Parser { public ConditionalOrExpressionContext conditionalOrExpression() { return getRuleContext(ConditionalOrExpressionContext.class,0); } + public TerminalNode QUESTION() { return getToken(Java8Parser.QUESTION, 0); } public ExpressionContext expression() { return getRuleContext(ExpressionContext.class,0); } + public TerminalNode COLON() { return getToken(Java8Parser.COLON, 0); } public ConditionalExpressionContext conditionalExpression() { return getRuleContext(ConditionalExpressionContext.class,0); } @@ -15792,6 +16268,7 @@ public class Java8Parser extends Parser { public ConditionalOrExpressionContext conditionalOrExpression() { return getRuleContext(ConditionalOrExpressionContext.class,0); } + public TerminalNode OR() { return getToken(Java8Parser.OR, 0); } public ConditionalOrExpressionContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -15829,7 +16306,7 @@ public class Java8Parser extends Parser { setState(2656); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,305,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; @@ -15870,6 +16347,7 @@ public class Java8Parser extends Parser { public ConditionalAndExpressionContext conditionalAndExpression() { return getRuleContext(ConditionalAndExpressionContext.class,0); } + public TerminalNode AND() { return getToken(Java8Parser.AND, 0); } public ConditionalAndExpressionContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -15907,7 +16385,7 @@ public class Java8Parser extends Parser { setState(2667); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,306,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; @@ -15948,6 +16426,7 @@ public class Java8Parser extends Parser { public InclusiveOrExpressionContext inclusiveOrExpression() { return getRuleContext(InclusiveOrExpressionContext.class,0); } + public TerminalNode BITOR() { return getToken(Java8Parser.BITOR, 0); } public InclusiveOrExpressionContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -15985,7 +16464,7 @@ public class Java8Parser extends Parser { setState(2678); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,307,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; @@ -16026,6 +16505,7 @@ public class Java8Parser extends Parser { public ExclusiveOrExpressionContext exclusiveOrExpression() { return getRuleContext(ExclusiveOrExpressionContext.class,0); } + public TerminalNode CARET() { return getToken(Java8Parser.CARET, 0); } public ExclusiveOrExpressionContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -16063,7 +16543,7 @@ public class Java8Parser extends Parser { setState(2689); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,308,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; @@ -16104,6 +16584,7 @@ public class Java8Parser extends Parser { public AndExpressionContext andExpression() { return getRuleContext(AndExpressionContext.class,0); } + public TerminalNode BITAND() { return getToken(Java8Parser.BITAND, 0); } public AndExpressionContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -16141,7 +16622,7 @@ public class Java8Parser extends Parser { setState(2700); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,309,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; @@ -16182,6 +16663,8 @@ public class Java8Parser extends Parser { public EqualityExpressionContext equalityExpression() { return getRuleContext(EqualityExpressionContext.class,0); } + public TerminalNode EQUAL() { return getToken(Java8Parser.EQUAL, 0); } + public TerminalNode NOTEQUAL() { return getToken(Java8Parser.NOTEQUAL, 0); } public EqualityExpressionContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -16219,7 +16702,7 @@ public class Java8Parser extends Parser { setState(2714); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,311,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; @@ -16278,6 +16761,11 @@ public class Java8Parser extends Parser { public RelationalExpressionContext relationalExpression() { return getRuleContext(RelationalExpressionContext.class,0); } + public TerminalNode LT() { return getToken(Java8Parser.LT, 0); } + public TerminalNode GT() { return getToken(Java8Parser.GT, 0); } + public TerminalNode LE() { return getToken(Java8Parser.LE, 0); } + public TerminalNode GE() { return getToken(Java8Parser.GE, 0); } + public TerminalNode INSTANCEOF() { return getToken(Java8Parser.INSTANCEOF, 0); } public ReferenceTypeContext referenceType() { return getRuleContext(ReferenceTypeContext.class,0); } @@ -16318,7 +16806,7 @@ public class Java8Parser extends Parser { setState(2737); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,313,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; @@ -16413,6 +16901,14 @@ public class Java8Parser extends Parser { public ShiftExpressionContext shiftExpression() { return getRuleContext(ShiftExpressionContext.class,0); } + public List LT() { return getTokens(Java8Parser.LT); } + public TerminalNode LT(int i) { + return getToken(Java8Parser.LT, i); + } + public List GT() { return getTokens(Java8Parser.GT); } + public TerminalNode GT(int i) { + return getToken(Java8Parser.GT, i); + } public ShiftExpressionContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -16450,7 +16946,7 @@ public class Java8Parser extends Parser { setState(2758); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,315,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; @@ -16529,6 +17025,8 @@ public class Java8Parser extends Parser { public AdditiveExpressionContext additiveExpression() { return getRuleContext(AdditiveExpressionContext.class,0); } + public TerminalNode ADD() { return getToken(Java8Parser.ADD, 0); } + public TerminalNode SUB() { return getToken(Java8Parser.SUB, 0); } public AdditiveExpressionContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -16566,7 +17064,7 @@ public class Java8Parser extends Parser { setState(2772); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,317,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; @@ -16625,6 +17123,9 @@ public class Java8Parser extends Parser { public MultiplicativeExpressionContext multiplicativeExpression() { return getRuleContext(MultiplicativeExpressionContext.class,0); } + public TerminalNode MUL() { return getToken(Java8Parser.MUL, 0); } + public TerminalNode DIV() { return getToken(Java8Parser.DIV, 0); } + public TerminalNode MOD() { return getToken(Java8Parser.MOD, 0); } public MultiplicativeExpressionContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -16662,7 +17163,7 @@ public class Java8Parser extends Parser { setState(2789); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,319,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; @@ -16733,9 +17234,11 @@ public class Java8Parser extends Parser { public PreDecrementExpressionContext preDecrementExpression() { return getRuleContext(PreDecrementExpressionContext.class,0); } + public TerminalNode ADD() { return getToken(Java8Parser.ADD, 0); } public UnaryExpressionContext unaryExpression() { return getRuleContext(UnaryExpressionContext.class,0); } + public TerminalNode SUB() { return getToken(Java8Parser.SUB, 0); } public UnaryExpressionNotPlusMinusContext unaryExpressionNotPlusMinus() { return getRuleContext(UnaryExpressionNotPlusMinusContext.class,0); } @@ -16837,6 +17340,7 @@ public class Java8Parser extends Parser { } public static class PreIncrementExpressionContext extends ParserRuleContext { + public TerminalNode INC() { return getToken(Java8Parser.INC, 0); } public UnaryExpressionContext unaryExpression() { return getRuleContext(UnaryExpressionContext.class,0); } @@ -16878,6 +17382,7 @@ public class Java8Parser extends Parser { } public static class PreDecrementExpressionContext extends ParserRuleContext { + public TerminalNode DEC() { return getToken(Java8Parser.DEC, 0); } public UnaryExpressionContext unaryExpression() { return getRuleContext(UnaryExpressionContext.class,0); } @@ -16922,9 +17427,11 @@ public class Java8Parser extends Parser { public PostfixExpressionContext postfixExpression() { return getRuleContext(PostfixExpressionContext.class,0); } + public TerminalNode TILDE() { return getToken(Java8Parser.TILDE, 0); } public UnaryExpressionContext unaryExpression() { return getRuleContext(UnaryExpressionContext.class,0); } + public TerminalNode BANG() { return getToken(Java8Parser.BANG, 0); } public CastExpressionContext castExpression() { return getRuleContext(CastExpressionContext.class,0); } @@ -17053,7 +17560,7 @@ public class Java8Parser extends Parser { setState(2823); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,324,_ctx); - while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { setState(2821); @@ -17097,6 +17604,7 @@ public class Java8Parser extends Parser { public PostfixExpressionContext postfixExpression() { return getRuleContext(PostfixExpressionContext.class,0); } + public TerminalNode INC() { return getToken(Java8Parser.INC, 0); } public PostIncrementExpressionContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -17135,6 +17643,7 @@ public class Java8Parser extends Parser { } public static class PostIncrementExpression_lf_postfixExpressionContext extends ParserRuleContext { + public TerminalNode INC() { return getToken(Java8Parser.INC, 0); } public PostIncrementExpression_lf_postfixExpressionContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -17174,6 +17683,7 @@ public class Java8Parser extends Parser { public PostfixExpressionContext postfixExpression() { return getRuleContext(PostfixExpressionContext.class,0); } + public TerminalNode DEC() { return getToken(Java8Parser.DEC, 0); } public PostDecrementExpressionContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -17212,6 +17722,7 @@ public class Java8Parser extends Parser { } public static class PostDecrementExpression_lf_postfixExpressionContext extends ParserRuleContext { + public TerminalNode DEC() { return getToken(Java8Parser.DEC, 0); } public PostDecrementExpression_lf_postfixExpressionContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -17248,9 +17759,11 @@ public class Java8Parser extends Parser { } public static class CastExpressionContext extends ParserRuleContext { + public TerminalNode LPAREN() { return getToken(Java8Parser.LPAREN, 0); } public PrimitiveTypeContext primitiveType() { return getRuleContext(PrimitiveTypeContext.class,0); } + public TerminalNode RPAREN() { return getToken(Java8Parser.RPAREN, 0); } public UnaryExpressionContext unaryExpression() { return getRuleContext(UnaryExpressionContext.class,0); } diff --git a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java index cbc35ad7..c7b74331 100755 --- a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java @@ -1,5 +1,6 @@ package de.dhbwstuttgart.target.bytecode; +import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.target.tree.*; import de.dhbwstuttgart.target.tree.expression.*; import de.dhbwstuttgart.target.tree.type.TargetFunNType; @@ -517,6 +518,11 @@ public class Codegen { } } + private void generateUnaryOp(State state, TargetUnaryOp op) { + // TODO + throw new NotImplementedException(); + } + private void generateLambdaExpression(State state, TargetLambdaExpression lambda) { var mv = state.mv; var name = "lambda$" + state.lambdaCounter; @@ -618,6 +624,9 @@ public class Codegen { case TargetBinaryOp op: generateBinaryOp(state, op); break; + case TargetUnaryOp op: + generateUnaryOp(state, op); + break; case TargetAssign assign: { switch (assign.left()) { case TargetLocalVar localVar: { diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index 23f04d2b..da917783 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -6,63 +6,75 @@ import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.Field; import de.dhbwstuttgart.syntaxtree.Method; 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 java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class ASTToTargetAST { - public TargetClass convert(ClassOrInterface input, ResultSet resultSet){ - throw new NotImplementedException(); + protected HashMap sigma; + + public ASTToTargetAST(ResultSet resultSet) { + this.sigma = new HashMap<>(); } - public TargetClass convert(ClassOrInterface input, Map sigma){ + 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(it, sigma)).collect(Collectors.toList()), - input.getMethods().stream().map(it -> convert(it, sigma)).collect(Collectors.toList())); + input.getFieldDecl().stream().map(it -> convert(it)).collect(Collectors.toList()), + input.getMethods().stream().map(it -> convert(input, it)).collect(Collectors.toList())); } - private TargetMethod convert(Method input, Map sigma) { + private TargetMethod convert(ClassOrInterface owner, Method input) { List params = input.getParameterList().getFormalparalist().stream() - .map(param -> new MethodParameter(convert(param.getType(), sigma), param.getName())).collect(Collectors.toList()); - // TODO - return new TargetMethod(0, null, input.name, params, null, convert(input.block)); + .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)); } - private TargetBlock convert(Block block) { - return new TargetBlock(block.statements.stream().map(e -> { - StatementToTargetExpression converter = new StatementToTargetExpression(); - e.accept(converter); - return converter.result; - }).collect(Collectors.toList())); + protected TargetBlock convert(Block block) { + return new TargetBlock(block.statements.stream().map(this::convert).collect(Collectors.toList())); } - private TargetField convert(Field input, Map sigma) { + protected TargetExpression convert(Expression expr) { + var converter = new StatementToTargetExpression(this); + expr.accept(converter); + return converter.result; + } + + private TargetField convert(Field input) { return null; } - private TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, Map sigma) { + protected TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input) { return input.acceptTV(new TypeVisitor<>() { @Override public TargetType visit(RefType refType) { return new TargetRefType(refType.getName().toString(), - refType.getParaList().stream().map((it) -> convert(it, sigma)).collect(Collectors.toList())); + refType.getParaList().stream().map(ASTToTargetAST.this::convert).collect(Collectors.toList())); } @Override public TargetType visit(SuperWildcardType superWildcardType) { - return new TargetSuperWildcard(convert(superWildcardType.getInnerType(), sigma)); + return new TargetSuperWildcard(convert(superWildcardType.getInnerType())); } @Override @@ -72,7 +84,7 @@ public class ASTToTargetAST { @Override public TargetType visit(ExtendsWildcardType extendsWildcardType) { - return new TargetExtendsWildcard(convert(extendsWildcardType.getInnerType(), sigma)); + return new TargetExtendsWildcard(convert(extendsWildcardType.getInnerType())); } @Override diff --git a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java index cf083f3d..3f16fa6e 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java @@ -1,117 +1,178 @@ package de.dhbwstuttgart.target.generate; +import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; -import de.dhbwstuttgart.syntaxtree.ASTVisitor; import de.dhbwstuttgart.syntaxtree.StatementVisitor; import de.dhbwstuttgart.syntaxtree.statement.*; -import de.dhbwstuttgart.target.tree.expression.TargetExpression; +import de.dhbwstuttgart.target.tree.MethodParameter; +import de.dhbwstuttgart.target.tree.expression.*; +import de.dhbwstuttgart.target.tree.type.TargetFunNType; + +import java.util.stream.StreamSupport; public class StatementToTargetExpression implements StatementVisitor { + + public StatementToTargetExpression(ASTToTargetAST converter) { + this.converter = converter; + } + public TargetExpression result; + private final ASTToTargetAST converter; @Override public void visit(ArgumentList argumentList) { - + throw new NotImplementedException(); } @Override public void visit(LambdaExpression lambdaExpression) { - + var parameters = StreamSupport + .stream(lambdaExpression.params.spliterator(), false) + .map(p -> new MethodParameter(converter.convert(p.getType()), p.getName())) + .toList(); + result = new TargetLambdaExpression( + new TargetFunNType(parameters.size(), parameters.stream().map(MethodParameter::type).toList()), + parameters, converter.convert(lambdaExpression.getReturnType()), converter.convert(lambdaExpression.methodBody) + ); } @Override public void visit(Assign assign) { + TargetExpression left; + if (assign.lefSide instanceof AssignToLocal) { + left = converter.convert(((AssignToLocal) assign.lefSide).localVar); + } else { + left = converter.convert(((AssignToField) assign.lefSide).field); + } + result = new TargetAssign(converter.convert(assign.getType()), left, converter.convert(assign.rightSide)); } @Override public void visit(BinaryExpr binary) { - + result = switch (binary.operation) { + case ADD -> new TargetBinaryOp.Add(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); + case SUB -> new TargetBinaryOp.Sub(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); + case MUL -> new TargetBinaryOp.Mul(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); + case MOD -> new TargetBinaryOp.Rem(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); + case AND -> new TargetBinaryOp.And(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); + case OR -> new TargetBinaryOp.Or(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); + case DIV -> new TargetBinaryOp.Div(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); + case LESSTHAN -> new TargetBinaryOp.Less(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); + case BIGGERTHAN -> new TargetBinaryOp.Greater(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); + case LESSEQUAL -> new TargetBinaryOp.LessOrEqual(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); + case BIGGEREQUAL -> new TargetBinaryOp.GreaterOrEqual(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); + case EQUAL -> new TargetBinaryOp.Equal(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); + case NOTEQUAL -> new TargetBinaryOp.NotEqual(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); + }; } @Override public void visit(Block block) { - + result = converter.convert(block); } @Override public void visit(CastExpr castExpr) { - + result = new TargetCast(converter.convert(castExpr.getType()), converter.convert(castExpr.expr)); } @Override public void visit(EmptyStmt emptyStmt) { - + result = null; } @Override public void visit(FieldVar fieldVar) { - + result = new TargetFieldVar( + converter.convert(fieldVar.getType()), + converter.convert(fieldVar.receiver.getType()), + false, + converter.convert(fieldVar.receiver), + fieldVar.fieldVarName); } @Override public void visit(ForStmt forStmt) { - + // TODO Doesn't seem to be fully implemented yet + throw new NotImplementedException(); } @Override public void visit(IfStmt ifStmt) { - + result = new TargetIf( + converter.convert(ifStmt.expr), + converter.convert(ifStmt.then_block), + converter.convert(ifStmt.else_block) + ); } @Override public void visit(InstanceOf instanceOf) { - + result = new TargetInstanceOf(converter.convert(instanceOf.lexpr), converter.convert(instanceOf.rexpr.getType())); } @Override public void visit(LocalVar localVar) { - + result = new TargetLocalVar(converter.convert(localVar.getType()), localVar.name); } @Override public void visit(LocalVarDecl localVarDecl) { - + // TODO No value, is this correct? + result = new TargetVarDecl(converter.convert(localVarDecl.getType()), localVarDecl.getName(), null); } @Override public void visit(MethodCall methodCall) { - + var receiver = methodCall.receiver; + result = new TargetMethodCall( + converter.convert(methodCall.getType()), + methodCall.argTypes.stream().map(converter::convert).toList(), + converter.convert(receiver), + methodCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), + converter.convert(receiver.getType()), + methodCall.name, false, false + ); } @Override - public void visit(NewClass methodCall) { - + public void visit(NewClass newClass) { + result = new TargetNew( + converter.convert(newClass.receiverType), + newClass.getArgumentList().getArguments().stream().map(converter::convert).toList() + ); } @Override public void visit(NewArray newArray) { - + // TODO + throw new NotImplementedException(); } @Override public void visit(Return aReturn) { - + result = new TargetReturn(converter.convert(aReturn.retexpr)); } @Override public void visit(ReturnVoid aReturn) { - + result = new TargetReturn(null); } @Override public void visit(StaticClassName staticClassName) { - + result = new TargetClassName(converter.convert(staticClassName.getType())); } @Override public void visit(Super aSuper) { - + result = new TargetSuper(converter.convert(aSuper.getType())); } @Override public void visit(This aThis) { - + result = new TargetThis(converter.convert(aThis.getType())); } @Override @@ -121,36 +182,63 @@ public class StatementToTargetExpression implements StatementVisitor { @Override public void visit(DoStmt whileStmt) { - + throw new NotImplementedException(); } + // TODO These two might not be necessary @Override public void visit(AssignToField assignLeftSide) { - + result = converter.convert(assignLeftSide.field); } @Override public void visit(AssignToLocal assignLeftSide) { - + result = converter.convert(assignLeftSide.localVar); } @Override public void visit(SuperCall superCall) { - + this.visit((MethodCall) superCall); } @Override public void visit(ExpressionReceiver expressionReceiver) { - + // TODO What is this? + throw new NotImplementedException(); } @Override public void visit(UnaryExpr unaryExpr) { - + result = switch (unaryExpr.operation) { + case NOT -> new TargetUnaryOp.Not(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr)); + case MINUS -> new TargetUnaryOp.Negate(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr)); + case PREINCREMENT -> new TargetUnaryOp.PreIncrement(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr)); + case PREDECREMENT -> new TargetUnaryOp.PreDecrement(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr)); + case POSTINCREMENT -> new TargetUnaryOp.PostIncrement(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr)); + case PLUS -> new TargetUnaryOp.Add(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr)); + case POSTDECREMENT -> new TargetUnaryOp.PostDecrement(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr)); + }; } @Override public void visit(Literal literal) { + if (literal.value instanceof Integer + || literal.value instanceof Short + || literal.value instanceof Byte) { + result = new TargetLiteral.IntLiteral((int) literal.value); + } else if (literal.value instanceof Float) { + result = new TargetLiteral.FloatLiteral((float) literal.value); + } else if (literal.value instanceof Double) { + result = new TargetLiteral.DoubleLiteral((double) literal.value); + } else if (literal.value instanceof Long) { + result = new TargetLiteral.LongLiteral((long) literal.value); + } else if (literal.value instanceof Character) { + result = new TargetLiteral.CharLiteral((char) literal.value); + } else if (literal.value instanceof String) { + result = new TargetLiteral.StringLiteral((String) literal.value); + } else if (literal.value instanceof Boolean) { + result = new TargetLiteral.BooleanLiteral((boolean) literal.value); + } } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFieldVar.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFieldVar.java index 0a72118e..5b82f22d 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFieldVar.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFieldVar.java @@ -3,5 +3,5 @@ package de.dhbwstuttgart.target.tree.expression; import de.dhbwstuttgart.target.tree.type.TargetRefType; import de.dhbwstuttgart.target.tree.type.TargetType; -public record TargetFieldVar(TargetType type, TargetRefType owner, boolean isStatic, TargetExpression left, String right) implements TargetExpression { +public record TargetFieldVar(TargetType type, TargetType owner, boolean isStatic, TargetExpression left, String right) implements TargetExpression { } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetInstanceOf.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetInstanceOf.java index 79bf75f9..c1f104e2 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetInstanceOf.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetInstanceOf.java @@ -3,7 +3,7 @@ package de.dhbwstuttgart.target.tree.expression; import de.dhbwstuttgart.syntaxtree.statement.Expression; import de.dhbwstuttgart.target.tree.type.TargetType; -public record TargetInstanceOf(Expression left, TargetType right) implements TargetExpression { +public record TargetInstanceOf(TargetExpression left, TargetType right) implements TargetExpression { @Override public TargetType type() { diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetUnaryOp.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetUnaryOp.java index 457a55ad..2f733e45 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetUnaryOp.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetUnaryOp.java @@ -6,6 +6,7 @@ public sealed interface TargetUnaryOp extends TargetExpression { TargetExpression expr(); record Negate(TargetType type, TargetExpression expr) implements TargetUnaryOp {} + record Add(TargetType type, TargetExpression expr) implements TargetUnaryOp {} record Not(TargetType type, TargetExpression expr) implements TargetUnaryOp {} record PreIncrement(TargetType type, TargetExpression expr) implements TargetStatementExpression {} diff --git a/src/test/java/targetast/ASTToTypedTargetAST.java b/src/test/java/targetast/ASTToTypedTargetAST.java index e4c93d1a..4e5437cc 100644 --- a/src/test/java/targetast/ASTToTypedTargetAST.java +++ b/src/test/java/targetast/ASTToTypedTargetAST.java @@ -23,7 +23,7 @@ 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().convert(emptyClass, emptyResultSet); + TargetClass emptyTargetClass = new ASTToTargetAST(emptyResultSet).convert(emptyClass); assert emptyTargetClass.getName().equals("EmptyClass"); assert emptyTargetClass.methods().size() == 0; assert emptyTargetClass.fields().size() == 0; From 0a1a596bb9ce286c85c3d45b823aa14d98085b62 Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Tue, 31 May 2022 14:02:39 +0200 Subject: [PATCH 45/69] Add Field transform --- .../target/generate/ASTToTargetAST.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index da917783..595ac922 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -35,7 +35,7 @@ public class ASTToTargetAST { 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(it)).collect(Collectors.toList()), + input.getFieldDecl().stream().map(it -> convert(input, it)).collect(Collectors.toList()), input.getMethods().stream().map(it -> convert(input, it)).collect(Collectors.toList())); } @@ -47,7 +47,8 @@ public class ASTToTargetAST { new TargetRefType(owner.getClassName().getClassName()), input.name, params, convert(input.getReturnType()), - convert(input.block)); + convert(input.block) + ); } protected TargetBlock convert(Block block) { @@ -60,8 +61,13 @@ public class ASTToTargetAST { return converter.result; } - private TargetField convert(Field input) { - return null; + private TargetField convert(ClassOrInterface owner, Field input) { + return new TargetField( + input.modifier, + new TargetRefType(owner.getClassName().getClassName()), + convert(input.getType()), + input.getName() + ); } protected TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input) { From 29112e7bd7e1ae5de117cde9c6839aaab4dc52a0 Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Fri, 17 Jun 2022 15:15:08 +0200 Subject: [PATCH 46/69] First implementation for overloaded functions and test case --- .../target/bytecode/Codegen.java | 2 +- .../target/generate/ASTToTargetAST.java | 123 +++++++++++++----- .../generate/StatementToTargetExpression.java | 18 ++- src/test/java/targetast/ASTToTargetTest.java | 5 - .../java/targetast/ASTToTypedTargetAST.java | 29 ++++- src/test/java/targetast/TestCodegen.java | 2 +- 6 files changed, 130 insertions(+), 49 deletions(-) delete mode 100644 src/test/java/targetast/ASTToTargetTest.java diff --git a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java index c7b74331..39974c92 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 595ac922..67e2330a 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 3f16fa6e..2bc06235 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 64d3368f..00000000 --- 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 4e5437cc..687a1ff8 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 1806fb33..b063ee82 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/"); From 3b439a49cd05140fc44705a6c21ea56165a26c8b Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Fri, 17 Jun 2022 15:16:56 +0200 Subject: [PATCH 47/69] IDEA wants it that way --- .../java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index 67e2330a..09897269 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -74,7 +74,7 @@ public class ASTToTargetAST { for (var s : all) { sigma = s; List params = convert(input.getParameterList()); - if (!parameterSet.stream().filter(p -> p.equals(params)).findFirst().isPresent()) { + if (parameterSet.stream().noneMatch(p -> p.equals(params))) { result.add(new TargetConstructor(input.modifier, new TargetRefType(owner.getClassName().getClassName()), params, convert(input.block))); parameterSet.add(params); } @@ -91,7 +91,7 @@ public class ASTToTargetAST { for (var s : all) { sigma = s; List params = convert(input.getParameterList()); - if (!parameterSet.stream().filter(p -> p.equals(params)).findFirst().isPresent()) { + if (parameterSet.stream().noneMatch(p -> p.equals(params))) { result.add(new TargetMethod( input.modifier, new TargetRefType(owner.getClassName().getClassName()), From f00ee2598f6fbd81efc52522dbbaaf1e0275179e Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Wed, 22 Jun 2022 17:06:49 +0200 Subject: [PATCH 48/69] 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 From 7e259e25971d413131fcb469fbc4000ce9f6f3d0 Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Thu, 23 Jun 2022 18:52:30 +0200 Subject: [PATCH 49/69] Mostly finish up populating generics --- .../target/generate/ASTToTargetAST.java | 294 ++++++++++-------- ...itor.java => TracingStatementVisitor.java} | 47 +-- 2 files changed, 191 insertions(+), 150 deletions(-) rename src/main/java/de/dhbwstuttgart/target/generate/{AbstractStatementVisitor.java => TracingStatementVisitor.java} (68%) diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index 92ff74d8..51e27e42 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -1,6 +1,5 @@ package de.dhbwstuttgart.target.generate; -import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.statement.*; import de.dhbwstuttgart.syntaxtree.type.*; @@ -11,7 +10,6 @@ import de.dhbwstuttgart.target.tree.type.*; import de.dhbwstuttgart.typeinference.result.*; import java.util.*; -import java.util.stream.Stream; public class ASTToTargetAST { @@ -19,10 +17,11 @@ public class ASTToTargetAST { protected Sigma sigma; private class Sigma { - HashMap> computedGenerics = new HashMap<>(); + Map> computedGenericsOfMethods = new HashMap<>(); + Map> computedGenericsOfClasses = new HashMap<>(); - Set simplifiedConstraints = new HashSet<>(); - Map result = new HashMap<>(); + HashSet simplifiedConstraints = new HashSet<>(); + Map concreteTypes = new HashMap<>(); Map equality = new HashMap<>(); Sigma(ResultSet constraints) { @@ -62,11 +61,9 @@ public class ASTToTargetAST { 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); + System.out.println("Simplified constraints: " + simplifiedConstraints); for (var equality : equalitySet) { var first = equality.get(0); @@ -76,155 +73,190 @@ public class ASTToTargetAST { for (var constraint : constraints.results) { if (constraint instanceof PairTPHequalRefTypeOrWildcardType p) { - result.put(p.left, convert(p.right)); + concreteTypes.put(this.equality.getOrDefault(p.left, p.left), p.right); } } } + void findTypeVariables(RefTypeOrTPHOrWildcardOrGeneric type, Set typeVariables) { + if (type instanceof TypePlaceholder tph) { + tph = equality.getOrDefault(tph, tph); + if (concreteTypes.containsKey(tph)) { + findTypeVariables(concreteTypes.get(tph), typeVariables); + return; + } + typeVariables.add(tph); + } else if (type instanceof RefType refType) { + for (var t : refType.getParaList()) + findTypeVariables(t, typeVariables); + } + } + + boolean hasBound(String name, Set generics) { + return generics.stream().anyMatch(generic -> generic.name().equals(name)); + } + // Family of generated Generics - Set generics(ClassOrInterface owner, Method method) { - if (computedGenerics.containsKey(method)) - return computedGenerics.get(method); + HashSet generics(ClassOrInterface owner, Method method) { + if (computedGenericsOfMethods.containsKey(method)) + return computedGenericsOfMethods.get(method); - Set result = new HashSet<>(); - computedGenerics.put(method, result); + HashSet result = new HashSet<>(); + computedGenericsOfMethods.put(method, result); - method.block.accept(new AbstractStatementVisitor() { - // These two methods do the actual work + var genericsOfClass = generics(owner); + var simplifiedConstraints = (HashSet) this.simplifiedConstraints.clone(); + + HashSet typeVariables = new HashSet<>(); + HashSet typeVariablesOfFields = new HashSet<>(); + + for (var field : owner.getFieldDecl()) { + findTypeVariables(field.getType(), typeVariablesOfFields); + } + + findTypeVariables(method.getReturnType(), typeVariables); + for (var arg : method.getParameterList().getFormalparalist()) { + findTypeVariables(arg.getType(), typeVariables); + } + + method.block.accept(new TracingStatementVisitor() { @Override public void visit(LocalVarDecl localVarDecl) { - // TODO + findTypeVariables(localVarDecl.getType(), typeVariables); } + }); + method.block.accept(new TracingStatementVisitor() { @Override public void visit(MethodCall methodCall) { + super.visit(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); + var generics = generics(owner, method); + HashSet all = new HashSet<>(generics); + // Reflexive and Transitive closure + HashSet toAdd = new HashSet<>(); + do { + toAdd.clear(); + for (var g1 : all) { + for (var g2 : all) { + if (g1.bound() instanceof TargetGenericType type) { + if (g2.name().equals(type.name()) && generics.stream().anyMatch(generic -> generic.name().equals(type.name()))) + toAdd.add(new TargetGeneric(g1.name(), g2.bound())); + } + } + } + all.addAll(toAdd); + } while (toAdd.size() > 0); + for (var generic : all) { + toAdd.add(new TargetGeneric(generic.name(), new TargetGenericType(generic.name()))); + } + all.addAll(toAdd); + + HashSet newPairs = new HashSet<>(); + // Loop from hell + outer: for (var tph : typeVariables) { + for (var generic : all) { + if (!(generic.bound() instanceof TargetGenericType type)) + continue; + + for (var pair : simplifiedConstraints) { + if (!(pair.left.equals(tph) && pair.right.getName().equals(generic.name()))) + continue; + + for (var tph2 : typeVariables) { + for (var pair2 : simplifiedConstraints) { + if (!(pair2.right.equals(tph2) && pair2.left.getName().equals(type.name()))) + continue; + + newPairs.add(new PairTPHsmallerTPH(tph, tph2)); + continue outer; + } + } + } + } + } + simplifiedConstraints.addAll(newPairs); } } } - - // 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; - } - - 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; + // Type variables with bounds that are also type variables of the method or type variables of fields + for (var typeVariable : (HashSet)typeVariables.clone()) { + for (var pair : simplifiedConstraints) { + if (pair.left.equals(typeVariable) && (typeVariables.contains(pair.right) || typeVariablesOfFields.contains(pair.right))) { + result.add(new TargetGeneric(pair.left.getName(), convert(pair.right))); + typeVariables.add(pair.right); } } } + + // All unbounded type variables + outer: for (var typeVariable : typeVariables) { + for (var pair : simplifiedConstraints) { + if (pair.left.equals(typeVariable) && typeVariables.contains(pair.right)) + continue outer; + } + if (!hasBound(typeVariable.getName(), genericsOfClass)) + result.add(new TargetGeneric(typeVariable.getName(), TargetType.Object)); + } + + // All unbounded bounds + outer: for (var pair : simplifiedConstraints) { + for (var pair2 : simplifiedConstraints) { + if (pair.right.equals(pair2.left)) + continue outer; + } + if (!hasBound(pair.right.getName(), genericsOfClass) && typeVariables.contains(pair.right)) + result.add(new TargetGeneric(pair.right.getName(), TargetType.Object)); + } + + System.out.println(method.name + ": " + result); + + return result; + } + + void findAllBounds(RefTypeOrTPHOrWildcardOrGeneric type, Set generics) { + if (type instanceof TypePlaceholder tph) { + tph = equality.getOrDefault(tph, tph); + + var concreteType = concreteTypes.get(tph); + if (concreteType != null) { + findAllBounds(concreteType, generics); + return; + } + + for (var rsp : simplifiedConstraints) { + var left = equality.getOrDefault(rsp.left, rsp.left); + var right = equality.getOrDefault(rsp.right, rsp.right); + if (left.equals(tph)) { + generics.add(new TargetGeneric(tph.getName(), new TargetGenericType(right.getName()))); + findAllBounds(right, generics); + return; + } + } + generics.add(new TargetGeneric(tph.getName(), TargetType.Object)); + } else if (type instanceof RefType refType) { + refType.getParaList().forEach(t -> findAllBounds(t, generics)); + } + } + + HashSet generics(ClassOrInterface classOrInterface) { + if (computedGenericsOfClasses.containsKey(classOrInterface)) + return computedGenericsOfClasses.get(classOrInterface); + + HashSet result = new HashSet<>(); + for (var field : classOrInterface.getFieldDecl()) { + findAllBounds(field.getType(), result); + } + computedGenericsOfClasses.put(classOrInterface, result); return result; } @@ -232,7 +264,9 @@ public class ASTToTargetAST { if (equality.containsKey(tph)) { return get(equality.get(tph)); } - return result.get(tph); + var type = concreteTypes.get(tph); + if (type == null) return new TargetGenericType(tph.getName()); + return convert(type); } } diff --git a/src/main/java/de/dhbwstuttgart/target/generate/AbstractStatementVisitor.java b/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java similarity index 68% rename from src/main/java/de/dhbwstuttgart/target/generate/AbstractStatementVisitor.java rename to src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java index b9e2243d..7a7352ad 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/AbstractStatementVisitor.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java @@ -4,30 +4,41 @@ import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; import de.dhbwstuttgart.syntaxtree.StatementVisitor; import de.dhbwstuttgart.syntaxtree.statement.*; -public abstract class AbstractStatementVisitor implements StatementVisitor { + +// This visitor walks the entire tree, individual methods may be overridden +public abstract class TracingStatementVisitor implements StatementVisitor { + + @Override + public void visit(MethodCall methodCall) { + methodCall.receiver.accept(this); + methodCall.getArgumentList().accept(this); + } + @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 @@ -47,12 +58,13 @@ public abstract class AbstractStatementVisitor implements StatementVisitor { @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 @@ -71,23 +83,18 @@ public abstract class AbstractStatementVisitor implements StatementVisitor { } @Override - public void visit(MethodCall methodCall) { - - } - - @Override - public void visit(NewClass methodCall) { - + public void visit(NewClass newClass) { + this.visit((MethodCall) newClass); } @Override public void visit(NewArray newArray) { - + newArray.expr.forEach(expr -> expr.accept(this)); } @Override public void visit(Return aReturn) { - + aReturn.retexpr.accept(this); } @Override @@ -112,12 +119,12 @@ public abstract class AbstractStatementVisitor implements StatementVisitor { @Override public void visit(WhileStmt whileStmt) { - + whileStmt.loopBlock.accept(this); } @Override public void visit(DoStmt whileStmt) { - + whileStmt.loopBlock.accept(this); } @Override @@ -142,7 +149,7 @@ public abstract class AbstractStatementVisitor implements StatementVisitor { @Override public void visit(UnaryExpr unaryExpr) { - + unaryExpr.expr.accept(this); } @Override From a8be387dd97695528baec68a507b290c432a8355 Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Thu, 23 Jun 2022 20:39:34 +0200 Subject: [PATCH 50/69] Add generics to the generated class file --- .../target/bytecode/Codegen.java | 49 +++++++++---------- .../target/generate/ASTToTargetAST.java | 3 ++ .../generate/StatementToTargetExpression.java | 10 ++-- .../target/tree/TargetConstructor.java | 4 ++ .../target/tree/TargetField.java | 4 -- .../target/tree/TargetMethod.java | 24 +++++++-- .../tree/type/TargetExtendsWildcard.java | 5 ++ .../target/tree/type/TargetGenericType.java | 9 +++- .../tree/type/TargetSpecializedType.java | 14 ++++++ .../target/tree/type/TargetSuperWildcard.java | 5 ++ .../target/tree/type/TargetType.java | 1 + .../java/targetast/ASTToTypedTargetAST.java | 2 +- 12 files changed, 87 insertions(+), 43 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java index 822ab670..13514baa 100755 --- a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java @@ -617,9 +617,11 @@ public class Codegen { break; case TargetVarDecl varDecl: { var local = state.createVariable(varDecl.name(), varDecl.varType()); - generate(state, varDecl.value()); - boxPrimitive(state, varDecl.varType()); - mv.visitVarInsn(ASTORE, local.index()); + if (varDecl.value() != null) { + generate(state, varDecl.value()); + boxPrimitive(state, varDecl.varType()); + mv.visitVarInsn(ASTORE, local.index()); + } break; } case TargetBinaryOp op: @@ -737,12 +739,8 @@ public class Codegen { generate(state, e); boxPrimitive(state, e.type()); } - if (call.expr() instanceof TargetThis) - mv.visitMethodInsn(INVOKESPECIAL, clazz.getName(), "", call.getDescriptor(), false); - else if (call.expr() instanceof TargetSuper) - mv.visitMethodInsn(INVOKESPECIAL, clazz.superType().getName(), "", call.getDescriptor(), false); - else mv.visitMethodInsn(call.isInterface() ? INVOKEINTERFACE : call.isStatic() ? INVOKESTATIC: INVOKEVIRTUAL, - call.owner().getName(), call.name(), call.getDescriptor(), call.isInterface()); + mv.visitMethodInsn(call.isInterface() ? INVOKEINTERFACE : call.isStatic() ? INVOKESTATIC: call.name() == "" ? INVOKESPECIAL : INVOKEVIRTUAL, + call.owner().getName(), call.name(), call.getDescriptor(), call.isInterface()); if (call.type() != null) unboxPrimitive(state, call.type()); break; @@ -766,29 +764,15 @@ public class Codegen { } private void generateField(TargetField field) { - cw.visitField(field.access(), field.name(), field.getDescriptor(), null, null); - } - - private boolean hasThisOrSuperCall(TargetBlock block) { - if (block.statements().size() == 0) return false; - TargetExpression first = block.statements().get(0); - if (!(first instanceof TargetMethodCall)) return false; - var methodCall = (TargetMethodCall) first; - if (methodCall.expr() instanceof TargetThis || methodCall.expr() instanceof TargetSuper) - return true; - return false; + cw.visitField(field.access(), field.name(), field.type().toSignature(), field.type().toGenericSignature(), null); } private void generateConstructor(TargetConstructor constructor) { - MethodVisitor mv = cw.visitMethod(constructor.access(), "", constructor.getDescriptor(), null, null); + MethodVisitor mv = cw.visitMethod(constructor.access(), "", constructor.getDescriptor(), constructor.getSignature(), null); mv.visitCode(); var state = new State(mv, 1); for (var param: constructor.parameters()) state.createVariable(param.name(), param.type()); - if (!hasThisOrSuperCall(constructor.block())) { - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, clazz.superType().getName(), "", "()V", false); - } generate(state, constructor.block()); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); @@ -796,7 +780,7 @@ public class Codegen { } private void generateMethod(TargetMethod method) { - MethodVisitor mv = cw.visitMethod(method.access(), method.name(), method.getDescriptor(), null, null); + MethodVisitor mv = cw.visitMethod(method.access(), method.name(), method.getDescriptor(), method.getSignature(), null); mv.visitCode(); var state = new State(mv, method.isStatic() ? 0 : 1); for (var param: method.parameters()) @@ -808,9 +792,20 @@ public class Codegen { mv.visitEnd(); } + private static String generateSignature(TargetClass clazz) { + String ret = "<"; + for (var generic : clazz.generics()) { + ret += generic.name() + ":" + generic.bound().toGenericSignature(); + } + ret += ">"; + ret += clazz.superType().toGenericSignature(); + + return ret; + } + public byte[] generate() { cw.visit(V1_8, clazz.modifiers(), clazz.qualifiedName(), - null, clazz.superType() != null ? clazz.superType().getName(): "java/lang/Object", + generateSignature(clazz), 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 51e27e42..f307b392 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -15,6 +15,7 @@ public class ASTToTargetAST { protected List all; protected Sigma sigma; + protected ClassOrInterface currentClass; // TODO This is only needed because of SuperCall, maybe there's a better way? private class Sigma { Map> computedGenericsOfMethods = new HashMap<>(); @@ -294,6 +295,7 @@ public class ASTToTargetAST { } private List convert(ClassOrInterface owner, Constructor input) { + currentClass = owner; sigma = all.get(0); List result = new ArrayList<>(); Set> parameterSet = new HashSet<>(); @@ -311,6 +313,7 @@ public class ASTToTargetAST { } private List convert(ClassOrInterface owner, Method input) { + currentClass = owner; sigma = all.get(0); List result = new ArrayList<>(); Set> parameterSet = new HashSet<>(); diff --git a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java index 2bc06235..53b69066 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java @@ -127,13 +127,12 @@ public class StatementToTargetExpression implements StatementVisitor { @Override public void visit(MethodCall methodCall) { - var receiver = methodCall.receiver; result = new TargetMethodCall( converter.convert(methodCall.getType()), methodCall.argTypes == null ? List.of() : methodCall.argTypes.stream().map(converter::convert).toList(), - converter.convert(receiver), + converter.convert(methodCall.receiver), methodCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), - converter.convert(receiver.getType()), + converter.convert(methodCall.receiver.getType()), methodCall.name, false, false ); } @@ -200,12 +199,13 @@ public class StatementToTargetExpression implements StatementVisitor { @Override public void visit(SuperCall superCall) { + var aSuper = converter.convert(converter.currentClass.getSuperClass()); result = new TargetMethodCall( converter.convert(superCall.getType()), superCall.argTypes == null ? List.of() : superCall.argTypes.stream().map(converter::convert).toList(), - new TargetSuper(null), + new TargetSuper(aSuper), superCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), - null, + aSuper, superCall.name, false, false ); } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java index a0e5a365..dc7f01ac 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java @@ -11,5 +11,9 @@ public record TargetConstructor(int access, Set generics, List generics, ret += parameterType.toSignature(); } ret += ")"; - if (returnType == null) { - ret += "V"; - } else { - ret += returnType.toSignature(); + if (returnType == null) ret += "V"; + else ret += returnType.toSignature(); + return ret; + } + + public static String getSignature(Set generics, List parameters, TargetType returnType) { + String ret = "<"; + for (var generic : generics) { + ret += generic.name() + ":" + generic.bound().toGenericSignature(); } + ret += ">("; + for (var param : parameters) { + ret += param.type().toGenericSignature(); + } + ret += ")"; + if (returnType == null) ret += "V"; + else ret += returnType.toGenericSignature(); return ret; } @@ -26,6 +38,10 @@ public record TargetMethod(int access, String name, Set generics, return getDescriptor(returnType, parameters.stream().map(MethodParameter::type).toArray(TargetType[]::new)); } + public String getSignature() { + return getSignature(generics, parameters, returnType); + } + public boolean isStatic() { return (access & Opcodes.ACC_STATIC) != 0; } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java index c9d70f19..5d32fb1b 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java @@ -6,6 +6,11 @@ public record TargetExtendsWildcard(TargetType innerType) implements TargetType return null; } + @Override + public String toGenericSignature() { + return null; + } + @Override public String getName() { return null; 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 149ed52c..cc9e4bb2 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetGenericType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetGenericType.java @@ -3,11 +3,16 @@ package de.dhbwstuttgart.target.tree.type; public record TargetGenericType(String name) implements TargetType { @Override public String toSignature() { - return null; + return "Ljava/lang/Object;"; // TODO Use bounds for this? + } + + @Override + public String toGenericSignature() { + return "T" + getName() + ";"; } @Override public String getName() { - return null; + return name; } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSpecializedType.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSpecializedType.java index 0dce9825..c1f4dfc9 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSpecializedType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSpecializedType.java @@ -4,4 +4,18 @@ import java.util.List; public sealed interface TargetSpecializedType extends TargetType permits TargetFunNType, TargetRefType { List params(); + + @Override + default String toGenericSignature() { + String ret = "L" + getName(); + if (params().size() > 0) { + ret += "<"; + for (var param : params()) { + ret += param.toGenericSignature(); + } + ret += ">"; + } + ret += ";"; + return ret; + } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java index fee11375..3306d14d 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java @@ -6,6 +6,11 @@ public record TargetSuperWildcard(TargetType innerType) implements TargetType { return null; } + @Override + public String toGenericSignature() { + return null; + } + @Override public String getName() { return null; 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 263c760c..ad9c895e 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetType.java @@ -18,5 +18,6 @@ public sealed interface TargetType TargetRefType Object = new TargetRefType("java.lang.Object"); String toSignature(); + String toGenericSignature(); String getName(); } diff --git a/src/test/java/targetast/ASTToTypedTargetAST.java b/src/test/java/targetast/ASTToTypedTargetAST.java index 17196470..db1c635f 100644 --- a/src/test/java/targetast/ASTToTypedTargetAST.java +++ b/src/test/java/targetast/ASTToTypedTargetAST.java @@ -59,6 +59,6 @@ public class ASTToTypedTargetAST { var converter = new ASTToTargetAST(resultSet); var classes = compiler.sourceFiles.get(file).getClasses(); - converter.convert(classes.get(0)); + var tphAndGenerics = TestCodegen.generateClass(converter.convert(classes.get(0))); } } From b43afd40ee1936f582e0bb8b0f575968283e8462 Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Sat, 2 Jul 2022 15:57:33 +0200 Subject: [PATCH 51/69] Decouple Sigma from Target --- .../target/generate/ASTToTargetAST.java | 89 +++++++++++-------- 1 file changed, 54 insertions(+), 35 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index f307b392..e9d1805e 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -1,6 +1,7 @@ package de.dhbwstuttgart.target.generate; import de.dhbwstuttgart.syntaxtree.*; +import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; import de.dhbwstuttgart.syntaxtree.statement.*; import de.dhbwstuttgart.syntaxtree.type.*; import de.dhbwstuttgart.target.tree.*; @@ -10,18 +11,21 @@ import de.dhbwstuttgart.target.tree.type.*; import de.dhbwstuttgart.typeinference.result.*; import java.util.*; +import java.util.stream.Collectors; public class ASTToTargetAST { + static RefType OBJECT = ASTFactory.createObjectType(); // TODO It would be better if I could call this directly but the hashcode seems to change + protected List all; protected Sigma sigma; protected ClassOrInterface currentClass; // TODO This is only needed because of SuperCall, maybe there's a better way? private class Sigma { - Map> computedGenericsOfMethods = new HashMap<>(); - Map> computedGenericsOfClasses = new HashMap<>(); + Map>> computedGenericsOfMethods = new HashMap<>(); + Map>> computedGenericsOfClasses = new HashMap<>(); - HashSet simplifiedConstraints = new HashSet<>(); + Set simplifiedConstraints = new HashSet<>(); Map concreteTypes = new HashMap<>(); Map equality = new HashMap<>(); @@ -93,20 +97,20 @@ public class ASTToTargetAST { } } - boolean hasBound(String name, Set generics) { - return generics.stream().anyMatch(generic -> generic.name().equals(name)); + boolean hasBound(TypePlaceholder name, Set> generics) { + return generics.stream().anyMatch(generic -> generic.getLeft().equals(name)); } // Family of generated Generics - HashSet generics(ClassOrInterface owner, Method method) { + Set> generics(ClassOrInterface owner, Method method) { if (computedGenericsOfMethods.containsKey(method)) return computedGenericsOfMethods.get(method); - HashSet result = new HashSet<>(); + Set> result = new HashSet<>(); computedGenericsOfMethods.put(method, result); var genericsOfClass = generics(owner); - var simplifiedConstraints = (HashSet) this.simplifiedConstraints.clone(); + var simplifiedConstraints = new HashSet<>(this.simplifiedConstraints); HashSet typeVariables = new HashSet<>(); HashSet typeVariablesOfFields = new HashSet<>(); @@ -139,41 +143,42 @@ public class ASTToTargetAST { assert optMethod.isPresent(); var method = optMethod.get(); var generics = generics(owner, method); - HashSet all = new HashSet<>(generics); + Set> all = new HashSet<>(generics); // Reflexive and Transitive closure - HashSet toAdd = new HashSet<>(); + HashSet> toAdd = new HashSet<>(); do { toAdd.clear(); for (var g1 : all) { for (var g2 : all) { - if (g1.bound() instanceof TargetGenericType type) { - if (g2.name().equals(type.name()) && generics.stream().anyMatch(generic -> generic.name().equals(type.name()))) - toAdd.add(new TargetGeneric(g1.name(), g2.bound())); + if (g1 instanceof PairTPHsmallerTPH pair) { + if (g2.getLeft().equals(pair.getLeft()) && generics.stream().anyMatch(generic -> generic.getLeft().equals(pair.getRight()))) + toAdd.add(new PairTPHsmallerTPH((TypePlaceholder) g1.getLeft(), (TypePlaceholder) g2.getRight())); } } } all.addAll(toAdd); } while (toAdd.size() > 0); for (var generic : all) { - toAdd.add(new TargetGeneric(generic.name(), new TargetGenericType(generic.name()))); + toAdd.add(new PairTPHsmallerTPH((TypePlaceholder) generic.getLeft(), (TypePlaceholder) generic.getLeft())); } all.addAll(toAdd); HashSet newPairs = new HashSet<>(); // Loop from hell - outer: for (var tph : typeVariables) { + outer: + for (var tph : typeVariables) { for (var generic : all) { - if (!(generic.bound() instanceof TargetGenericType type)) + if (!(generic.getRight() instanceof TypePlaceholder type)) continue; for (var pair : simplifiedConstraints) { - if (!(pair.left.equals(tph) && pair.right.getName().equals(generic.name()))) + if (!(pair.left.equals(tph) && pair.right.equals(generic.getLeft()))) continue; for (var tph2 : typeVariables) { for (var pair2 : simplifiedConstraints) { - if (!(pair2.right.equals(tph2) && pair2.left.getName().equals(type.name()))) + if (!(pair2.right.equals(tph2) && pair2.left.equals(type))) continue; newPairs.add(new PairTPHsmallerTPH(tph, tph2)); @@ -190,33 +195,35 @@ public class ASTToTargetAST { }); // Type variables with bounds that are also type variables of the method or type variables of fields - for (var typeVariable : (HashSet)typeVariables.clone()) { + for (var typeVariable : new HashSet<>(typeVariables)) { for (var pair : simplifiedConstraints) { if (pair.left.equals(typeVariable) && (typeVariables.contains(pair.right) || typeVariablesOfFields.contains(pair.right))) { - result.add(new TargetGeneric(pair.left.getName(), convert(pair.right))); + result.add(new PairTPHsmallerTPH(pair.left, equality.getOrDefault(pair.right, pair.right))); typeVariables.add(pair.right); } } } // All unbounded type variables - outer: for (var typeVariable : typeVariables) { + outer: + for (var typeVariable : typeVariables) { for (var pair : simplifiedConstraints) { if (pair.left.equals(typeVariable) && typeVariables.contains(pair.right)) continue outer; } - if (!hasBound(typeVariable.getName(), genericsOfClass)) - result.add(new TargetGeneric(typeVariable.getName(), TargetType.Object)); + if (!hasBound(typeVariable, genericsOfClass)) + result.add(new PairTPHequalRefTypeOrWildcardType(typeVariable, OBJECT)); } // All unbounded bounds - outer: for (var pair : simplifiedConstraints) { + outer: + for (var pair : simplifiedConstraints) { for (var pair2 : simplifiedConstraints) { if (pair.right.equals(pair2.left)) continue outer; } - if (!hasBound(pair.right.getName(), genericsOfClass) && typeVariables.contains(pair.right)) - result.add(new TargetGeneric(pair.right.getName(), TargetType.Object)); + if (!hasBound(pair.right, genericsOfClass) && typeVariables.contains(pair.right)) + result.add(new PairTPHequalRefTypeOrWildcardType(pair.right, OBJECT)); } System.out.println(method.name + ": " + result); @@ -224,7 +231,7 @@ public class ASTToTargetAST { return result; } - void findAllBounds(RefTypeOrTPHOrWildcardOrGeneric type, Set generics) { + void findAllBounds(RefTypeOrTPHOrWildcardOrGeneric type, Set> generics) { if (type instanceof TypePlaceholder tph) { tph = equality.getOrDefault(tph, tph); @@ -238,22 +245,22 @@ public class ASTToTargetAST { var left = equality.getOrDefault(rsp.left, rsp.left); var right = equality.getOrDefault(rsp.right, rsp.right); if (left.equals(tph)) { - generics.add(new TargetGeneric(tph.getName(), new TargetGenericType(right.getName()))); + generics.add(new PairTPHsmallerTPH(tph, right)); findAllBounds(right, generics); return; } } - generics.add(new TargetGeneric(tph.getName(), TargetType.Object)); + generics.add(new PairTPHequalRefTypeOrWildcardType(tph, OBJECT)); } else if (type instanceof RefType refType) { refType.getParaList().forEach(t -> findAllBounds(t, generics)); } } - HashSet generics(ClassOrInterface classOrInterface) { + Set> generics(ClassOrInterface classOrInterface) { if (computedGenericsOfClasses.containsKey(classOrInterface)) return computedGenericsOfClasses.get(classOrInterface); - HashSet result = new HashSet<>(); + Set> result = new HashSet<>(); for (var field : classOrInterface.getFieldDecl()) { findAllBounds(field.getType(), result); } @@ -279,9 +286,21 @@ public class ASTToTargetAST { this.sigma = all.get(0); } + Set convert(Set> result) { + return result.stream().map(p -> { + if (p instanceof PairTPHsmallerTPH pair) { + return new TargetGeneric(pair.left.getName(), new TargetGenericType(pair.right.getName())); + } else if (p instanceof PairTPHequalRefTypeOrWildcardType pair) { + return new TargetGeneric(pair.left.getName(), convert(pair.right)); + } else { + throw new IllegalArgumentException(); + } + }).collect(Collectors.toSet()); + } + public TargetClass convert(ClassOrInterface input) { - return new TargetClass(input.getModifiers(),input.getClassName().toString(), convert(input.getSuperClass()), - sigma.generics(input), + return new TargetClass(input.getModifiers(), input.getClassName().toString(), convert(input.getSuperClass()), + convert(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(), @@ -304,7 +323,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, sigma.generics(owner, input), params, convert(input.block))); + result.add(new TargetConstructor(input.modifier, convert(sigma.generics(owner, input)), params, convert(input.block))); parameterSet.add(params); } } @@ -324,7 +343,7 @@ public class ASTToTargetAST { if (parameterSet.stream().noneMatch(p -> p.equals(params))) { result.add(new TargetMethod( input.modifier, - input.name, sigma.generics(owner, input), params, + input.name, convert(sigma.generics(owner, input)), params, convert(input.getReturnType()), convert(input.block) )); From d7380c6cb74b3fdacd035e146bee3fb9a162134e Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Sat, 2 Jul 2022 16:14:46 +0200 Subject: [PATCH 52/69] Remove duplicate testcase --- src/test/java/targetast/ASTToTypedTargetAST.java | 5 +++-- .../bytecode/javFiles/TPHsAndGenerics.jav | 16 ---------------- 2 files changed, 3 insertions(+), 18 deletions(-) delete mode 100644 src/test/resources/bytecode/javFiles/TPHsAndGenerics.jav diff --git a/src/test/java/targetast/ASTToTypedTargetAST.java b/src/test/java/targetast/ASTToTypedTargetAST.java index db1c635f..881e0cb7 100644 --- a/src/test/java/targetast/ASTToTypedTargetAST.java +++ b/src/test/java/targetast/ASTToTypedTargetAST.java @@ -52,8 +52,8 @@ public class ASTToTypedTargetAST { } @Test - public void generics() throws Exception { - var file = Path.of(System.getProperty("user.dir"), "/src/test/resources/bytecode/javFiles/TPHsAndGenerics.jav").toFile(); + public void tphsAndGenerics() throws Exception { + var file = Path.of(System.getProperty("user.dir"), "/src/test/resources/bytecode/javFiles/Tph2.jav").toFile(); var compiler = new JavaTXCompiler(file); var resultSet = compiler.typeInference(); var converter = new ASTToTargetAST(resultSet); @@ -61,4 +61,5 @@ public class ASTToTypedTargetAST { var tphAndGenerics = TestCodegen.generateClass(converter.convert(classes.get(0))); } + } diff --git a/src/test/resources/bytecode/javFiles/TPHsAndGenerics.jav b/src/test/resources/bytecode/javFiles/TPHsAndGenerics.jav deleted file mode 100644 index 84844c9b..00000000 --- a/src/test/resources/bytecode/javFiles/TPHsAndGenerics.jav +++ /dev/null @@ -1,16 +0,0 @@ -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 From 560f0c5a6f67eafddc281f5d25759960117bfb56 Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Sun, 3 Jul 2022 15:17:12 +0200 Subject: [PATCH 53/69] Filter out cycles and infima --- .../target/bytecode/Codegen.java | 3 +- .../target/generate/ASTToTargetAST.java | 138 +++++++++++++++++- .../java/targetast/ASTToTypedTargetAST.java | 21 +++ .../resources/bytecode/javFiles/Cycle.jav | 6 + .../resources/bytecode/javFiles/Infimum.jav | 6 + 5 files changed, 170 insertions(+), 4 deletions(-) create mode 100644 src/test/resources/bytecode/javFiles/Cycle.jav create mode 100644 src/test/resources/bytecode/javFiles/Infimum.jav diff --git a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java index 13514baa..8b540e69 100755 --- a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java @@ -717,9 +717,8 @@ public class Codegen { break; } case TargetReturn ret: { - generate(state, ret.expression()); - if (ret.expression() != null) { + generate(state, ret.expression()); boxPrimitive(state, ret.expression().type()); mv.visitInsn(ARETURN); } else mv.visitInsn(RETURN); diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index e9d1805e..39ad380d 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -1,5 +1,6 @@ package de.dhbwstuttgart.target.generate; +import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; import de.dhbwstuttgart.syntaxtree.statement.*; @@ -226,6 +227,7 @@ public class ASTToTargetAST { result.add(new PairTPHequalRefTypeOrWildcardType(pair.right, OBJECT)); } + eliminateCyclesAndInfima(result); System.out.println(method.name + ": " + result); return result; @@ -265,9 +267,53 @@ public class ASTToTargetAST { findAllBounds(field.getType(), result); } computedGenericsOfClasses.put(classOrInterface, result); + eliminateCyclesAndInfima(result); + System.out.println("Class " + classOrInterface.getClassName().getClassName() + ": " + result); return result; } + void eliminateCyclesAndInfima(Set> input) { + // Eliminate cycles + var cycles = findCycles(input); + for (var cycle : cycles) { + var newTph = TypePlaceholder.fresh(new NullToken()); + input.add(new PairTPHequalRefTypeOrWildcardType(newTph, OBJECT)); + cycle.add(cycle.get(0)); // Make it a complete cycle + for (var i = 0; i < cycle.size() - 1; i++) { + var left = cycle.get(i); + var right = cycle.get(i + 1); + var pair = new PairTPHsmallerTPH(left, right); + input.remove(pair); + equality.put(left, newTph); + } + } + // Eliminate infima + var foundInfima = false; + do { + foundInfima = false; + for (var constraint : new HashSet<>(input)) { + var left = (TypePlaceholder) constraint.getLeft(); + Set infima = new HashSet<>(); + for (var pair : input) { + if (pair instanceof PairTPHsmallerTPH stph) + if (pair.getLeft().equals(constraint.getLeft())) + infima.add(stph); + } + if (infima.size() > 1) { + foundInfima = true; + var newTph = TypePlaceholder.fresh(new NullToken()); + input.add(new PairTPHsmallerTPH(left, newTph)); + input.add(new PairTPHequalRefTypeOrWildcardType(newTph, OBJECT)); + input.removeAll(infima); + for (var infimum : infima) { + equality.put(infimum.right, newTph); + input.removeIf(pair -> pair.getLeft().equals(infimum.right)); + } + } + } + } while (foundInfima); + } + TargetType get(TypePlaceholder tph) { if (equality.containsKey(tph)) { return get(equality.get(tph)); @@ -286,6 +332,92 @@ public class ASTToTargetAST { this.sigma = all.get(0); } + static Set allNodes(Set> input) { + return input.stream().map(pair -> (TypePlaceholder) pair.getLeft()).collect(Collectors.toSet()); + } + + static Set outgoingEdgesOf(TypePlaceholder tph, Set> input) { + return input.stream() + .filter(pair -> pair instanceof PairTPHsmallerTPH && pair.getLeft().equals(tph)) + .map(pair -> (TypePlaceholder) pair.getRight()).collect(Collectors.toSet()); + } + + static boolean containsEdge(TypePlaceholder a, TypePlaceholder b, Set> input) { + return input.stream().anyMatch(pair -> pair.getLeft().equals(a) && pair.getRight().equals(b)); + } + + // Tiernan simple cycles algorithm + static Set> findCycles(Set> input) { + Map indices = new HashMap<>(); + List path = new ArrayList<>(); + Set pathSet = new HashSet<>(); + Map> blocked = new HashMap<>(); + Set> cycles = new HashSet<>(); + + int index = 0; + for (var tph : allNodes(input)) { + blocked.put(tph, new HashSet<>()); + indices.put(tph, index++); + } + + var vertexIterator = allNodes(input).iterator(); + if (!vertexIterator.hasNext()) return cycles; + + TypePlaceholder startOfPath = null; + TypePlaceholder endOfPath = vertexIterator.next(); + TypePlaceholder temp = null; + int endIndex = 0; + boolean extensionFound = false; + path.add(endOfPath); + pathSet.add(endOfPath); + + while (true) { + do { + extensionFound = false; + for (TypePlaceholder n : outgoingEdgesOf(endOfPath, input)) { + int cmp = indices.get(n).compareTo(indices.get(path.get(0))); + if ((cmp > 0) && !pathSet.contains(n) && !blocked.get(endOfPath).contains(n)) { + path.add(n); + pathSet.add(n); + endOfPath = n; + extensionFound = true; + break; + } + } + } while (extensionFound); + + startOfPath = path.get(0); + if (containsEdge(endOfPath, startOfPath, input)) { + List cycle = new ArrayList<>(path); + cycles.add(cycle); + } + if (path.size() > 1) { + blocked.get(endOfPath).clear(); + endIndex = path.size() - 1; + path.remove(endIndex); + pathSet.remove(endOfPath); + --endIndex; + temp = endOfPath; + endOfPath = path.get(endIndex); + blocked.get(endOfPath).add(temp); + continue; + } + if (vertexIterator.hasNext()) { + path.clear(); + pathSet.clear(); + endOfPath = vertexIterator.next(); + path.add(endOfPath); + pathSet.add(endOfPath); + for (TypePlaceholder tph : blocked.keySet()) { + blocked.get(tph).clear(); + } + continue; + } + break; + } + return cycles; + } + Set convert(Set> result) { return result.stream().map(p -> { if (p instanceof PairTPHsmallerTPH pair) { @@ -321,9 +453,10 @@ public class ASTToTargetAST { for (var s : all) { sigma = s; + var generics = sigma.generics(owner, input); List params = convert(input.getParameterList()); if (parameterSet.stream().noneMatch(p -> p.equals(params))) { - result.add(new TargetConstructor(input.modifier, convert(sigma.generics(owner, input)), params, convert(input.block))); + result.add(new TargetConstructor(input.modifier, convert(generics), params, convert(input.block))); parameterSet.add(params); } } @@ -339,11 +472,12 @@ public class ASTToTargetAST { for (var s : all) { sigma = s; + var generics = sigma.generics(owner, input); List params = convert(input.getParameterList()); if (parameterSet.stream().noneMatch(p -> p.equals(params))) { result.add(new TargetMethod( input.modifier, - input.name, convert(sigma.generics(owner, input)), params, + input.name, convert(generics), params, convert(input.getReturnType()), convert(input.block) )); diff --git a/src/test/java/targetast/ASTToTypedTargetAST.java b/src/test/java/targetast/ASTToTypedTargetAST.java index 881e0cb7..6f914432 100644 --- a/src/test/java/targetast/ASTToTypedTargetAST.java +++ b/src/test/java/targetast/ASTToTypedTargetAST.java @@ -62,4 +62,25 @@ public class ASTToTypedTargetAST { var tphAndGenerics = TestCodegen.generateClass(converter.convert(classes.get(0))); } + @Test + public void cycles() throws Exception { + var file = Path.of(System.getProperty("user.dir"), "/src/test/resources/bytecode/javFiles/Cycle.jav").toFile(); + var compiler = new JavaTXCompiler(file); + var resultSet = compiler.typeInference(); + var converter = new ASTToTargetAST(resultSet); + var classes = compiler.sourceFiles.get(file).getClasses(); + + var cycle = TestCodegen.generateClass(converter.convert(classes.get(0))); + } + + @Test + public void infimum() throws Exception { + var file = Path.of(System.getProperty("user.dir"), "/src/test/resources/bytecode/javFiles/Infimum.jav").toFile(); + var compiler = new JavaTXCompiler(file); + var resultSet = compiler.typeInference(); + var converter = new ASTToTargetAST(resultSet); + var classes = compiler.sourceFiles.get(file).getClasses(); + + var infimum = TestCodegen.generateClass(converter.convert(classes.get(0))); + } } diff --git a/src/test/resources/bytecode/javFiles/Cycle.jav b/src/test/resources/bytecode/javFiles/Cycle.jav new file mode 100644 index 00000000..85f2ba9a --- /dev/null +++ b/src/test/resources/bytecode/javFiles/Cycle.jav @@ -0,0 +1,6 @@ +class Cycle { + m(x, y) { + y = x; + x = y; + } +} \ No newline at end of file diff --git a/src/test/resources/bytecode/javFiles/Infimum.jav b/src/test/resources/bytecode/javFiles/Infimum.jav new file mode 100644 index 00000000..7c475394 --- /dev/null +++ b/src/test/resources/bytecode/javFiles/Infimum.jav @@ -0,0 +1,6 @@ +class Infimum { + m(x, y, z) { + y = x; + z = x; + } +} \ No newline at end of file From ef06a8de380f965042f4aee0c9c11686ec25304a Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Sun, 3 Jul 2022 15:25:35 +0200 Subject: [PATCH 54/69] Actually replace instead of removing pairs --- .../target/generate/ASTToTargetAST.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index 39ad380d..1a9589d8 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -303,11 +303,24 @@ public class ASTToTargetAST { foundInfima = true; var newTph = TypePlaceholder.fresh(new NullToken()); input.add(new PairTPHsmallerTPH(left, newTph)); - input.add(new PairTPHequalRefTypeOrWildcardType(newTph, OBJECT)); input.removeAll(infima); for (var infimum : infima) { equality.put(infimum.right, newTph); - input.removeIf(pair -> pair.getLeft().equals(infimum.right)); + new HashSet<>(input).stream().forEach(pair -> { + if (pair.getLeft().equals(infimum.right)) { + input.remove(pair); + if (pair instanceof PairTPHsmallerTPH stph) { + input.add(new PairTPHsmallerTPH(newTph, stph.right)); + } else if (pair instanceof PairTPHequalRefTypeOrWildcardType rtph) { + input.add(new PairTPHequalRefTypeOrWildcardType(newTph, rtph.getRight())); + } + } else if (pair.getRight().equals(infimum.right)) { + input.remove(pair); + if (pair instanceof PairTPHsmallerTPH stph) { + input.add(new PairTPHsmallerTPH(stph.left, newTph)); + } + } + }); } } } From de417d3ee6bec9a0271be8660a74146777b509da Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Sun, 3 Jul 2022 18:10:40 +0200 Subject: [PATCH 55/69] Remove inner type variables --- .../target/generate/ASTToTargetAST.java | 40 ++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index 1a9589d8..6a8e2612 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -13,6 +13,7 @@ import de.dhbwstuttgart.typeinference.result.*; import java.util.*; import java.util.stream.Collectors; +import java.util.stream.Stream; public class ASTToTargetAST { @@ -268,10 +269,45 @@ public class ASTToTargetAST { } computedGenericsOfClasses.put(classOrInterface, result); eliminateCyclesAndInfima(result); + eliminateInnerTypeVariables(classOrInterface, result); System.out.println("Class " + classOrInterface.getClassName().getClassName() + ": " + result); return result; } + void findTphs(RefTypeOrTPHOrWildcardOrGeneric type, Set tphs) { + if (type instanceof RefType refType) { + refType.getParaList().forEach(t -> findTphs(t, tphs)); + } else if (type instanceof TypePlaceholder tph) { + tph = equality.getOrDefault(tph, tph); + var concreteType = concreteTypes.get(tph); + if (concreteType != null) { + findTphs(concreteType, tphs); + return; + } + tphs.add(tph); + } + } + + void eliminateInnerTypeVariables(ClassOrInterface classOrInterface, Set> input) { + Set referenced = new HashSet<>(); + for (var field : classOrInterface.getFieldDecl()) { + findTphs(field.getType(), referenced); + } + + var oldInput = new HashSet<>(input); + for (var pair : oldInput) { + if (!referenced.contains(pair.getLeft())) { + input.remove(pair); + for (var pair2 : oldInput) { + if (pair2.getRight().equals(pair.getLeft())) { + input.remove(pair2); + input.add(new PairTPHsmallerTPH((TypePlaceholder) pair2.getLeft(), (TypePlaceholder) pair.getRight())); + } + } + } + } + } + void eliminateCyclesAndInfima(Set> input) { // Eliminate cycles var cycles = findCycles(input); @@ -346,7 +382,9 @@ public class ASTToTargetAST { } static Set allNodes(Set> input) { - return input.stream().map(pair -> (TypePlaceholder) pair.getLeft()).collect(Collectors.toSet()); + return input.stream() + .filter(pair -> pair instanceof PairTPHsmallerTPH) + .flatMap(pair -> Stream.of((TypePlaceholder) pair.getLeft(), (TypePlaceholder) pair.getRight())).collect(Collectors.toSet()); } static Set outgoingEdgesOf(TypePlaceholder tph, Set> input) { From 699155e21a4041bafd3d469f681c6160b3f78b78 Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Sun, 3 Jul 2022 19:24:54 +0200 Subject: [PATCH 56/69] Equalize type variables in covariant and contravariant position --- .../target/generate/ASTToTargetAST.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index 6a8e2612..a118339b 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -270,10 +270,29 @@ public class ASTToTargetAST { computedGenericsOfClasses.put(classOrInterface, result); eliminateCyclesAndInfima(result); eliminateInnerTypeVariables(classOrInterface, result); + equalizeTypeVariables(result); + System.out.println("Class " + classOrInterface.getClassName().getClassName() + ": " + result); return result; } + void equalizeTypeVariables(Set> input) { + for (var pair : new HashSet<>(input)) { + if (pair instanceof PairTPHsmallerTPH ptph) { + if (ptph.left.getVariance() == 1 && ptph.right.getVariance() == -1) { + equality.put(ptph.left, ptph.right); + input.remove(ptph); + for (var pair2 : new HashSet<>(input)) { + if (pair2 instanceof PairTPHsmallerTPH ptph2 && ptph2.right.equals(ptph.left)) { + input.remove(pair2); + input.add(new PairTPHsmallerTPH(ptph2.left, ptph.right)); + } + } + } + } + } + } + void findTphs(RefTypeOrTPHOrWildcardOrGeneric type, Set tphs) { if (type instanceof RefType refType) { refType.getParaList().forEach(t -> findTphs(t, tphs)); From 6e1786ec7c18e241312fd2ab63dfd12f26b733b5 Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Wed, 13 Jul 2022 14:38:17 +0200 Subject: [PATCH 57/69] Test cases and some fixes --- .../target/bytecode/Codegen.java | 339 +++++++++++---- .../target/generate/ASTToTargetAST.java | 44 +- .../generate/StatementToTargetExpression.java | 15 +- .../target/tree/expression/TargetUnaryOp.java | 8 +- .../tree/type/TargetExtendsWildcard.java | 4 +- .../target/tree/type/TargetRefType.java | 15 + .../target/tree/type/TargetSuperWildcard.java | 4 +- .../java/targetast/ASTToTypedTargetAST.java | 11 +- src/test/java/targetast/GreaterEqualTest.java | 134 ++++++ src/test/java/targetast/GreaterThanTest.java | 132 ++++++ src/test/java/targetast/InheritTest.java | 102 +++++ src/test/java/targetast/InheritTest2.java | 118 ++++++ src/test/java/targetast/LessEqualTest.java | 111 +++++ src/test/java/targetast/LessThanTest.java | 119 ++++++ src/test/java/targetast/OLTest.java | 71 ++++ src/test/java/targetast/PostIncTest.java | 49 +++ src/test/java/targetast/PreIncTest.java | 49 +++ src/test/java/targetast/PutTest.java | 58 +++ src/test/java/targetast/TestCodegen.java | 100 ++++- src/test/java/targetast/TestComplete.java | 385 ++++++++++++++++++ src/test/java/targetast/TphTest.java | 58 +++ src/test/java/targetast/WhileTest.java | 47 +++ 22 files changed, 1851 insertions(+), 122 deletions(-) create mode 100644 src/test/java/targetast/GreaterEqualTest.java create mode 100644 src/test/java/targetast/GreaterThanTest.java create mode 100644 src/test/java/targetast/InheritTest.java create mode 100644 src/test/java/targetast/InheritTest2.java create mode 100644 src/test/java/targetast/LessEqualTest.java create mode 100644 src/test/java/targetast/LessThanTest.java create mode 100644 src/test/java/targetast/OLTest.java create mode 100644 src/test/java/targetast/PostIncTest.java create mode 100644 src/test/java/targetast/PreIncTest.java create mode 100644 src/test/java/targetast/PutTest.java create mode 100644 src/test/java/targetast/TestComplete.java create mode 100644 src/test/java/targetast/TphTest.java create mode 100644 src/test/java/targetast/WhileTest.java diff --git a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java index 8b540e69..948c55fd 100755 --- a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java @@ -1,6 +1,5 @@ package de.dhbwstuttgart.target.bytecode; -import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.target.tree.*; import de.dhbwstuttgart.target.tree.expression.*; import de.dhbwstuttgart.target.tree.type.TargetFunNType; @@ -13,20 +12,22 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.IntStream; import static org.objectweb.asm.Opcodes.*; import static de.dhbwstuttgart.target.tree.expression.TargetBinaryOp.*; import static de.dhbwstuttgart.target.tree.expression.TargetLiteral.*; public class Codegen { - private TargetClass clazz; - private ClassWriter cw; + private final TargetClass clazz; + private final ClassWriter cw; + public final String className; public Codegen(TargetClass clazz) { this.clazz = clazz; + this.className = clazz.qualifiedName(); this.cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); } @@ -125,14 +126,14 @@ public class Codegen { } } - private void generateRelationalOperator(State state, TargetRelationalOp op, int code) { + private void generateRelationalOperator(State state, TargetRelationalOp op, TargetType type, int code) { var mv = state.mv; Label if_true = new Label(); Label end = new Label(); generate(state, op.left()); - convertTo(state, op.exprType(), op.type()); + convertTo(state, op.left().type(), type); generate(state, op.right()); - convertTo(state, op.exprType(), op.type()); + convertTo(state, op.right().type(), type); mv.visitJumpInsn(code, if_true); mv.visitInsn(ICONST_0); mv.visitJumpInsn(GOTO, end); @@ -141,16 +142,15 @@ public class Codegen { mv.visitLabel(end); } - private void generateRelationalOperator(State state, TargetRelationalOp op, int cmp, int code) { + private void generateRelationalOperator(State state, TargetRelationalOp op, TargetType type, int cmp, int code) { var mv = state.mv; Label if_true = new Label(); Label end = new Label(); generate(state, op.left()); - convertTo(state, op.left().type(), op.exprType()); + convertTo(state, op.left().type(), type); generate(state, op.right()); - convertTo(state, op.right().type(), op.exprType()); + convertTo(state, op.right().type(), type); mv.visitInsn(cmp); - mv.visitInsn(code); mv.visitJumpInsn(code, if_true); mv.visitInsn(ICONST_0); mv.visitJumpInsn(GOTO, end); @@ -159,14 +159,35 @@ public class Codegen { mv.visitLabel(end); } + private void convertToString(State state, TargetType type) { + var mv = state.mv; + if (type.equals(TargetType.Boolean)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(Z)Ljava/lang/Boolean;", false); + } else if (type.equals(TargetType.Byte)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(B)Ljava/lang/Byte;", false); + } else if (type.equals(TargetType.Double)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(D)Ljava/lang/Double;", false); + } else if (type.equals(TargetType.Long)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(J)Ljava/lang/Long;", false); + } else if (type.equals(TargetType.Integer)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(I)Ljava/lang/Integer;", false); + } else if (type.equals(TargetType.Float)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(F)Ljava/lang/Float;", false); + } else if (type.equals(TargetType.Short)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(S)Ljava/lang/Short;", false); + } else if (type.equals(TargetType.Char)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(C)Ljava/lang/Char;", false); + } + } + private void convertTo(State state, TargetType source, TargetType dest) { var mv = state.mv; if (source.equals(dest)) return; if (source.equals(TargetType.Long)) { - if (dest.equals(TargetType.Integer)) + if (dest.equals(TargetType.Integer)) { mv.visitInsn(L2I); - else if (dest.equals(TargetType.Float)) + } else if (dest.equals(TargetType.Float)) mv.visitInsn(L2F); else if (dest.equals(TargetType.Double)) mv.visitInsn(L2D); @@ -174,7 +195,7 @@ public class Codegen { || dest.equals(TargetType.Char) || dest.equals(TargetType.Short)) { mv.visitInsn(L2I); - source = TargetType.Integer; + convertTo(state, TargetType.Integer, dest); } } else if (source.equals(TargetType.Float)) { if (dest.equals(TargetType.Integer)) @@ -187,7 +208,7 @@ public class Codegen { || dest.equals(TargetType.Char) || dest.equals(TargetType.Short)) { mv.visitInsn(F2I); - source = TargetType.Integer; + convertTo(state, TargetType.Integer, dest); } } else if (source.equals(TargetType.Double)) { if (dest.equals(TargetType.Integer)) @@ -200,10 +221,9 @@ public class Codegen { || dest.equals(TargetType.Char) || dest.equals(TargetType.Short)) { mv.visitInsn(D2I); - source = TargetType.Integer; + convertTo(state, TargetType.Integer, dest); } - } - if (source.equals(TargetType.Byte) + } else if (source.equals(TargetType.Byte) || source.equals(TargetType.Char) || source.equals(TargetType.Short) || source.equals(TargetType.Integer)) { @@ -220,33 +240,62 @@ public class Codegen { else if (dest.equals(TargetType.Double)) mv.visitInsn(I2D); } else { + boxPrimitive(state, source); mv.visitTypeInsn(CHECKCAST, dest.getName()); unboxPrimitive(state, dest); } } + private TargetType largerType(TargetType left, TargetType right) { + if (left.equals(TargetType.String) || right.equals(TargetType.String)) { + return TargetType.String; + } else if (left.equals(TargetType.Double) || right.equals(TargetType.Double)) { + return TargetType.Double; + } else if (left.equals(TargetType.Float) || right.equals(TargetType.Float)) { + return TargetType.Float; + } else if (left.equals(TargetType.Long) || right.equals(TargetType.Long)) { + return TargetType.Long; + } else { + return TargetType.Integer; + } + } + private void generateBinaryOp(State state, TargetBinaryOp op) { var mv = state.mv; switch (op) { case Add add: { - generate(state, add.left()); - convertTo(state, add.left().type(), op.type()); - generate(state, add.right()); - convertTo(state, add.right().type(), op.type()); - var type = add.type(); - if (type.equals(TargetType.Byte) - || type.equals(TargetType.Char) - || type.equals(TargetType.Integer) - || type.equals(TargetType.Short)) { - mv.visitInsn(IADD); - } else if (type.equals(TargetType.Long)) { - mv.visitInsn(LADD); - } else if (type.equals(TargetType.Float)) { - mv.visitInsn(FADD); - } else if (type.equals(TargetType.Double)) { - mv.visitInsn(DADD); + if (add.type().equals(TargetType.String)) { + mv.visitTypeInsn(NEW, "java/lang/StringBuilder"); + mv.visitInsn(DUP); + generate(state, add.left()); + convertToString(state, add.left().type()); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "", "(Ljava/lang/String;)V", false); } else { - throw new CodeGenException("Invalid argument to Add expression"); + generate(state, add.left()); + convertTo(state, add.left().type(), add.type()); + generate(state, add.right()); + convertTo(state, add.right().type(), add.type()); + var type = add.type(); + if (type.equals(TargetType.Byte) + || type.equals(TargetType.Char) + || type.equals(TargetType.Integer) + || type.equals(TargetType.Short)) { + mv.visitInsn(IADD); + } else if (type.equals(TargetType.Long)) { + mv.visitInsn(LADD); + } else if (type.equals(TargetType.Float)) { + mv.visitInsn(FADD); + } else if (type.equals(TargetType.Double)) { + mv.visitInsn(DADD); + } else { + throw new CodeGenException("Invalid argument to Add expression"); + } + } + if (add.type().equals(TargetType.String)) { + generate(state, add.right()); + convertToString(state, add.right().type()); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false); } break; } @@ -429,106 +478,231 @@ public class Codegen { break; } case Greater greater: { - var type = greater.exprType(); + var type = largerType(greater.left().type(), greater.right().type()); if (type.equals(TargetType.Long)) { - generateRelationalOperator(state, greater, LCMP, IFGT); + generateRelationalOperator(state, greater, type, LCMP, IFGT); } else if (type.equals(TargetType.Float)) { - generateRelationalOperator(state, greater, FCMPL, IFGT); + generateRelationalOperator(state, greater, type, FCMPL, IFGT); } else if (type.equals(TargetType.Double)) { - generateRelationalOperator(state, greater, DCMPL, IFGT); + generateRelationalOperator(state, greater, type, DCMPL, IFGT); } else { - generateRelationalOperator(state, greater, IF_ICMPGT); + generateRelationalOperator(state, greater, type, IF_ICMPGT); } break; } case Less less: { - var type = less.exprType(); + var type = largerType(less.left().type(), less.right().type()); if (type.equals(TargetType.Long)) { - generateRelationalOperator(state, less, LCMP, IFLT); + generateRelationalOperator(state, less, type, LCMP, IFLT); } else if (type.equals(TargetType.Float)) { - generateRelationalOperator(state, less, FCMPL, IFLT); + generateRelationalOperator(state, less, type, FCMPL, IFLT); } else if (type.equals(TargetType.Double)) { - generateRelationalOperator(state, less, DCMPL, IFLT); + generateRelationalOperator(state, less, type, DCMPL, IFLT); } else { - generateRelationalOperator(state, less, IF_ICMPLT); + generateRelationalOperator(state, less, type, IF_ICMPLT); } break; } case GreaterOrEqual greaterOrEqual: { - var type = greaterOrEqual.exprType(); + var type = largerType(greaterOrEqual.left().type(), greaterOrEqual.right().type()); if (type.equals(TargetType.Long)) { - generateRelationalOperator(state, greaterOrEqual, LCMP, IFGE); + generateRelationalOperator(state, greaterOrEqual, type, LCMP, IFGE); } else if (type.equals(TargetType.Float)) { - generateRelationalOperator(state, greaterOrEqual, FCMPL, IFGE); + generateRelationalOperator(state, greaterOrEqual, type, FCMPL, IFGE); } else if (type.equals(TargetType.Double)) { - generateRelationalOperator(state, greaterOrEqual, DCMPL, IFGE); + generateRelationalOperator(state, greaterOrEqual, type, DCMPL, IFGE); } else { - generateRelationalOperator(state, greaterOrEqual, IF_ICMPGE); + generateRelationalOperator(state, greaterOrEqual, type, IF_ICMPGE); } break; } case LessOrEqual lessOrEqual: { - var type = lessOrEqual.exprType(); + var type = largerType(lessOrEqual.left().type(), lessOrEqual.right().type()); if (type.equals(TargetType.Long)) { - generateRelationalOperator(state, lessOrEqual, LCMP, IFLE); + generateRelationalOperator(state, lessOrEqual, type, LCMP, IFLE); } else if (type.equals(TargetType.Float)) { - generateRelationalOperator(state, lessOrEqual, FCMPL, IFLE); + generateRelationalOperator(state, lessOrEqual, type, FCMPL, IFLE); } else if (type.equals(TargetType.Double)) { - generateRelationalOperator(state, lessOrEqual, DCMPL, IFLE); + generateRelationalOperator(state, lessOrEqual, type, DCMPL, IFLE); } else { - generateRelationalOperator(state, lessOrEqual, IF_ICMPLE); + generateRelationalOperator(state, lessOrEqual, type, IF_ICMPLE); } break; } case Equal equal: { - var type = equal.exprType(); + var type = largerType(equal.left().type(), equal.right().type()); if (type.equals(TargetType.Long)) { - generateRelationalOperator(state, equal, LCMP, IFEQ); + generateRelationalOperator(state, equal, type, LCMP, IFEQ); } else if (type.equals(TargetType.Float)) { - generateRelationalOperator(state, equal, FCMPL, IFEQ); + generateRelationalOperator(state, equal, type, FCMPL, IFEQ); } else if (type.equals(TargetType.Double)) { - generateRelationalOperator(state, equal, DCMPL, IFEQ); + generateRelationalOperator(state, equal, type, DCMPL, IFEQ); } else if (type.equals(TargetType.Char) || type.equals(TargetType.Short) || type.equals(TargetType.Byte) - || type.equals(TargetType.Integer)) { - generateRelationalOperator(state, equal, IF_ICMPEQ); + || type.equals(TargetType.Integer) + || type.equals(TargetType.Boolean)) { + generateRelationalOperator(state, equal, type, IF_ICMPEQ); } else { - generateRelationalOperator(state, equal, IF_ACMPEQ); + generateRelationalOperator(state, equal, type, IF_ACMPEQ); } break; } case NotEqual notEqual: { - var type = notEqual.exprType(); + var type = largerType(notEqual.left().type(), notEqual.right().type()); if (type.equals(TargetType.Long)) { - generateRelationalOperator(state, notEqual, LCMP, IFNE); + generateRelationalOperator(state, notEqual, type, LCMP, IFNE); } else if (type.equals(TargetType.Float)) { - generateRelationalOperator(state, notEqual, FCMPL, IFNE); + generateRelationalOperator(state, notEqual, type, FCMPL, IFNE); } else if (type.equals(TargetType.Double)) { - generateRelationalOperator(state, notEqual, DCMPL, IFNE); + generateRelationalOperator(state, notEqual, type, DCMPL, IFNE); } else if (type.equals(TargetType.Char) || type.equals(TargetType.Short) || type.equals(TargetType.Byte) || type.equals(TargetType.Integer)) { - generateRelationalOperator(state, notEqual, IF_ICMPNE); + generateRelationalOperator(state, notEqual, type, IF_ICMPNE); } else { - generateRelationalOperator(state, notEqual, IF_ACMPNE); + generateRelationalOperator(state, notEqual, type, IF_ACMPNE); } break; } } } + private void afterIncDec(State state, TargetUnaryOp op) { + var mv = state.mv; + if (op.expr() instanceof TargetLocalVar localVar) { + mv.visitVarInsn(ASTORE, state.scope.get(localVar.name()).index); + } else if (op.expr() instanceof TargetFieldVar fieldVar) { + generate(state, fieldVar.left()); + mv.visitInsn(SWAP); + mv.visitFieldInsn(PUTFIELD, fieldVar.owner().getName(), fieldVar.right(), fieldVar.type().toSignature()); + } + } + private void generateUnaryOp(State state, TargetUnaryOp op) { - // TODO - throw new NotImplementedException(); + var mv = state.mv; + switch (op) { + case TargetUnaryOp.Add add: + // This literally does nothing + generate(state, add.expr()); + break; + case TargetUnaryOp.Negate negate: + generate(state, negate.expr()); + if (negate.type().equals(TargetType.Double)) + mv.visitInsn(DNEG); + else if (negate.type().equals(TargetType.Float)) + mv.visitInsn(FNEG); + else if (negate.type().equals(TargetType.Long)) + mv.visitInsn(LNEG); + else mv.visitInsn(INEG); + break; + case TargetUnaryOp.Not not: + generate(state, not.expr()); + if (not.type().equals(TargetType.Long)) { + mv.visitLdcInsn(-1L); + mv.visitInsn(LXOR); + } else { + mv.visitInsn(ICONST_M1); + mv.visitInsn(IXOR); + } + break; + case TargetUnaryOp.PreIncrement preIncrement: + generate(state, preIncrement.expr()); + if (preIncrement.type().equals(TargetType.Float)) { + mv.visitLdcInsn(1F); + mv.visitInsn(FADD); + mv.visitInsn(DUP); + } else if (preIncrement.type().equals(TargetType.Double)) { + mv.visitLdcInsn(1D); + mv.visitInsn(DADD); + mv.visitInsn(DUP2); + } else if (preIncrement.type().equals(TargetType.Long)) { + mv.visitLdcInsn(1L); + mv.visitInsn(LADD); + mv.visitInsn(DUP2); + } else { + mv.visitLdcInsn(1); + mv.visitInsn(IADD); + mv.visitInsn(DUP); + } + boxPrimitive(state, preIncrement.type()); + afterIncDec(state, preIncrement); + break; + case TargetUnaryOp.PreDecrement preDecrement: + generate(state, preDecrement.expr()); + if (preDecrement.type().equals(TargetType.Float)) { + mv.visitLdcInsn(1F); + mv.visitInsn(FSUB); + mv.visitInsn(DUP); + } else if (preDecrement.type().equals(TargetType.Double)) { + mv.visitLdcInsn(1D); + mv.visitInsn(DSUB); + mv.visitInsn(DUP2); + } else if (preDecrement.type().equals(TargetType.Long)) { + mv.visitLdcInsn(1L); + mv.visitInsn(LSUB); + mv.visitInsn(DUP2); + } else { + mv.visitLdcInsn(1); + mv.visitInsn(ISUB); + mv.visitInsn(DUP); + } + boxPrimitive(state, preDecrement.type()); + afterIncDec(state, preDecrement); + break; + case TargetUnaryOp.PostIncrement postIncrement: + generate(state, postIncrement.expr()); + if (postIncrement.type().equals(TargetType.Float)) { + mv.visitInsn(DUP); + mv.visitLdcInsn(1F); + mv.visitInsn(FADD); + } else if (postIncrement.type().equals(TargetType.Double)) { + mv.visitInsn(DUP2); + mv.visitLdcInsn(1D); + mv.visitInsn(DADD); + } else if (postIncrement.type().equals(TargetType.Long)) { + mv.visitInsn(DUP2); + mv.visitLdcInsn(1L); + mv.visitInsn(LADD); + } else { + mv.visitInsn(DUP); + mv.visitLdcInsn(1); + mv.visitInsn(IADD); + } + boxPrimitive(state, postIncrement.type()); + afterIncDec(state, postIncrement); + break; + case TargetUnaryOp.PostDecrement postDecrement: + generate(state, postDecrement.expr()); + if (postDecrement.type().equals(TargetType.Float)) { + mv.visitInsn(DUP); + mv.visitLdcInsn(1F); + mv.visitInsn(FSUB); + } else if (postDecrement.type().equals(TargetType.Double)) { + mv.visitInsn(DUP2); + mv.visitLdcInsn(1D); + mv.visitInsn(DSUB); + } else if (postDecrement.type().equals(TargetType.Long)) { + mv.visitInsn(DUP2); + mv.visitLdcInsn(1L); + mv.visitInsn(LSUB); + } else { + mv.visitInsn(DUP); + mv.visitLdcInsn(1); + mv.visitInsn(ISUB); + } + boxPrimitive(state, postDecrement.type()); + afterIncDec(state, postDecrement); + break; + } } private void generateLambdaExpression(State state, TargetLambdaExpression lambda) { var mv = state.mv; var name = "lambda$" + state.lambdaCounter; var impl = new TargetMethod( - ACC_PRIVATE, name, Set.of(), + 0, name, Set.of(), lambda.params(), lambda.returnType(), lambda.block() ); generateMethod(impl); @@ -665,6 +839,7 @@ public class Codegen { if (!dot.isStatic()) generate(state, dot.left()); mv.visitFieldInsn(dot.isStatic() ? GETSTATIC : GETFIELD, dot.left().type().getName(), dot.right(), dot.type().toSignature()); + unboxPrimitive(state, dot.type()); break; } case TargetFor _for: { @@ -738,8 +913,17 @@ public class Codegen { generate(state, e); boxPrimitive(state, e.type()); } - mv.visitMethodInsn(call.isInterface() ? INVOKEINTERFACE : call.isStatic() ? INVOKESTATIC: call.name() == "" ? INVOKESPECIAL : INVOKEVIRTUAL, - call.owner().getName(), call.name(), call.getDescriptor(), call.isInterface()); + var descriptor = call.getDescriptor(); + if (call.owner() instanceof TargetFunNType) // Decay FunN + descriptor = TargetMethod.getDescriptor( + call.type() == null ? null : TargetType.Object, + call.parameterTypes().stream().map(x -> TargetType.Object).toArray(TargetType[]::new) + ); + + mv.visitMethodInsn(call.isInterface() ? INVOKEINTERFACE : call.isStatic() ? INVOKESTATIC: call.name().equals("") ? INVOKESPECIAL : INVOKEVIRTUAL, + call.owner().getName(), call.name(), descriptor, call.isInterface()); + if (call.owner() instanceof TargetFunNType) + mv.visitTypeInsn(CHECKCAST, call.type().getName()); if (call.type() != null) unboxPrimitive(state, call.type()); break; @@ -763,11 +947,11 @@ public class Codegen { } private void generateField(TargetField field) { - cw.visitField(field.access(), field.name(), field.type().toSignature(), field.type().toGenericSignature(), null); + cw.visitField(field.access() | ACC_PUBLIC, field.name(), field.type().toSignature(), field.type().toGenericSignature(), null); } private void generateConstructor(TargetConstructor constructor) { - MethodVisitor mv = cw.visitMethod(constructor.access(), "", constructor.getDescriptor(), constructor.getSignature(), null); + MethodVisitor mv = cw.visitMethod(constructor.access() | ACC_PUBLIC, "", constructor.getDescriptor(), constructor.getSignature(), null); mv.visitCode(); var state = new State(mv, 1); for (var param: constructor.parameters()) @@ -779,7 +963,8 @@ public class Codegen { } private void generateMethod(TargetMethod method) { - MethodVisitor mv = cw.visitMethod(method.access(), method.name(), method.getDescriptor(), method.getSignature(), null); + // TODO The older codegen has set ACC_PUBLIC for all methods, good for testing but bad for everything else + MethodVisitor mv = cw.visitMethod(method.access() | ACC_PUBLIC, method.name(), method.getDescriptor(), method.getSignature(), null); mv.visitCode(); var state = new State(mv, method.isStatic() ? 0 : 1); for (var param: method.parameters()) @@ -803,7 +988,7 @@ public class Codegen { } public byte[] generate() { - cw.visit(V1_8, clazz.modifiers(), clazz.qualifiedName(), + cw.visit(V1_8, clazz.modifiers() | ACC_PUBLIC, clazz.qualifiedName(), generateSignature(clazz), clazz.superType() != null ? clazz.superType().getName(): "java/lang/Object", clazz.implementingInterfaces().stream().map(TargetType::toSignature).toArray(String[]::new) ); diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index a118339b..b1eea73c 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -1,5 +1,6 @@ package de.dhbwstuttgart.target.generate; +import de.dhbwstuttgart.bytecode.funN.FunNGenerator; import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; @@ -25,6 +26,7 @@ public class ASTToTargetAST { private class Sigma { Map>> computedGenericsOfMethods = new HashMap<>(); + Map> usedTPHsOfMethods = new HashMap<>(); Map>> computedGenericsOfClasses = new HashMap<>(); Set simplifiedConstraints = new HashSet<>(); @@ -142,14 +144,16 @@ public class ASTToTargetAST { 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(); + if (optMethod.isEmpty()) return; var method = optMethod.get(); var generics = generics(owner, method); Set> all = new HashSet<>(generics); // Reflexive and Transitive closure HashSet> toAdd = new HashSet<>(); + int sizeBefore; do { + sizeBefore = all.size(); toAdd.clear(); for (var g1 : all) { for (var g2 : all) { @@ -160,7 +164,7 @@ public class ASTToTargetAST { } } all.addAll(toAdd); - } while (toAdd.size() > 0); + } while (sizeBefore < all.size()); for (var generic : all) { toAdd.add(new PairTPHsmallerTPH((TypePlaceholder) generic.getLeft(), (TypePlaceholder) generic.getLeft())); } @@ -231,6 +235,11 @@ public class ASTToTargetAST { eliminateCyclesAndInfima(result); System.out.println(method.name + ": " + result); + Set allUsedTPHs = new HashSet<>(); + allUsedTPHs.addAll(typeVariables); + allUsedTPHs.addAll(typeVariablesOfFields); + usedTPHsOfMethods.put(method, allUsedTPHs); + return result; } @@ -248,8 +257,11 @@ public class ASTToTargetAST { var left = equality.getOrDefault(rsp.left, rsp.left); var right = equality.getOrDefault(rsp.right, rsp.right); if (left.equals(tph)) { - generics.add(new PairTPHsmallerTPH(tph, right)); - findAllBounds(right, generics); + var pair = new PairTPHsmallerTPH(tph, right); + if (!generics.contains(pair)) { + generics.add(pair); + findAllBounds(right, generics); + } return; } } @@ -312,6 +324,10 @@ public class ASTToTargetAST { for (var field : classOrInterface.getFieldDecl()) { findTphs(field.getType(), referenced); } + for (var method : classOrInterface.getMethods()) { + generics(classOrInterface, method); + referenced.addAll(usedTPHsOfMethods.get(method)); + } var oldInput = new HashSet<>(input); for (var pair : oldInput) { @@ -320,7 +336,10 @@ public class ASTToTargetAST { for (var pair2 : oldInput) { if (pair2.getRight().equals(pair.getLeft())) { input.remove(pair2); - input.add(new PairTPHsmallerTPH((TypePlaceholder) pair2.getLeft(), (TypePlaceholder) pair.getRight())); + if (pair instanceof PairTPHsmallerTPH) + input.add(new PairTPHsmallerTPH((TypePlaceholder) pair2.getLeft(), (TypePlaceholder) pair.getRight())); + else + input.add(new PairTPHequalRefTypeOrWildcardType((TypePlaceholder) pair2.getLeft(), pair.getRight())); } } } @@ -361,7 +380,7 @@ public class ASTToTargetAST { input.removeAll(infima); for (var infimum : infima) { equality.put(infimum.right, newTph); - new HashSet<>(input).stream().forEach(pair -> { + new HashSet<>(input).forEach(pair -> { if (pair.getLeft().equals(infimum.right)) { input.remove(pair); if (pair instanceof PairTPHsmallerTPH stph) { @@ -417,6 +436,7 @@ public class ASTToTargetAST { } // Tiernan simple cycles algorithm + // Adapted from https://github.com/jgrapht/jgrapht/blob/master/jgrapht-core/src/main/java/org/jgrapht/alg/cycle/TiernanSimpleCycles.java static Set> findCycles(Set> input) { Map indices = new HashMap<>(); List path = new ArrayList<>(); @@ -576,6 +596,12 @@ public class ASTToTargetAST { ); } + private Set usedFunN = new HashSet<>(); + + public List generateUsedFunNTypes() { + return usedFunN.stream().map(n -> FunNGenerator.getInstance().generateSuperBytecode(n)).toList(); + } + protected TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input) { return input.acceptTV(new TypeVisitor<>() { @Override @@ -584,8 +610,10 @@ 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 - return new TargetFunNType(params.size(), params); + if (name.matches("Fun\\d\\$\\$")) { // TODO This seems like a bad idea + usedFunN.add(params.size() - 1); + return new TargetFunNType(params.size() - 1, params); + } return new TargetRefType(name, params); } diff --git a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java index 53b69066..79338248 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java @@ -8,6 +8,7 @@ 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 de.dhbwstuttgart.target.tree.type.TargetType; import java.util.List; import java.util.stream.StreamSupport; @@ -127,20 +128,24 @@ public class StatementToTargetExpression implements StatementVisitor { @Override public void visit(MethodCall methodCall) { + var receiverType = converter.convert(methodCall.receiver.getType()); + var isFunNType = receiverType instanceof TargetFunNType; + var returnType = converter.convert(methodCall.getType()); + result = new TargetMethodCall( - converter.convert(methodCall.getType()), - methodCall.argTypes == null ? List.of() : methodCall.argTypes.stream().map(converter::convert).toList(), + returnType, + methodCall.arglist.getArguments().stream().map(expr -> converter.convert(expr.getType())).toList(), converter.convert(methodCall.receiver), methodCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), - converter.convert(methodCall.receiver.getType()), - methodCall.name, false, false + receiverType, + methodCall.name, false, isFunNType ); } @Override public void visit(NewClass newClass) { result = new TargetNew( - converter.convert(newClass.receiverType), + new TargetRefType(newClass.name), newClass.getArgumentList().getArguments().stream().map(converter::convert).toList() ); } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetUnaryOp.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetUnaryOp.java index 2f733e45..92e57647 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetUnaryOp.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetUnaryOp.java @@ -9,8 +9,8 @@ public sealed interface TargetUnaryOp extends TargetExpression { record Add(TargetType type, TargetExpression expr) implements TargetUnaryOp {} record Not(TargetType type, TargetExpression expr) implements TargetUnaryOp {} - record PreIncrement(TargetType type, TargetExpression expr) implements TargetStatementExpression {} - record PostIncrement(TargetType type, TargetExpression expr) implements TargetStatementExpression {} - record PreDecrement(TargetType type, TargetExpression expr) implements TargetStatementExpression {} - record PostDecrement(TargetType type, TargetExpression expr) implements TargetStatementExpression {} + record PreIncrement(TargetType type, TargetExpression expr) implements TargetStatementExpression, TargetUnaryOp {} + record PostIncrement(TargetType type, TargetExpression expr) implements TargetStatementExpression, TargetUnaryOp {} + record PreDecrement(TargetType type, TargetExpression expr) implements TargetStatementExpression, TargetUnaryOp {} + record PostDecrement(TargetType type, TargetExpression expr) implements TargetStatementExpression, TargetUnaryOp {} } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java index 5d32fb1b..533472c8 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java @@ -3,12 +3,12 @@ package de.dhbwstuttgart.target.tree.type; public record TargetExtendsWildcard(TargetType innerType) implements TargetType { @Override public String toSignature() { - return null; + return innerType.toSignature(); } @Override public String toGenericSignature() { - return null; + return innerType.toGenericSignature(); } @Override 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 98878f93..bdd92e03 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetRefType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetRefType.java @@ -3,6 +3,7 @@ package de.dhbwstuttgart.target.tree.type; import de.dhbwstuttgart.target.tree.type.TargetType; import java.util.List; +import java.util.Objects; public record TargetRefType(String name, List params) implements TargetSpecializedType { public TargetRefType(String name) { @@ -17,4 +18,18 @@ public record TargetRefType(String name, List params) implements Tar public String toSignature() { return "L" + getName() + ";"; } + + // Type erasure means we need to override hashCode and equals to only consider the name + @Override + public int hashCode() { + return Objects.hashCode(name); + } + + @Override + public boolean equals(Object other) { + if (other instanceof TargetRefType refType) { + return refType.name.equals(name); + } + return false; + } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java index 3306d14d..101a3a53 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java @@ -3,12 +3,12 @@ package de.dhbwstuttgart.target.tree.type; public record TargetSuperWildcard(TargetType innerType) implements TargetType { @Override public String toSignature() { - return null; + return innerType.toSignature(); } @Override public String toGenericSignature() { - return null; + return innerType.toGenericSignature(); } @Override diff --git a/src/test/java/targetast/ASTToTypedTargetAST.java b/src/test/java/targetast/ASTToTypedTargetAST.java index 6f914432..4a46db0c 100644 --- a/src/test/java/targetast/ASTToTypedTargetAST.java +++ b/src/test/java/targetast/ASTToTypedTargetAST.java @@ -38,8 +38,9 @@ public class ASTToTypedTargetAST { var converter = new ASTToTargetAST(resultSet); var classes = compiler.sourceFiles.get(file).getClasses(); - var overloading = TestCodegen.generateClass(converter.convert(classes.get(0))); - var overloading2 = TestCodegen.generateClass(converter.convert(classes.get(1))); + var classLoader = new ByteArrayClassLoader(); + var overloading = TestCodegen.generateClass(converter.convert(classes.get(0)), classLoader); + var overloading2 = TestCodegen.generateClass(converter.convert(classes.get(1)), classLoader); var test1 = overloading.getDeclaredMethod("test", overloading); test1.setAccessible(true); @@ -59,7 +60,7 @@ public class ASTToTypedTargetAST { var converter = new ASTToTargetAST(resultSet); var classes = compiler.sourceFiles.get(file).getClasses(); - var tphAndGenerics = TestCodegen.generateClass(converter.convert(classes.get(0))); + var tphAndGenerics = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader()); } @Test @@ -70,7 +71,7 @@ public class ASTToTypedTargetAST { var converter = new ASTToTargetAST(resultSet); var classes = compiler.sourceFiles.get(file).getClasses(); - var cycle = TestCodegen.generateClass(converter.convert(classes.get(0))); + var cycle = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader()); } @Test @@ -81,6 +82,6 @@ public class ASTToTypedTargetAST { var converter = new ASTToTargetAST(resultSet); var classes = compiler.sourceFiles.get(file).getClasses(); - var infimum = TestCodegen.generateClass(converter.convert(classes.get(0))); + var infimum = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader()); } } diff --git a/src/test/java/targetast/GreaterEqualTest.java b/src/test/java/targetast/GreaterEqualTest.java new file mode 100644 index 00000000..ac9216c9 --- /dev/null +++ b/src/test/java/targetast/GreaterEqualTest.java @@ -0,0 +1,134 @@ +package targetast; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class GreaterEqualTest { + static Class classToTest; + static Object instance; + + @BeforeClass + public static void beforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("GreaterEqual.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("GreaterEqual"); + instance = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testIntegers() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Integer.class, Integer.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 7, 5); + assertTrue(result); + } + + @Test + public void testIntegers2() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Integer.class, Integer.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 5, 7); + assertFalse(result); + } + + @Test + public void testEqIntegers() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Integer.class, Integer.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 5, 5); + assertTrue(result); + } + + @Test + public void testLongs() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Long.class, Long.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 10L, 7L); + assertTrue(result); + } + + @Test + public void testFloats() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Float.class, Float.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 5F, 7F); + assertFalse(result); + } + + @Test + public void testDoubles() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Double.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 5.0, 7.0); + assertFalse(result); + } + + @Test + public void testLongInt() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Long.class, Integer.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 15L, 7); + assertTrue(result); + } + + @Test + public void testFloatInt() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Float.class, Integer.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 5F, 7); + assertFalse(result); + } + + @Test + public void testDoubleInt() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Integer.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 25.0, 17); + assertTrue(result); + } + + @Test + public void testFloatLong() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Float.class, Long.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 75F, 70L); + assertTrue(result); + } + + @Test + public void testDoubleLong() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Long.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 5.0, 7L); + assertFalse(result); + } + + @Test + public void testEqDoubleFloat() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Float.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 7.0, 7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Float.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 15.0, 7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat3() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Float.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 9.0, 17F); + assertFalse(result); + } +} diff --git a/src/test/java/targetast/GreaterThanTest.java b/src/test/java/targetast/GreaterThanTest.java new file mode 100644 index 00000000..c5684c5a --- /dev/null +++ b/src/test/java/targetast/GreaterThanTest.java @@ -0,0 +1,132 @@ +package targetast; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class GreaterThanTest { + static Class classToTest; + static Object instance; + + @BeforeClass + public static void beforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("GreaterThan.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("GreaterThan"); + instance = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testIntegers() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Integer.class, Integer.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 7, 5); + assertTrue(result); + } + + @Test + public void testIntegers2() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Integer.class, Integer.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 5, 7); + assertFalse(result); + } + + @Test + public void testEqIntegers() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Integer.class, Integer.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 5, 5); + assertFalse(result); + } + + @Test + public void testLongs() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Long.class, Long.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 10L,7L); + assertTrue(result); + }@Test + + public void testFloats() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Float.class, Float.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 5F,7F); + assertFalse(result); + } + + @Test + public void testDoubles() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Double.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 5.0,7.0); + assertFalse(result); + } + + @Test + public void testLongInt() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Long.class, Integer.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 15L,7); + assertTrue(result); + } + + @Test + public void testFloatInt() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Float.class, Integer.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 5F,7); + assertFalse(result); + } + + @Test + public void testDoubleInt() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Integer.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 25.0,17); + assertTrue(result); + } + + @Test + public void testFloatLong() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Float.class, Long.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 75F,70L); + assertTrue(result); + } + + @Test + public void testDoubleLong() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Long.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 5.0,7L); + assertFalse(result); + } + + @Test + public void testEqDoubleFloat() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Float.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 7.0,7F); + assertFalse(result); + } + + @Test + public void testDoubleFloat() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Float.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 15.0,7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat3() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Float.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 9.0,17F); + assertFalse(result); + } +} diff --git a/src/test/java/targetast/InheritTest.java b/src/test/java/targetast/InheritTest.java new file mode 100644 index 00000000..fcf276a9 --- /dev/null +++ b/src/test/java/targetast/InheritTest.java @@ -0,0 +1,102 @@ +package targetast; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; +import java.util.Vector; + +import static org.junit.Assert.assertEquals; + +public class InheritTest { + private static Class classToTest, classToTestAA, classToTestBB, classToTestCC, classToTestDD; + private static Object instanceOfClass, instanceOfClassAA, instanceOfClassBB, instanceOfClassCC, instanceOfClassDD; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + var classLoader = new ByteArrayClassLoader(); + classToTest = TestCodegen.generateClassFiles("Inherit.jav", classLoader).get("Inherit"); + classToTestAA = TestCodegen.generateClassFiles("AA.jav", classLoader).get("AA"); + classToTestBB = TestCodegen.generateClassFiles("BB.jav", classLoader).get("BB"); + classToTestCC = TestCodegen.generateClassFiles("CC.jav", classLoader).get("CC"); + classToTestDD = TestCodegen.generateClassFiles("DD.jav", classLoader).get("DD"); + + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + instanceOfClassAA = classToTestAA.getDeclaredConstructor().newInstance(); + instanceOfClassBB = classToTestBB.getDeclaredConstructor().newInstance(); + instanceOfClassCC = classToTestCC.getDeclaredConstructor().newInstance(); + instanceOfClassDD = classToTestDD.getDeclaredConstructor().newInstance(); + } + + @Test + public void testmainAA() throws Exception { + Method m = classToTestAA.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassAA, 5), "AA"); + Method main = classToTest.getDeclaredMethod("main", classToTestAA, Integer.class); + assertEquals(main.invoke(instanceOfClass, instanceOfClassAA, 5), "AA"); + } + + @Test + public void testmainBB() throws Exception { + Method m = classToTestAA.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassBB, 5), "AA"); + Method main = classToTest.getDeclaredMethod("main", classToTestAA, Integer.class); + assertEquals(main.invoke(instanceOfClass, instanceOfClassBB, 5), "AA"); + } + + @Test + public void testmainCC() throws Exception { + Method m = classToTestCC.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassCC, 5), "CC"); + Method main = classToTest.getDeclaredMethod("main", classToTestCC, Integer.class); + assertEquals(main.invoke(instanceOfClass, instanceOfClassCC, 5), "CC"); + } + + @Test + public void testmainDD() throws Exception { + Method m = classToTestCC.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassDD, 5), "CC"); + Method main = classToTest.getDeclaredMethod("main", classToTestCC, Integer.class); + assertEquals(main.invoke(instanceOfClass, instanceOfClassDD, 5), "CC"); + } + + @Test + public void testmainVectorAA() throws Exception { + Method m = classToTestAA.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassAA, 5), "AA"); + Vector v = new Vector<>(); + v.add(instanceOfClassAA); + Method main = classToTest.getDeclaredMethod("main", Vector.class, Integer.class); + assertEquals(main.invoke(instanceOfClass, v, 5), "AA"); + } + + @Test + public void testmainVectorBB() throws Exception { + Method m = classToTestAA.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassBB, 5), "AA"); + Vector v = new Vector<>(); + v.add(instanceOfClassBB); + Method main = classToTest.getDeclaredMethod("main", Vector.class, Integer.class); + assertEquals(main.invoke(instanceOfClass, v, 5), "AA"); + } + + @Test + public void testmainVectorCC() throws Exception { + Method m = classToTestCC.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassCC, 5), "CC"); + Vector v = new Vector<>(); + v.add(instanceOfClassCC); + Method main = classToTest.getDeclaredMethod("main", Vector.class, Integer.class); + assertEquals(main.invoke(instanceOfClass, v, 5), "CC"); + } + + @Test + public void testmainVectorDD() throws Exception { + Method m = classToTestCC.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassDD, 5), "CC"); + Vector v = new Vector<>(); + v.add(instanceOfClassDD); + Method main = classToTest.getDeclaredMethod("main", Vector.class, Integer.class); + assertEquals(main.invoke(instanceOfClass, v, 5), "CC"); + } +} diff --git a/src/test/java/targetast/InheritTest2.java b/src/test/java/targetast/InheritTest2.java new file mode 100644 index 00000000..a6ec9227 --- /dev/null +++ b/src/test/java/targetast/InheritTest2.java @@ -0,0 +1,118 @@ +package targetast; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; +import java.util.Vector; + +import static org.junit.Assert.assertEquals; + +public class InheritTest2 { + private static Class classToTest, classToTestAA, classToTestBB, classToTestCC, classToTestDD; + private static Object instanceOfClass, instanceOfClassAA, instanceOfClassBB, instanceOfClassCC, instanceOfClassDD; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + var classLoader = new ByteArrayClassLoader(); + classToTest = TestCodegen.generateClassFiles("Inherit.jav", classLoader).get("Inherit2"); + classToTestAA = TestCodegen.generateClassFiles("AA.jav", classLoader).get("AA"); + classToTestBB = TestCodegen.generateClassFiles("BB.jav", classLoader).get("BB"); + classToTestCC = TestCodegen.generateClassFiles("CC.jav", classLoader).get("CC"); + classToTestDD = TestCodegen.generateClassFiles("DD.jav", classLoader).get("DD"); + + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + instanceOfClassAA = classToTestAA.getDeclaredConstructor().newInstance(); + instanceOfClassBB = classToTestBB.getDeclaredConstructor().newInstance(); + instanceOfClassCC = classToTestCC.getDeclaredConstructor().newInstance(); + instanceOfClassDD = classToTestDD.getDeclaredConstructor().newInstance(); + } + + @Test + public void testmainAA() throws Exception { + Method m2 = classToTestAA.getDeclaredMethod("m2", classToTestAA); + assertEquals(m2.invoke(instanceOfClassAA, instanceOfClassAA), "AA"); + Method main = classToTest.getDeclaredMethod("main", classToTestAA); + assertEquals(main.invoke(instanceOfClass, instanceOfClassAA), "AA"); + } + + @Test + public void testmainBB() throws Exception { + Method m2 = classToTestAA.getDeclaredMethod("m2", classToTestAA); + assertEquals(m2.invoke(instanceOfClassAA, instanceOfClassAA), "AA"); + Method main = classToTest.getDeclaredMethod("main", classToTestAA); + assertEquals(main.invoke(instanceOfClass, instanceOfClassBB), "AA"); + } + + @Test + public void testmainCC() throws Exception { + Method m2 = classToTestCC.getDeclaredMethod("m2", classToTestCC); + assertEquals(m2.invoke(instanceOfClassCC, instanceOfClassCC), "CC"); + Method main = classToTest.getDeclaredMethod("main", classToTestCC); + assertEquals(main.invoke(instanceOfClass, instanceOfClassCC), "CC"); + } + + @Test + public void testmainDD() throws Exception { + Method m2 = classToTestCC.getDeclaredMethod("m2", classToTestCC); + assertEquals(m2.invoke(instanceOfClassCC, instanceOfClassCC), "CC"); + Method main = classToTest.getDeclaredMethod("main", classToTestCC); + assertEquals(main.invoke(instanceOfClass, instanceOfClassDD), "CC"); + } + + + //PL 2020-05-12: Die folgenden Test funktionieren erst, wenn Generics im Bytecode implementiert sind + @Test + public void testmainVectorAA() throws Exception { + Method m2 = classToTestAA.getDeclaredMethod("m2", classToTestAA); + assertEquals(m2.invoke(instanceOfClassAA, instanceOfClassAA), "AA"); + Vector v = new Vector<>(); + v.add(instanceOfClassAA); + Method main = classToTest.getDeclaredMethod("main", Vector.class); + try { + assertEquals(main.invoke(instanceOfClass, v), "AA"); + } + catch (java.lang.reflect.InvocationTargetException e) { + testmainVectorCC(); + } + } + + @Test + public void testmainVectorBB() throws Exception { + Method m2 = classToTestAA.getDeclaredMethod("m2", classToTestAA); + assertEquals(m2.invoke(instanceOfClassAA, instanceOfClassAA), "AA"); + Vector v = new Vector<>(); + v.add(instanceOfClassBB); + Method main = classToTest.getDeclaredMethod("main", Vector.class); + try { + assertEquals(main.invoke(instanceOfClass, v), "AA"); + } + catch (java.lang.reflect.InvocationTargetException e) { + testmainVectorCC(); + } + } + + @Test + public void testmainVectorCC() throws Exception { + Method m2 = classToTestCC.getDeclaredMethod("m2", classToTestCC); + assertEquals(m2.invoke(instanceOfClassCC, instanceOfClassCC), "CC"); + Vector v = new Vector<>(); + v.add(instanceOfClassCC); + Method main = classToTest.getDeclaredMethod("main", Vector.class); + String erg; + assertEquals(erg= (String) main.invoke(instanceOfClass, v), + erg.equals("CC")? "CC": "AA"); + } + + @Test + public void testmainVectorDD() throws Exception { + Method m2 = classToTestCC.getDeclaredMethod("m2", classToTestCC); + assertEquals(m2.invoke(instanceOfClassCC, instanceOfClassCC), "CC"); + Vector v = new Vector<>(); + v.add(instanceOfClassDD); + Method main = classToTest.getDeclaredMethod("main", Vector.class); + String erg; + assertEquals(erg= (String) main.invoke(instanceOfClass, v), + erg.equals("CC")? "CC": "AA"); + } +} diff --git a/src/test/java/targetast/LessEqualTest.java b/src/test/java/targetast/LessEqualTest.java new file mode 100644 index 00000000..d0eea8b2 --- /dev/null +++ b/src/test/java/targetast/LessEqualTest.java @@ -0,0 +1,111 @@ +package targetast; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class LessEqualTest { + static Class classToTest; + static Object instance; + + @BeforeClass + public static void beforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("LessEqual.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("LessEqual"); + instance = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testIntegers() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Integer.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5,7); + assertTrue(result); + } + + @Test + public void testEqualIntegers() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Integer.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5,5); + assertTrue(result); + } + + @Test + public void testLongs() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Long.class, Long.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5L,7L); + assertTrue(result); + }@Test + + public void testFloats() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Float.class, Float.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5F,7F); + assertTrue(result); + } + + @Test + public void testDoubles() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Double.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5.0,7.0); + assertTrue(result); + } + + @Test + public void testLongInt() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Long.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5L,7); + assertTrue(result); + } + + @Test + public void testFloatInt() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Float.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5F,7); + assertTrue(result); + } + + @Test + public void testDoubleInt() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5.0,7); + assertTrue(result); + } + + @Test + public void testFloatLong() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Float.class, Long.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5F,7L); + assertTrue(result); + } + + @Test + public void testDoubleLong() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Long.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5.0,7L); + assertTrue(result); + } + + @Test + public void testEqDoubleFloat() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Float.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 7.0,7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Float.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5.0,7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat3() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Float.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 9.0,7F); + assertFalse(result); + } +} diff --git a/src/test/java/targetast/LessThanTest.java b/src/test/java/targetast/LessThanTest.java new file mode 100644 index 00000000..4de4b1d3 --- /dev/null +++ b/src/test/java/targetast/LessThanTest.java @@ -0,0 +1,119 @@ +package targetast; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class LessThanTest { + static Class classToTest; + static Object instance; + + @BeforeClass + public static void beforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("LessThan.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("LessThan"); + instance = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testLessThanInt() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Integer.class,Integer.class); + Boolean result = (Boolean) lessThan.invoke(instance, 5, 7); + assertTrue(result); + } + + @Test + public void testLessThanInt2() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Integer.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7, 5); + assertFalse(result); + } + + @Test + public void testLessThanInt3() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Integer.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instance, 5, 5); + assertFalse(result); + } + + @Test + public void testLessThanLong() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Long.class,Long.class); + Boolean result = (Boolean) lessThan.invoke(instance, 5L, 7L); + assertTrue(result); + } + + @Test + public void testLessThanLong2() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Long.class, Long.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7L, 5L); + assertFalse(result); + } + + @Test + public void testLessThanLong3() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Long.class, Long.class); + Boolean result = (Boolean) lessThan.invoke(instance, 5L, 5L); + assertFalse(result); + } + + @Test + public void testLessThanFloat() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Float.class, Float.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7F, 5F); + assertFalse(result); + } + + @Test + public void testLessThanDouble() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Double.class, Double.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7.0, 5.0); + assertFalse(result); + } + + @Test + public void testLessThanLongInt() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Long.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7L, 5); + assertFalse(result); + } + + @Test + public void testLessThanFloatInt() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Float.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7F, 5); + assertFalse(result); + } + + @Test + public void testLessThanDoubleInt() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Double.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7.0, 5); + assertFalse(result); + } + + @Test + public void testLessThanFloatLong() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Float.class, Long.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7F, 5L); + assertFalse(result); + } + + @Test + public void testLessThanDoubleLong() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Double.class, Long.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7.0, 5L); + assertFalse(result); + } + + @Test + public void testLessThanDoubleFloat() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Double.class, Float.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7.0, 5F); + assertFalse(result); + } +} diff --git a/src/test/java/targetast/OLTest.java b/src/test/java/targetast/OLTest.java new file mode 100644 index 00000000..a4972320 --- /dev/null +++ b/src/test/java/targetast/OLTest.java @@ -0,0 +1,71 @@ +package targetast; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; + +import static org.junit.Assert.assertEquals; + +public class OLTest { + private static Class classToTest; + private static Class classToTest1; + private static Object instanceOfClass; + private static Object instanceOfClass1; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("OL.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("OL"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + classToTest1 = classFiles.get("OLMain"); + instanceOfClass1 = classToTest1.getDeclaredConstructor().newInstance(); + } + + @Test + public void testmInt() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Integer.class); + Integer result = (Integer) m.invoke(instanceOfClass, 5); + assertEquals(new Integer(10), result); + } + + @Test + public void testmDouble() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Double.class); + Double result = (Double) m.invoke(instanceOfClass, 5.0); + assertEquals(new Double(10.0), result); + } + + @Test + public void testmString() throws Exception { + Method m = classToTest.getDeclaredMethod("m", String.class); + String result = (String) m.invoke(instanceOfClass, "xxx"); + assertEquals("xxxxxx", result); + } + + @Test + public void testOLMainClassName() { + assertEquals("OLMain", classToTest1.getName()); + } + + @Test + public void testmainInt() throws Exception { + Method main = classToTest1.getDeclaredMethod("main", Integer.class); + Integer result = (Integer) main.invoke(instanceOfClass1, 5); + assertEquals(Integer.valueOf(10), result); + } + + @Test + public void testmainDouble() throws Exception { + Method main = classToTest1.getDeclaredMethod("main", Double.class); + Double result = (Double) main.invoke(instanceOfClass1, 5.0); + assertEquals(Double.valueOf(10.0), result); + } + + @Test + public void testmainString() throws Exception { + Method main = classToTest1.getDeclaredMethod("main", String.class); + String result = (String) main.invoke(instanceOfClass1, "xxx"); + assertEquals("xxxxxx", result); + } +} diff --git a/src/test/java/targetast/PostIncTest.java b/src/test/java/targetast/PostIncTest.java new file mode 100644 index 00000000..28a4b4e3 --- /dev/null +++ b/src/test/java/targetast/PostIncTest.java @@ -0,0 +1,49 @@ +package targetast; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; + +import static org.junit.Assert.assertEquals; + +public class PostIncTest { + private static Class classToTest; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("PostIncDec.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("PostIncDec"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testM1() throws Exception { + Method m = classToTest.getDeclaredMethod("m"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(Integer.valueOf(1), res); + } + + @Test + public void testM2() throws Exception { + Method m = classToTest.getDeclaredMethod("m2"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(Integer.valueOf(0), res); + } + + @Test + public void testD1() throws Exception { + Method m = classToTest.getDeclaredMethod("d"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(Integer.valueOf(-1), res); + } + + @Test + public void testD2() throws Exception { + Method m = classToTest.getDeclaredMethod("d2"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(Integer.valueOf(0), res); + } + +} diff --git a/src/test/java/targetast/PreIncTest.java b/src/test/java/targetast/PreIncTest.java new file mode 100644 index 00000000..24fc5cfb --- /dev/null +++ b/src/test/java/targetast/PreIncTest.java @@ -0,0 +1,49 @@ +package targetast; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; + +import static org.junit.Assert.assertEquals; + +public class PreIncTest { + private static Class classToTest; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("PreInc.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("PreInc"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testM() throws Exception { + Method m = classToTest.getDeclaredMethod("m"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(Integer.valueOf(1), res); + } + + @Test + public void testM2() throws Exception { + Method m = classToTest.getDeclaredMethod("m2"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(Integer.valueOf(1), res); + } + + @Test + public void testD() throws Exception { + Method m = classToTest.getDeclaredMethod("d"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(Integer.valueOf(-1), res); + } + + @Test + public void testD2() throws Exception { + Method m = classToTest.getDeclaredMethod("d2"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(Integer.valueOf(-1), res); + } + +} diff --git a/src/test/java/targetast/PutTest.java b/src/test/java/targetast/PutTest.java new file mode 100644 index 00000000..a14771b4 --- /dev/null +++ b/src/test/java/targetast/PutTest.java @@ -0,0 +1,58 @@ +package targetast; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; +import java.util.Stack; +import java.util.Vector; + +import static org.junit.Assert.assertEquals; + +public class PutTest { + private static Class classToTest; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("Put.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("Put"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testPutElementVector() throws Exception { + Method m = classToTest.getDeclaredMethod("putElement", Object.class, Vector.class); + Vector v_invoke = new Vector<>(); + m.invoke(instanceOfClass, 5, v_invoke); + Vector v = new Vector<>(); + v.add(5); + assertEquals(v, v_invoke); + } + + @Test + public void testPutElementStack() throws Exception { + Method m = classToTest.getDeclaredMethod("putElement", Object.class, Stack.class); + Stack s_invoke = new Stack<>(); + m.invoke(instanceOfClass, 5, s_invoke); + assertEquals(new Integer(5), s_invoke.pop()); + } + + @Test + public void testMainVector() throws Exception { + Method m = classToTest.getDeclaredMethod("main", Object.class, Vector.class); + Vector v_invoke = new Vector<>(); + m.invoke(instanceOfClass, 6, v_invoke); + Vector v = new Vector<>(); + v.add(6); + assertEquals(v, v_invoke); + } + + @Test + public void testMainStack() throws Exception { + Method m = classToTest.getDeclaredMethod("main", Object.class, Stack.class); + Stack s_invoke = new Stack<>(); + m.invoke(instanceOfClass, 6, s_invoke); + assertEquals(new Integer(6), s_invoke.pop()); + } +} diff --git a/src/test/java/targetast/TestCodegen.java b/src/test/java/targetast/TestCodegen.java index b063ee82..9fac2a04 100644 --- a/src/test/java/targetast/TestCodegen.java +++ b/src/test/java/targetast/TestCodegen.java @@ -1,9 +1,12 @@ package targetast; +import de.dhbwstuttgart.core.JavaTXCompiler; import de.dhbwstuttgart.target.bytecode.Codegen; +import de.dhbwstuttgart.target.generate.ASTToTargetAST; import de.dhbwstuttgart.target.tree.MethodParameter; import de.dhbwstuttgart.target.tree.TargetClass; 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.Test; @@ -15,26 +18,47 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; public class TestCodegen { - private static ByteArrayClassLoader loader = new ByteArrayClassLoader(); - - public static Class generateClass(TargetClass clazz) throws IOException { + public static Class generateClass(TargetClass clazz, ByteArrayClassLoader classLoader) throws IOException { var codegen = new Codegen(clazz); var bytes = codegen.generate(); var path = Path.of(System.getProperty("user.dir"), "src/test/resources/target/"); Files.createDirectories(path); Files.write(path.resolve(clazz.qualifiedName() + ".class"), bytes, StandardOpenOption.CREATE); - return loader.loadClass(bytes); + return classLoader.loadClass(bytes); + } + + public static Map> generateClassFiles(String filename, ByteArrayClassLoader classLoader) throws IOException, ClassNotFoundException { + var file = Path.of(System.getProperty("user.dir"), "/src/test/resources/bytecode/javFiles/", filename).toFile(); + var compiler = new JavaTXCompiler(file); + var resultSet = compiler.typeInference(); + var converter = new ASTToTargetAST(resultSet); + var classes = compiler.sourceFiles.get(file).getClasses(); + + for (var bytes : converter.generateUsedFunNTypes()) { + classLoader.loadClass(bytes); + } + + return classes.stream().map(cli -> { + try { + return generateClass(converter.convert(cli), classLoader); + } catch (IOException exception) { + throw new RuntimeException(exception); + } + }).collect(Collectors.toMap(Class::getName, Function.identity())); } @Test public void testEmptyClass() throws Exception { var clazz = new TargetClass(Opcodes.ACC_PUBLIC, "Empty"); clazz.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "main", List.of(), null, new TargetBlock(List.of())); - generateClass(clazz).getDeclaredMethod("main").invoke(null); + generateClass(clazz, new ByteArrayClassLoader()).getDeclaredMethod("main").invoke(null); } @Test @@ -78,7 +102,7 @@ public class TestCodegen { ); - var clazz = generateClass(targetClass); + var clazz = generateClass(targetClass, new ByteArrayClassLoader()); assertEquals(clazz.getDeclaredMethod("add", Integer.class, Integer.class).invoke(null, 10, 10), 20); assertEquals(clazz.getDeclaredMethod("sub", Integer.class, Integer.class).invoke(null, 20, 10), 10); assertEquals(clazz.getDeclaredMethod("div", Integer.class, Integer.class).invoke(null, 20, 10), 2); @@ -86,6 +110,39 @@ public class TestCodegen { assertEquals(clazz.getDeclaredMethod("rem", Integer.class, Integer.class).invoke(null, 10, 3), 1); } + @Test + public void testUnary() throws Exception { + var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "Unary"); + + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "not", + List.of(new MethodParameter(TargetType.Integer, "a")), + TargetType.Integer, + new TargetBlock(List.of(new TargetReturn( + new TargetUnaryOp.Not(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "a"))) + )) + ); + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "neg", + List.of(new MethodParameter(TargetType.Integer, "a")), + TargetType.Integer, + new TargetBlock(List.of(new TargetReturn( + new TargetUnaryOp.Negate(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "a"))) + )) + ); + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "add", + List.of(new MethodParameter(TargetType.Integer, "a")), + TargetType.Integer, + new TargetBlock(List.of(new TargetReturn( + new TargetUnaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "a"))) + )) + ); + + var clazz = generateClass(targetClass, new ByteArrayClassLoader()); + assertEquals(clazz.getDeclaredMethod("not", Integer.class).invoke(null, 10), -11); + assertEquals(clazz.getDeclaredMethod("neg", Integer.class).invoke(null, 10), -10); + assertEquals(clazz.getDeclaredMethod("add", Integer.class).invoke(null, 10), 10); + + } + @Test public void testConditional() throws Exception { var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "Conditional"); @@ -105,7 +162,7 @@ public class TestCodegen { )) ); - var clazz = generateClass(targetClass); + var clazz = generateClass(targetClass, new ByteArrayClassLoader()); var and = clazz.getDeclaredMethod("and", Boolean.class, Boolean.class); var or = clazz.getDeclaredMethod("or", Boolean.class, Boolean.class); assertEquals(and.invoke(null, true, false), false); @@ -123,7 +180,7 @@ public class TestCodegen { new TargetBinaryOp.Add(TargetType.Long, new TargetLiteral.CharLiteral((char)10), new TargetLiteral.LongLiteral((long)20)) ))) ); - var clazz = generateClass(targetClass); + var clazz = generateClass(targetClass, new ByteArrayClassLoader()); assertEquals(clazz.getDeclaredMethod("add").invoke(null), (long)30); } @@ -146,7 +203,7 @@ public class TestCodegen { ))) ); - var clazz = generateClass(targetClass); + var clazz = generateClass(targetClass, new ByteArrayClassLoader()); clazz.getDeclaredMethod("helloWorld").invoke(null); } @@ -166,7 +223,7 @@ public class TestCodegen { ) ))) ); - var clazz = generateClass(targetClass); + var clazz = generateClass(targetClass, new ByteArrayClassLoader()); var ifStmt = clazz.getDeclaredMethod("ifStmt", Integer.class); assertEquals(ifStmt.invoke(null, 10), 1); assertEquals(ifStmt.invoke(null, 3), 2); @@ -195,7 +252,7 @@ public class TestCodegen { new TargetReturn(new TargetLocalVar(TargetType.Integer, "sum")) )) ); - var clazz = generateClass(targetClass); + var clazz = generateClass(targetClass, new ByteArrayClassLoader()); assertEquals(clazz.getDeclaredMethod("forLoop").invoke(null), 45); } @@ -217,7 +274,7 @@ public class TestCodegen { new TargetReturn(new TargetLocalVar(TargetType.Integer, "i")) )) ); - var clazz = generateClass(targetClass); + var clazz = generateClass(targetClass, new ByteArrayClassLoader()); assertEquals(clazz.getDeclaredMethod("whileLoop").invoke(null), 10); } @@ -230,6 +287,7 @@ public class TestCodegen { pointTarget.addConstructor(Opcodes.ACC_PUBLIC, List.of(new MethodParameter(TargetType.Integer, "x"), new MethodParameter(TargetType.Integer, "y")), new TargetBlock(List.of( + new TargetMethodCall(null, new TargetSuper(TargetType.Object), List.of(), TargetType.Object, "", false, false), new TargetAssign(TargetType.Integer, new TargetFieldVar(TargetType.Integer, pointType, false, new TargetThis(pointType), "x"), new TargetLocalVar(TargetType.Integer, "x") @@ -252,8 +310,9 @@ public class TestCodegen { )) ); - var pointClass = generateClass(pointTarget); - var mainClass = generateClass(mainTarget); + var classLoader = new ByteArrayClassLoader(); + var pointClass = generateClass(pointTarget, classLoader); + var mainClass = generateClass(mainTarget, classLoader); var point = mainClass.getDeclaredMethod("makePoint", Integer.class, Integer.class).invoke(null, 10, 20); assertEquals(point.getClass().getDeclaredField("x").get(point), 10); @@ -262,11 +321,14 @@ public class TestCodegen { @Test public void testLambda() throws Exception { - var fun = loader.loadClass(Path.of(System.getProperty("user.dir"), "src/test/java/targetast/Fun1$$.class")); - var interfaceType = new TargetRefType("Fun1$$"); + 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 targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "Lambda"); - targetClass.addConstructor(Opcodes.ACC_PUBLIC, List.of(), new TargetBlock(List.of())); + var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "CGLambda"); + targetClass.addConstructor(Opcodes.ACC_PUBLIC, List.of(), new TargetBlock(List.of( + new TargetMethodCall(null, new TargetSuper(TargetType.Object), List.of(), TargetType.Object, "", false, false) + ))); targetClass.addMethod(Opcodes.ACC_PUBLIC, "lambda", List.of(), TargetType.Integer, new TargetBlock(List.of( new TargetVarDecl(interfaceType, "by2", @@ -284,7 +346,7 @@ public class TestCodegen { ), interfaceType, "apply", false, true))) )) ); - var clazz = generateClass(targetClass); + var clazz = generateClass(targetClass, classLoader); var instance = clazz.getConstructor().newInstance(); assertEquals(clazz.getDeclaredMethod("lambda").invoke(instance), 20); } diff --git a/src/test/java/targetast/TestComplete.java b/src/test/java/targetast/TestComplete.java new file mode 100644 index 00000000..c026a479 --- /dev/null +++ b/src/test/java/targetast/TestComplete.java @@ -0,0 +1,385 @@ +package targetast; + +import org.junit.Ignore; +import org.junit.Test; + +import java.lang.reflect.Method; +import java.util.Vector; + +import static org.junit.Assert.*; +import static targetast.TestCodegen.generateClassFiles; + +public class TestComplete { + + @Test + public void applyLambdaTest() throws Exception { + var classFiles = generateClassFiles("applyLambda.jav", new ByteArrayClassLoader()); + var applyLambda = classFiles.get("applyLambda"); + var instance = applyLambda.getDeclaredConstructor().newInstance(); + var m = applyLambda.getDeclaredMethod("m"); + var result = m.invoke(instance); + + assertEquals(result.getClass(), classFiles.get("Apply")); + } + + @Test + public void binaryTest() throws Exception { + var classFiles = generateClassFiles("BinaryInMeth.jav", new ByteArrayClassLoader()); + var binaryInMeth = classFiles.get("BinaryInMeth"); + var instance = binaryInMeth.getDeclaredConstructor().newInstance(); + + var m2 = binaryInMeth.getDeclaredMethod("m2", Integer.class, Integer.class); + var m3 = binaryInMeth.getDeclaredMethod("m3", Integer.class); + + assertEquals(6, m2.invoke(instance, 2, 3)); + assertEquals(4, m3.invoke(instance, 2)); + } + + @Test + public void classGenLamTest() throws Exception { + var classFiles = generateClassFiles("ClassGenLam.jav", new ByteArrayClassLoader()); + classFiles.get("ClassGenLam").getDeclaredConstructor().newInstance(); + } + + @Test + public void facTest() throws Exception { + var classFiles = generateClassFiles("Fac.jav", new ByteArrayClassLoader()); + var fac = classFiles.get("Fac"); + var instance = fac.getDeclaredConstructor().newInstance(); + + var getFac = fac.getDeclaredMethod("getFac", Integer.class); + assertEquals(6, getFac.invoke(instance, 3)); + } + + @Test + public void facultyTest() throws Exception { + var classFiles = generateClassFiles("Faculty.jav", new ByteArrayClassLoader()); + + var fac = classFiles.get("Faculty"); + var constructor = fac.getDeclaredConstructor(); + constructor.setAccessible(true); + var instance = constructor.newInstance(); + + var getFact = fac.getDeclaredMethod("getFact", Integer.class); + assertEquals(6, getFact.invoke(instance, 3)); + } + + @Test + public void fieldTest() throws Exception { + var classFiles = generateClassFiles("Field.jav", new ByteArrayClassLoader()); + var field = classFiles.get("Field"); + var instance = field.getDeclaredConstructor().newInstance(); + assertEquals(1, field.getFields().length); + } + + @Test + public void fieldTph2Test() throws Exception { + var classFiles = generateClassFiles("FieldTph2.jav", new ByteArrayClassLoader()); + var fieldtph2 = classFiles.get("FieldTph2"); + var instance = fieldtph2.getDeclaredConstructor().newInstance(); + + var a = fieldtph2.getDeclaredField("a"); + var m2 = fieldtph2.getDeclaredMethod("m2", Object.class); + m2.invoke(instance, 1); + + var m = fieldtph2.getDeclaredMethod("m", Object.class); + assertEquals(1, m.invoke(instance, 1)); + } + + @Test + public void fieldTphConsMethTest() throws Exception { + var classFiles = generateClassFiles("FieldTphConsMeth.jav", new ByteArrayClassLoader()); + var fieldTphConsMeth = classFiles.get("FieldTphConsMeth"); + + var ctor = fieldTphConsMeth.getDeclaredConstructor(Object.class); + var instance = ctor.newInstance("C"); + var a = fieldTphConsMeth.getDeclaredField("a"); + var id = fieldTphConsMeth.getDeclaredMethod("id", Object.class); + + assertEquals(42, id.invoke(instance, 42)); + assertEquals("C", a.get(instance)); + } + + @Test + public void fieldTphMMethTest() throws Exception { + var classFiles = generateClassFiles("FieldTphMMeth.jav", new ByteArrayClassLoader()); + var fieldTphMMeth = classFiles.get("FieldTphMMeth"); + var ctor = fieldTphMMeth.getDeclaredConstructor(Object.class, Object.class, Boolean.class); + + var instance1 = ctor.newInstance("C", 42, true); + var instance2 = ctor.newInstance("C", 42, false); + + var m = fieldTphMMeth.getDeclaredMethod("m", Object.class, Object.class, Boolean.class); + assertEquals(42, m.invoke(instance1, "C", 42, false)); + + var a = fieldTphMMeth.getDeclaredField("a"); + assertEquals("C", a.get(instance1)); + assertEquals(42, a.get(instance2)); + } + + @Test + public void genTest() throws Exception { + var classFiles = generateClassFiles("Gen.jav", new ByteArrayClassLoader()); + } + + @Test + public void idTest() throws Exception { + var classFiles = generateClassFiles("Id.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("Id").getDeclaredConstructor().newInstance(); + } + + @Test + public void infTest() throws Exception { + var classFiles = generateClassFiles("Inf.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("Inf").getDeclaredConstructor().newInstance(); + } + + @Test + public void kompTphTest() throws Exception { + var classFiles = generateClassFiles("KompTph.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("KompTph").getDeclaredConstructor().newInstance(); + } + + @Test + public void lambdaCaptureTest() throws Exception { + var classFiles = generateClassFiles("LambdaCapture.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("LambdaCapture").getDeclaredConstructor().newInstance(); + } + + @Test + public void lambdaTest() throws Exception { + var classFiles = generateClassFiles("Lambda.jav", new ByteArrayClassLoader()); + var classToTest = classFiles.get("Lambda"); + var instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + + var m = classToTest.getDeclaredMethod("m"); + var lambda = m.invoke(instanceOfClass).getClass(); + var apply = lambda.getMethod("apply", Object.class); + apply.setAccessible(true); + + var i = Integer.valueOf(77); + assertEquals(i, apply.invoke(m.invoke(instanceOfClass), i)); + } + + @Test + public void mathStrucInteger() throws Exception { + var classFiles = generateClassFiles("mathStrucInteger.jav", new ByteArrayClassLoader()); + var mathStrucInteger = classFiles.get("mathStrucInteger"); + mathStrucInteger.getDeclaredConstructor(Integer.class).newInstance(10); + } + + @Test + public void mathStruc() throws Exception { + var classFiles = generateClassFiles("mathStruc.jav", new ByteArrayClassLoader()); + var mathStruc = classFiles.get("mathStruc"); + mathStruc.getDeclaredConstructor(Object.class).newInstance("A"); + } + + @Test + public void matrixOpTest() throws Exception { + var classFiles = generateClassFiles("MatrixOP.jav", new ByteArrayClassLoader()); + var matrixOP = classFiles.get("MatrixOP"); + + Vector> vv = new Vector<>(); + Vector v1 = new Vector<>(); + v1.addElement(2); + v1.addElement(2); + Vector v2 = new Vector<>(); + v2.addElement(3); + v2.addElement(3); + vv.addElement(v1); + vv.addElement(v2); + + var instanceOfClass_m1 = matrixOP.getDeclaredConstructor(Vector.class).newInstance(vv); + + Vector> vv1 = new Vector<>(); + Vector v3 = new Vector<>(); + v3.addElement(2); + v3.addElement(2); + Vector v4 = new Vector<>(); + v4.addElement(3); + v4.addElement(3); + vv1.addElement(v3); + vv1.addElement(v4); + + var instanceOfClass_m2 = matrixOP.getDeclaredConstructor(Vector.class).newInstance(vv1);//Matrix m2 = new Matrix(vv1); + + var mul = matrixOP.getField("mul"); + mul.setAccessible(true); + + var lambda = mul.get(instanceOfClass_m1).getClass(); + var apply = lambda.getMethod("apply", Object.class, Object.class); + apply.setAccessible(true); + + var result = apply.invoke(mul.get(instanceOfClass_m1), instanceOfClass_m1, instanceOfClass_m2); + System.out.println(instanceOfClass_m1.toString() + " * " + instanceOfClass_m2.toString() + " = " + result.toString()); + + Vector> res = new Vector<>(); + Vector v5 = new Vector<>(); + v5.addElement(10); + v5.addElement(10); + Vector v6 = new Vector<>(); + v6.addElement(15); + v6.addElement(15); + res.addElement(v5); + res.addElement(v6); + + var instanceOfClass_m3 = matrixOP.getDeclaredConstructor(Vector.class).newInstance(res); + assertEquals(result, instanceOfClass_m3); + } + + @Ignore("Thread blocking for some reason") + @Test + public void matrixTest() throws Exception { + var classFiles = generateClassFiles("Matrix.jav", new ByteArrayClassLoader()); + var matrix = classFiles.get("Matrix"); + + Vector> vv = new Vector<>(); + Vector v1 = new Vector<> (); + v1.addElement(2); + v1.addElement(2); + Vector v2 = new Vector<> (); + v2.addElement(3); + v2.addElement(3); + vv.addElement(v1); + vv.addElement(v2); + + var instanceOfClass_m1 = matrix.getDeclaredConstructor(Vector.class).newInstance(vv); + + Vector> vv1 = new Vector<>(); + Vector v3 = new Vector<> (); + v3.addElement(2); + v3.addElement(2); + Vector v4 = new Vector<> (); + v4.addElement(3); + v4.addElement(3); + vv1.addElement(v3); + vv1.addElement(v4); + + var instanceOfClass_m2 = matrix.getDeclaredConstructor(Vector.class).newInstance(vv1); + + var mul = matrix.getDeclaredMethod("mul", Vector.class); + var result = mul.invoke(instanceOfClass_m1, instanceOfClass_m2); + System.out.println(instanceOfClass_m1.toString() + " * " + instanceOfClass_m2.toString() + " = " + result.toString()); + + Vector> res = new Vector<>(); + Vector v5 = new Vector<> (); + v5.addElement(10); + v5.addElement(10); + Vector v6 = new Vector<> (); + v6.addElement(15); + v6.addElement(15); + res.addElement(v5); + res.addElement(v6); + + var instanceOfClass_m3 = matrix.getDeclaredConstructor(Vector.class).newInstance(res); + assertEquals(result, instanceOfClass_m3); + } + + @Test + public void mergeTest() throws Exception { + var classFiles = generateClassFiles("Merge.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("Merge").getDeclaredConstructor().newInstance(); + } + + @Test + public void overloadingSortingTest() throws Exception { + var classFiles = generateClassFiles("Sorting.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("Sorting").getDeclaredConstructor().newInstance(); + } + + @Test + public void overloadingTest() throws Exception { + var classFiles = generateClassFiles("Overloading.jav", new ByteArrayClassLoader()); + var overloading = classFiles.get("Overloading"); + var overloading2 = classFiles.get("Overloading2"); + var instance1 = overloading.getDeclaredConstructor().newInstance(); + var instance2 = overloading2.getDeclaredConstructor().newInstance(); + + var m1 = overloading.getDeclaredMethod("test", overloading); + assertEquals("Overloading", m1.invoke(instance1, instance1)); + var m2 = overloading.getDeclaredMethod("test", overloading2); + assertEquals("Overloading2", m2.invoke(instance1, instance2)); + } + + @Test + public void plusTest() throws Exception { + var classFiles = generateClassFiles("Plus.jav", new ByteArrayClassLoader()); + var plus = classFiles.get("Plus"); + var instance = plus.getDeclaredConstructor().newInstance(); + + var addInt = plus.getDeclaredMethod("m", Integer.class, Integer.class); + assertEquals(10, addInt.invoke(instance, 7, 3)); + + var addString = plus.getDeclaredMethod("m", String.class, String.class); + assertEquals("ByteCode", addString.invoke(instance, "Byte", "Code")); + } + + @Test + public void relOpsTest() throws Exception { + var classFiles = generateClassFiles("RelOps.jav", new ByteArrayClassLoader()); + var relOps = classFiles.get("RelOps"); + var instance = relOps.getDeclaredConstructor().newInstance(); + + var m = relOps.getDeclaredMethod("m", Integer.class,Integer.class); + assertFalse((Boolean) m.invoke(instance, 7, 3)); + } + + @Test + public void simpleCyclesTest() throws Exception { + var classFiles = generateClassFiles("SimpleCycle.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("SimpleCycle").getDeclaredConstructor().newInstance(); + } + + @Test + public void subMatTest() throws Exception { + var classFiles = generateClassFiles("SubMatrix.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("SubMatrix").getDeclaredConstructor().newInstance(); + } + + @Test + public void tph3Test() throws Exception { + var classFiles = generateClassFiles("Tph3.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("Tph3").getDeclaredConstructor().newInstance(); + } + + @Test + public void tph5Test() throws Exception { + var classFiles = generateClassFiles("Tph5.jav", new ByteArrayClassLoader()); + var tph5 = classFiles.get("Tph5"); + var instance = tph5.getDeclaredConstructor().newInstance(); + var m = tph5.getDeclaredMethod("m", Object.class, Object.class); + } + + @Test + public void tph6Test() throws Exception { + var classFiles = generateClassFiles("Tph6.jav", new ByteArrayClassLoader()); + var tph5 = classFiles.get("Tph6"); + var instance = tph5.getDeclaredConstructor().newInstance(); + var m = tph5.getDeclaredMethod("m", Object.class, Object.class); + } + + @Test + public void typedIdTest() throws Exception { + var classFiles = generateClassFiles("TypedID.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("TypedID").getDeclaredConstructor().newInstance(); + } + + @Test + public void vectorAddTest() throws Exception { + var classFiles = generateClassFiles("VectorAdd.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("VectorAdd").getDeclaredConstructor().newInstance(); + } + + @Test + public void vectorSuperTest() throws Exception { + var classFiles = generateClassFiles("VectorSuper.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("VectorSuper").getDeclaredConstructor().newInstance(); + } + + @Test + public void yTest() throws Exception { + var classFiles = generateClassFiles("Y.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("Y").getDeclaredConstructor().newInstance(); + } +} diff --git a/src/test/java/targetast/TphTest.java b/src/test/java/targetast/TphTest.java new file mode 100644 index 00000000..e550885f --- /dev/null +++ b/src/test/java/targetast/TphTest.java @@ -0,0 +1,58 @@ +package targetast; + +import de.dhbwstuttgart.core.JavaTXCompiler; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import static org.junit.Assert.assertEquals; + +public class TphTest { + + private static Class classToTest; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("Tph.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("Tph"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test1() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class); + Object result = m.invoke(instanceOfClass, 1,2); + + assertEquals(1,result); + } + + @Test + public void test2() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class); + Object result = m.invoke(instanceOfClass, 1, "sss"); + + assertEquals(1,result); + } + + @Test + public void test3() throws Exception { + Method m = classToTest.getDeclaredMethod("m2", Object.class); + Object result = m.invoke(instanceOfClass, 2); + + assertEquals(2,result); + } + + @Test + public void test4() throws Exception { + Method m = classToTest.getDeclaredMethod("m2", Object.class); + Object result = m.invoke(instanceOfClass,"xxx"); + + assertEquals("xxx",result); + } + +} diff --git a/src/test/java/targetast/WhileTest.java b/src/test/java/targetast/WhileTest.java new file mode 100644 index 00000000..c0e2c431 --- /dev/null +++ b/src/test/java/targetast/WhileTest.java @@ -0,0 +1,47 @@ +package targetast; + +import de.dhbwstuttgart.core.JavaTXCompiler; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import static org.junit.Assert.assertEquals; + +public class WhileTest { + private static Class classToTest; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("While.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("While"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Integer.class); + Integer result = (Integer) m.invoke(instanceOfClass, 0); + assertEquals(Integer.valueOf(2), result); + } + + @Test + public void testDouble() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Double.class); + Double result = (Double) m.invoke(instanceOfClass, 0.0); + assertEquals(Double.valueOf(2.0), result); + } + + @Test + public void testLong() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Long.class); + Long result = (Long) m.invoke(instanceOfClass, 0l); + assertEquals(Long.valueOf(2l), result); + } + +} From c21104f646f54bd88f69dca04908a313f1e7a3c4 Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Tue, 2 Aug 2022 18:10:52 +0200 Subject: [PATCH 58/69] Find functions in class files and primitive types --- .../target}/ByteArrayClassLoader.java | 2 +- .../target/bytecode/Codegen.java | 37 +++++++++------- .../target/generate/ASTToTargetAST.java | 40 ++++++++++++++---- .../generate/StatementToTargetExpression.java | 42 +++++++++++++++++-- .../tree/expression/TargetMethodCall.java | 6 +-- .../tree/type/TargetExtendsWildcard.java | 2 +- .../target/tree/type/TargetPrimitiveType.java | 19 +++++++++ .../target/tree/type/TargetSuperWildcard.java | 2 +- .../target/tree/type/TargetType.java | 38 ++++++++++++++++- .../java/targetast/ASTToTypedTargetAST.java | 1 + src/test/java/targetast/GreaterEqualTest.java | 1 + src/test/java/targetast/GreaterThanTest.java | 1 + src/test/java/targetast/InheritTest.java | 1 + src/test/java/targetast/InheritTest2.java | 3 +- src/test/java/targetast/LessEqualTest.java | 1 + src/test/java/targetast/LessThanTest.java | 1 + src/test/java/targetast/OLTest.java | 1 + src/test/java/targetast/PostIncTest.java | 1 + src/test/java/targetast/PreIncTest.java | 1 + src/test/java/targetast/PutTest.java | 1 + src/test/java/targetast/TestCodegen.java | 10 ++--- src/test/java/targetast/TestComplete.java | 2 +- src/test/java/targetast/TphTest.java | 5 +-- src/test/java/targetast/WhileTest.java | 6 +-- 24 files changed, 174 insertions(+), 50 deletions(-) rename src/{test/java/targetast => main/java/de/dhbwstuttgart/target}/ByteArrayClassLoader.java (92%) create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/type/TargetPrimitiveType.java diff --git a/src/test/java/targetast/ByteArrayClassLoader.java b/src/main/java/de/dhbwstuttgart/target/ByteArrayClassLoader.java similarity index 92% rename from src/test/java/targetast/ByteArrayClassLoader.java rename to src/main/java/de/dhbwstuttgart/target/ByteArrayClassLoader.java index 66937cf4..428e214d 100644 --- a/src/test/java/targetast/ByteArrayClassLoader.java +++ b/src/main/java/de/dhbwstuttgart/target/ByteArrayClassLoader.java @@ -1,4 +1,4 @@ -package targetast; +package de.dhbwstuttgart.target; import java.io.IOException; import java.nio.file.Files; diff --git a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java index 948c55fd..c361c893 100755 --- a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java @@ -3,6 +3,7 @@ package de.dhbwstuttgart.target.bytecode; import de.dhbwstuttgart.target.tree.*; import de.dhbwstuttgart.target.tree.expression.*; import de.dhbwstuttgart.target.tree.type.TargetFunNType; +import de.dhbwstuttgart.target.tree.type.TargetPrimitiveType; import de.dhbwstuttgart.target.tree.type.TargetRefType; import de.dhbwstuttgart.target.tree.type.TargetType; import org.objectweb.asm.*; @@ -13,6 +14,7 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.stream.IntStream; @@ -86,21 +88,21 @@ public class Codegen { private void boxPrimitive(State state, TargetType type) { var mv = state.mv; - if (type.equals(TargetType.Boolean)) { + if (type.equals(TargetType.Boolean) || type.equals(TargetType.boolean_)) { mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); - } else if (type.equals(TargetType.Byte)) { + } else if (type.equals(TargetType.Byte) || type.equals(TargetType.byte_)) { mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false); - } else if (type.equals(TargetType.Double)) { + } else if (type.equals(TargetType.Double) || type.equals(TargetType.double_)) { mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false); - } else if (type.equals(TargetType.Long)) { + } else if (type.equals(TargetType.Long) || type.equals(TargetType.long_)) { mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false); - } else if (type.equals(TargetType.Integer)) { + } else if (type.equals(TargetType.Integer) || type.equals(TargetType.int_)) { mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false); - } else if (type.equals(TargetType.Float)) { + } else if (type.equals(TargetType.Float) || type.equals(TargetType.float_)) { mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false); - } else if (type.equals(TargetType.Short)) { + } else if (type.equals(TargetType.Short) || type.equals(TargetType.short_)) { mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false); - } else if (type.equals(TargetType.Char)) { + } else if (type.equals(TargetType.Char) || type.equals(TargetType.char_)) { mv.visitMethodInsn(INVOKESTATIC, "java/lang/Char", "valueOf", "(C)Ljava/lang/Char;", false); } } @@ -909,23 +911,28 @@ public class Codegen { } case TargetMethodCall call: { generate(state, call.expr()); - for (TargetExpression e : call.args()) { + for (var i = 0; i < call.args().size(); i++) { + var e = call.args().get(i); + var arg = call.parameterTypes().get(i); generate(state, e); - boxPrimitive(state, e.type()); + if (!(arg instanceof TargetPrimitiveType)) + boxPrimitive(state, e.type()); } var descriptor = call.getDescriptor(); if (call.owner() instanceof TargetFunNType) // Decay FunN descriptor = TargetMethod.getDescriptor( - call.type() == null ? null : TargetType.Object, + call.returnType() == null ? null : TargetType.Object, call.parameterTypes().stream().map(x -> TargetType.Object).toArray(TargetType[]::new) ); mv.visitMethodInsn(call.isInterface() ? INVOKEINTERFACE : call.isStatic() ? INVOKESTATIC: call.name().equals("") ? INVOKESPECIAL : INVOKEVIRTUAL, call.owner().getName(), call.name(), descriptor, call.isInterface()); - if (call.owner() instanceof TargetFunNType) - mv.visitTypeInsn(CHECKCAST, call.type().getName()); - if (call.type() != null) - unboxPrimitive(state, call.type()); + + if (call.returnType() != null && !(call.returnType() instanceof TargetPrimitiveType)) { + if (!call.returnType().equals(call.type())) + mv.visitTypeInsn(CHECKCAST, call.type().getName()); + else unboxPrimitive(state, call.type()); + } break; } case TargetLambdaExpression lambda: diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index b1eea73c..d9e5cfdd 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -11,6 +11,7 @@ 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.*; +import de.dhbwstuttgart.target.ByteArrayClassLoader; import java.util.*; import java.util.stream.Collectors; @@ -142,8 +143,9 @@ public class ASTToTargetAST { 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(); + var optMethod = owner.getMethods().stream().filter( + m -> m.name.equals(methodCall.name) && parameterEquals(methodCall.getArgumentList(), methodCall.getArgumentList().getArguments()) + ).findFirst(); if (optMethod.isEmpty()) return; var method = optMethod.get(); var generics = generics(owner, method); @@ -411,7 +413,30 @@ public class ASTToTargetAST { } } + private boolean parameterEquals(ArgumentList argumentList, List arguments) { + if (argumentList.getArguments().size() != arguments.size()) + return false; + + for (var i = 0; i < argumentList.getArguments().size(); i++) { + var type1 = convert(argumentList.getArguments().get(i).getType()); + var type2 = convert(arguments.get(i).getType()); + if (!type1.equals(type2)) return false; + } + + return true; + } + + protected ByteArrayClassLoader classLoader; + protected SourceFile sourceFile; + public ASTToTargetAST(List resultSets) { + this(resultSets, null, new ByteArrayClassLoader()); + } + + public ASTToTargetAST(List resultSets, SourceFile sourceFile, ByteArrayClassLoader classLoader) { + this.classLoader = classLoader; + this.sourceFile = sourceFile; + all = new ArrayList<>(); for (var set : resultSets) { all.add(new Sigma(set)); @@ -596,11 +621,7 @@ public class ASTToTargetAST { ); } - private Set usedFunN = new HashSet<>(); - - public List generateUsedFunNTypes() { - return usedFunN.stream().map(n -> FunNGenerator.getInstance().generateSuperBytecode(n)).toList(); - } + private final Set usedFunN = new HashSet<>(); protected TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input) { return input.acceptTV(new TypeVisitor<>() { @@ -611,7 +632,10 @@ public class ASTToTargetAST { var params = refType.getParaList().stream().map(ASTToTargetAST.this::convert).toList(); if (name.matches("Fun\\d\\$\\$")) { // TODO This seems like a bad idea - usedFunN.add(params.size() - 1); + if (!usedFunN.contains(params.size() - 1)) { + usedFunN.add(params.size() - 1); + classLoader.loadClass(FunNGenerator.getInstance().generateSuperBytecode(params.size() - 1)); + } return new TargetFunNType(params.size() - 1, params); } return new TargetRefType(name, params); diff --git a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java index 79338248..279e3625 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java @@ -2,8 +2,11 @@ package de.dhbwstuttgart.target.generate; import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import de.dhbwstuttgart.syntaxtree.Method; import de.dhbwstuttgart.syntaxtree.StatementVisitor; import de.dhbwstuttgart.syntaxtree.statement.*; +import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.target.tree.MethodParameter; import de.dhbwstuttgart.target.tree.expression.*; import de.dhbwstuttgart.target.tree.type.TargetFunNType; @@ -11,6 +14,7 @@ import de.dhbwstuttgart.target.tree.type.TargetRefType; import de.dhbwstuttgart.target.tree.type.TargetType; import java.util.List; +import java.util.stream.Stream; import java.util.stream.StreamSupport; public class StatementToTargetExpression implements StatementVisitor { @@ -131,10 +135,41 @@ public class StatementToTargetExpression implements StatementVisitor { var receiverType = converter.convert(methodCall.receiver.getType()); var isFunNType = receiverType instanceof TargetFunNType; var returnType = converter.convert(methodCall.getType()); + var receiverName = new JavaClassName(((TargetRefType) converter.convert(methodCall.receiver.getType())).name()); + + var argList = methodCall.arglist.getArguments().stream().map(expr -> converter.convert(expr.getType())).toList(); + + java.lang.reflect.Method foundMethod = null; + if (converter.sourceFile.imports.contains(receiverName)) { + try { + var clazz = converter.classLoader.loadClass(receiverName.toString()); + + outer: for (var method : clazz.getMethods()) { + if (method.getParameterTypes().length != argList.size()) continue; + if (!method.getName().equals(methodCall.name)) continue; + + for (var i = 0; i < method.getParameterTypes().length; i++) { + var param = method.getParameterTypes()[i]; + var arg = argList.get(i); + if (param.isPrimitive()) { + arg = TargetType.toPrimitive(arg); + } + if (!TargetType.toTargetType(param).equals(arg)) continue outer; + } + foundMethod = method; + break; + } + } catch (ClassNotFoundException ignored) {} + } + + if (foundMethod != null) { + returnType = TargetType.toTargetType(foundMethod.getReturnType()); + argList = Stream.of(foundMethod.getParameterTypes()).map(TargetType::toTargetType).toList(); + } result = new TargetMethodCall( - returnType, - methodCall.arglist.getArguments().stream().map(expr -> converter.convert(expr.getType())).toList(), + converter.convert(methodCall.getType()), + returnType, argList, converter.convert(methodCall.receiver), methodCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), receiverType, @@ -205,8 +240,9 @@ public class StatementToTargetExpression implements StatementVisitor { @Override public void visit(SuperCall superCall) { var aSuper = converter.convert(converter.currentClass.getSuperClass()); + var type = converter.convert(superCall.getType()); result = new TargetMethodCall( - converter.convert(superCall.getType()), + type, type, superCall.argTypes == null ? List.of() : superCall.argTypes.stream().map(converter::convert).toList(), new TargetSuper(aSuper), superCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetMethodCall.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetMethodCall.java index 12325962..50a31471 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetMethodCall.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetMethodCall.java @@ -7,13 +7,13 @@ import de.dhbwstuttgart.target.tree.type.TargetType; import java.util.List; -public record TargetMethodCall(TargetType type, List parameterTypes, TargetExpression expr, List args, TargetType owner, String name, boolean isStatic, boolean isInterface) implements TargetStatementExpression { +public record TargetMethodCall(TargetType type, TargetType returnType, List parameterTypes, TargetExpression expr, List args, TargetType owner, String name, boolean isStatic, boolean isInterface) implements TargetStatementExpression { public TargetMethodCall(TargetType type, TargetExpression expr, List args, TargetType owner, String name, boolean isStatic, boolean isInterface) { - this(type, args.stream().map(TargetExpression::type).toList(), expr, args, owner, name, isStatic, isInterface); + this(type, type, args.stream().map(TargetExpression::type).toList(), expr, args, owner, name, isStatic, isInterface); } public String getDescriptor() { - return TargetMethod.getDescriptor(type, parameterTypes.toArray(TargetType[]::new)); + return TargetMethod.getDescriptor(returnType, parameterTypes.toArray(TargetType[]::new)); } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java index 533472c8..d5b67745 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java @@ -13,7 +13,7 @@ public record TargetExtendsWildcard(TargetType innerType) implements TargetType @Override public String getName() { - return null; + return innerType.getName(); } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetPrimitiveType.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetPrimitiveType.java new file mode 100644 index 00000000..3f170d18 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetPrimitiveType.java @@ -0,0 +1,19 @@ +package de.dhbwstuttgart.target.tree.type; + +public record TargetPrimitiveType(String name) implements TargetType { + + @Override + public String toSignature() { + return getName(); + } + + @Override + public String toGenericSignature() { + return toSignature(); + } + + @Override + public String getName() { + return name; + } +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java index 101a3a53..b1a78907 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java @@ -13,6 +13,6 @@ public record TargetSuperWildcard(TargetType innerType) implements TargetType { @Override public String getName() { - return null; + return innerType.getName(); } } 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 ad9c895e..63cbb945 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, TargetGenericType, TargetSpecializedType, TargetSuperWildcard { + permits TargetExtendsWildcard, TargetGenericType, TargetSpecializedType, TargetSuperWildcard, TargetPrimitiveType { // Builtin types TargetRefType Boolean = new TargetRefType("java.lang.Boolean"); @@ -17,6 +17,42 @@ public sealed interface TargetType TargetRefType String = new TargetRefType("java.lang.String"); TargetRefType Object = new TargetRefType("java.lang.Object"); + // Builtin types + TargetPrimitiveType boolean_ = new TargetPrimitiveType("Z"); + TargetPrimitiveType char_ = new TargetPrimitiveType("C"); + TargetPrimitiveType byte_ = new TargetPrimitiveType("B"); + TargetPrimitiveType short_ = new TargetPrimitiveType("S"); + TargetPrimitiveType int_ = new TargetPrimitiveType("I"); + TargetPrimitiveType long_ = new TargetPrimitiveType("J"); + TargetPrimitiveType float_ = new TargetPrimitiveType("F"); + TargetPrimitiveType double_ = new TargetPrimitiveType("D"); + + static TargetType toPrimitive(TargetType type) { + if (type.equals(Boolean)) return boolean_; + if (type.equals(Char)) return char_; + if (type.equals(Byte)) return byte_; + if (type.equals(Short)) return short_; + if (type.equals(Integer)) return int_; + if (type.equals(Long)) return long_; + if (type.equals(Float)) return float_; + if (type.equals(Double)) return double_; + return type; + } + + static TargetType toTargetType(Class clazz) { + if (clazz.isPrimitive()) { + if (clazz.equals(boolean.class)) return boolean_; + if (clazz.equals(char.class)) return char_; + if (clazz.equals(byte.class)) return byte_; + if (clazz.equals(short.class)) return short_; + if (clazz.equals(int.class)) return int_; + if (clazz.equals(long.class)) return long_; + if (clazz.equals(float.class)) return float_; + if (clazz.equals(double.class)) return double_; + } + return new TargetRefType(clazz.getName()); + } + String toSignature(); String toGenericSignature(); String getName(); diff --git a/src/test/java/targetast/ASTToTypedTargetAST.java b/src/test/java/targetast/ASTToTypedTargetAST.java index 4a46db0c..94b56bd4 100644 --- a/src/test/java/targetast/ASTToTypedTargetAST.java +++ b/src/test/java/targetast/ASTToTypedTargetAST.java @@ -5,6 +5,7 @@ import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.target.ByteArrayClassLoader; import de.dhbwstuttgart.target.generate.ASTToTargetAST; import de.dhbwstuttgart.target.tree.TargetClass; import de.dhbwstuttgart.typeinference.result.ResultSet; diff --git a/src/test/java/targetast/GreaterEqualTest.java b/src/test/java/targetast/GreaterEqualTest.java index ac9216c9..2a4c6b0d 100644 --- a/src/test/java/targetast/GreaterEqualTest.java +++ b/src/test/java/targetast/GreaterEqualTest.java @@ -1,5 +1,6 @@ package targetast; +import de.dhbwstuttgart.target.ByteArrayClassLoader; import org.junit.BeforeClass; import org.junit.Test; diff --git a/src/test/java/targetast/GreaterThanTest.java b/src/test/java/targetast/GreaterThanTest.java index c5684c5a..3d7ce1cf 100644 --- a/src/test/java/targetast/GreaterThanTest.java +++ b/src/test/java/targetast/GreaterThanTest.java @@ -1,5 +1,6 @@ package targetast; +import de.dhbwstuttgart.target.ByteArrayClassLoader; import org.junit.BeforeClass; import org.junit.Test; diff --git a/src/test/java/targetast/InheritTest.java b/src/test/java/targetast/InheritTest.java index fcf276a9..7c99cc66 100644 --- a/src/test/java/targetast/InheritTest.java +++ b/src/test/java/targetast/InheritTest.java @@ -1,5 +1,6 @@ package targetast; +import de.dhbwstuttgart.target.ByteArrayClassLoader; import org.junit.BeforeClass; import org.junit.Test; diff --git a/src/test/java/targetast/InheritTest2.java b/src/test/java/targetast/InheritTest2.java index a6ec9227..c4c48ed5 100644 --- a/src/test/java/targetast/InheritTest2.java +++ b/src/test/java/targetast/InheritTest2.java @@ -1,5 +1,6 @@ package targetast; +import de.dhbwstuttgart.target.ByteArrayClassLoader; import org.junit.BeforeClass; import org.junit.Test; @@ -15,7 +16,7 @@ public class InheritTest2 { @BeforeClass public static void setUpBeforeClass() throws Exception { var classLoader = new ByteArrayClassLoader(); - classToTest = TestCodegen.generateClassFiles("Inherit.jav", classLoader).get("Inherit2"); + classToTest = TestCodegen.generateClassFiles("Inherit2.jav", classLoader).get("Inherit2"); classToTestAA = TestCodegen.generateClassFiles("AA.jav", classLoader).get("AA"); classToTestBB = TestCodegen.generateClassFiles("BB.jav", classLoader).get("BB"); classToTestCC = TestCodegen.generateClassFiles("CC.jav", classLoader).get("CC"); diff --git a/src/test/java/targetast/LessEqualTest.java b/src/test/java/targetast/LessEqualTest.java index d0eea8b2..617a3f0b 100644 --- a/src/test/java/targetast/LessEqualTest.java +++ b/src/test/java/targetast/LessEqualTest.java @@ -1,5 +1,6 @@ package targetast; +import de.dhbwstuttgart.target.ByteArrayClassLoader; import org.junit.BeforeClass; import org.junit.Test; diff --git a/src/test/java/targetast/LessThanTest.java b/src/test/java/targetast/LessThanTest.java index 4de4b1d3..3ed46908 100644 --- a/src/test/java/targetast/LessThanTest.java +++ b/src/test/java/targetast/LessThanTest.java @@ -1,5 +1,6 @@ package targetast; +import de.dhbwstuttgart.target.ByteArrayClassLoader; import org.junit.BeforeClass; import org.junit.Test; diff --git a/src/test/java/targetast/OLTest.java b/src/test/java/targetast/OLTest.java index a4972320..30957a09 100644 --- a/src/test/java/targetast/OLTest.java +++ b/src/test/java/targetast/OLTest.java @@ -1,5 +1,6 @@ package targetast; +import de.dhbwstuttgart.target.ByteArrayClassLoader; import org.junit.BeforeClass; import org.junit.Test; diff --git a/src/test/java/targetast/PostIncTest.java b/src/test/java/targetast/PostIncTest.java index 28a4b4e3..9fbbb965 100644 --- a/src/test/java/targetast/PostIncTest.java +++ b/src/test/java/targetast/PostIncTest.java @@ -1,5 +1,6 @@ package targetast; +import de.dhbwstuttgart.target.ByteArrayClassLoader; import org.junit.BeforeClass; import org.junit.Test; diff --git a/src/test/java/targetast/PreIncTest.java b/src/test/java/targetast/PreIncTest.java index 24fc5cfb..a48cea2c 100644 --- a/src/test/java/targetast/PreIncTest.java +++ b/src/test/java/targetast/PreIncTest.java @@ -1,5 +1,6 @@ package targetast; +import de.dhbwstuttgart.target.ByteArrayClassLoader; import org.junit.BeforeClass; import org.junit.Test; diff --git a/src/test/java/targetast/PutTest.java b/src/test/java/targetast/PutTest.java index a14771b4..a67ad03a 100644 --- a/src/test/java/targetast/PutTest.java +++ b/src/test/java/targetast/PutTest.java @@ -1,5 +1,6 @@ package targetast; +import de.dhbwstuttgart.target.ByteArrayClassLoader; import org.junit.BeforeClass; import org.junit.Test; diff --git a/src/test/java/targetast/TestCodegen.java b/src/test/java/targetast/TestCodegen.java index 9fac2a04..165dff72 100644 --- a/src/test/java/targetast/TestCodegen.java +++ b/src/test/java/targetast/TestCodegen.java @@ -1,6 +1,7 @@ package targetast; import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.target.ByteArrayClassLoader; import de.dhbwstuttgart.target.bytecode.Codegen; import de.dhbwstuttgart.target.generate.ASTToTargetAST; import de.dhbwstuttgart.target.tree.MethodParameter; @@ -38,13 +39,10 @@ public class TestCodegen { var file = Path.of(System.getProperty("user.dir"), "/src/test/resources/bytecode/javFiles/", filename).toFile(); var compiler = new JavaTXCompiler(file); var resultSet = compiler.typeInference(); - var converter = new ASTToTargetAST(resultSet); + var sourceFile = compiler.sourceFiles.get(file); + var converter = new ASTToTargetAST(resultSet, sourceFile, classLoader); var classes = compiler.sourceFiles.get(file).getClasses(); - for (var bytes : converter.generateUsedFunNTypes()) { - classLoader.loadClass(bytes); - } - return classes.stream().map(cli -> { try { return generateClass(converter.convert(cli), classLoader); @@ -341,7 +339,7 @@ public class TestCodegen { ) )) ), - new TargetReturn(new TargetCast(TargetType.Integer, new TargetMethodCall(TargetType.Object, List.of(TargetType.Object), new TargetLocalVar(interfaceType, "by2"), List.of( + new TargetReturn(new TargetCast(TargetType.Integer, new TargetMethodCall(TargetType.Object, TargetType.Object, List.of(TargetType.Object), new TargetLocalVar(interfaceType, "by2"), List.of( new TargetLiteral.IntLiteral(10) ), interfaceType, "apply", false, true))) )) diff --git a/src/test/java/targetast/TestComplete.java b/src/test/java/targetast/TestComplete.java index c026a479..f75520df 100644 --- a/src/test/java/targetast/TestComplete.java +++ b/src/test/java/targetast/TestComplete.java @@ -1,9 +1,9 @@ package targetast; +import de.dhbwstuttgart.target.ByteArrayClassLoader; import org.junit.Ignore; import org.junit.Test; -import java.lang.reflect.Method; import java.util.Vector; import static org.junit.Assert.*; diff --git a/src/test/java/targetast/TphTest.java b/src/test/java/targetast/TphTest.java index e550885f..c2bb9835 100644 --- a/src/test/java/targetast/TphTest.java +++ b/src/test/java/targetast/TphTest.java @@ -1,13 +1,10 @@ package targetast; -import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.target.ByteArrayClassLoader; import org.junit.BeforeClass; import org.junit.Test; -import java.io.File; import java.lang.reflect.Method; -import java.net.URL; -import java.net.URLClassLoader; import static org.junit.Assert.assertEquals; diff --git a/src/test/java/targetast/WhileTest.java b/src/test/java/targetast/WhileTest.java index c0e2c431..0321c90f 100644 --- a/src/test/java/targetast/WhileTest.java +++ b/src/test/java/targetast/WhileTest.java @@ -1,14 +1,10 @@ package targetast; -import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.target.ByteArrayClassLoader; import org.junit.BeforeClass; import org.junit.Test; -import java.io.File; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.net.URL; -import java.net.URLClassLoader; import static org.junit.Assert.assertEquals; From bfc5c55e90320248e5571834f640ff88de8392e7 Mon Sep 17 00:00:00 2001 From: "pl@gohorb.ba-horb.de" Date: Wed, 3 Aug 2022 15:18:55 +0200 Subject: [PATCH 59/69] modified: ../../../../pom.xml modified: ../../java/targetast/TphTest.java modified: ../bytecode/javFiles/Tph.jav new file: ../bytecode/javFiles/Tph7.jav --- pom.xml | 4 ++-- src/test/java/targetast/TphTest.java | 3 +++ src/test/resources/bytecode/javFiles/Tph.jav | 1 - src/test/resources/bytecode/javFiles/Tph7.jav | 11 +++++++++++ 4 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 src/test/resources/bytecode/javFiles/Tph7.jav diff --git a/pom.xml b/pom.xml index 3f7cc7e3..c2ee1230 100644 --- a/pom.xml +++ b/pom.xml @@ -122,8 +122,8 @@ http://maven.apache.org/maven-v4_0_0.xsd"> org.apache.maven.plugins maven-compiler-plugin - 17 - 17 + 18 + 18 --enable-preview diff --git a/src/test/java/targetast/TphTest.java b/src/test/java/targetast/TphTest.java index c2bb9835..198bea5b 100644 --- a/src/test/java/targetast/TphTest.java +++ b/src/test/java/targetast/TphTest.java @@ -18,6 +18,9 @@ public class TphTest { var classFiles = TestCodegen.generateClassFiles("Tph.jav", new ByteArrayClassLoader()); classToTest = classFiles.get("Tph"); instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + classFiles = TestCodegen.generateClassFiles("Tph7.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("Tph7"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); } @Test diff --git a/src/test/resources/bytecode/javFiles/Tph.jav b/src/test/resources/bytecode/javFiles/Tph.jav index 9faa570c..3f9d0aab 100644 --- a/src/test/resources/bytecode/javFiles/Tph.jav +++ b/src/test/resources/bytecode/javFiles/Tph.jav @@ -3,7 +3,6 @@ public class Tph { m(a,b){ var c = m2(b); return a; -// return m2(b); } m2(b){ diff --git a/src/test/resources/bytecode/javFiles/Tph7.jav b/src/test/resources/bytecode/javFiles/Tph7.jav new file mode 100644 index 00000000..cc55afb5 --- /dev/null +++ b/src/test/resources/bytecode/javFiles/Tph7.jav @@ -0,0 +1,11 @@ +public class Tph7 { + + m(a,b){ + var c = m2(b); + return m2(b); + } + + m2(b){ + return b; + } +} \ No newline at end of file From 4e6e8c5cc77c860a41f23a0cb53b413217a8a00a Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Fri, 5 Aug 2022 16:20:30 +0200 Subject: [PATCH 60/69] Add Tph7 test. --- .../target/generate/ASTToTargetAST.java | 44 +++++++++++++++++-- .../generate/StatementToTargetExpression.java | 5 ++- .../target/tree/type/TargetFunNType.java | 5 +++ .../tree/type/TargetSpecializedType.java | 2 + src/test/java/targetast/TestComplete.java | 7 +++ src/test/resources/bytecode/javFiles/Tph7.jav | 10 +++++ 6 files changed, 68 insertions(+), 5 deletions(-) create mode 100644 src/test/resources/bytecode/javFiles/Tph7.jav diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index d9e5cfdd..310d24a3 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -106,6 +106,25 @@ public class ASTToTargetAST { return generics.stream().anyMatch(generic -> generic.getLeft().equals(name)); } + boolean containsRelation(Set> result, PairTPHsmallerTPH pair) { + // Check if both the right and the left are already part of a relation + var containsLeft = false; + for (var pair2 : result) { + if (pair2.getLeft().equals(pair.left)) { + containsLeft = true; + break; + } + } + var containsRight = false; + for (var pair2 : result) { + if (pair2.getRight().equals(pair.right)) { + containsRight = true; + break; + } + } + return containsLeft && containsRight; + } + // Family of generated Generics Set> generics(ClassOrInterface owner, Method method) { if (computedGenericsOfMethods.containsKey(method)) @@ -119,6 +138,7 @@ public class ASTToTargetAST { HashSet typeVariables = new HashSet<>(); HashSet typeVariablesOfFields = new HashSet<>(); + HashSet allTypeVariables = new HashSet<>(); for (var field : owner.getFieldDecl()) { findTypeVariables(field.getType(), typeVariablesOfFields); @@ -136,6 +156,17 @@ public class ASTToTargetAST { } }); + // Type variables with bounds that are also type variables of the method + for (var typeVariable : new HashSet<>(typeVariables)) { + for (var pair : simplifiedConstraints) { + if (pair.left.equals(typeVariable) && typeVariables.contains(pair.right)) { + result.add(new PairTPHsmallerTPH(pair.left, equality.getOrDefault(pair.right, pair.right))); + typeVariables.add(pair.right); + } + } + } + + var visitedMethods = new HashSet(); method.block.accept(new TracingStatementVisitor() { @Override public void visit(MethodCall methodCall) { @@ -148,6 +179,9 @@ public class ASTToTargetAST { ).findFirst(); if (optMethod.isEmpty()) return; var method = optMethod.get(); + if (visitedMethods.contains(method)) return; + visitedMethods.add(method); + var generics = generics(owner, method); Set> all = new HashSet<>(generics); @@ -189,7 +223,11 @@ public class ASTToTargetAST { if (!(pair2.right.equals(tph2) && pair2.left.equals(type))) continue; - newPairs.add(new PairTPHsmallerTPH(tph, tph2)); + var newPair = new PairTPHsmallerTPH(tph, tph2); + newPairs.add(newPair); + + if (!containsRelation(result, newPair)) + result.add(newPair); continue outer; } } @@ -202,10 +240,10 @@ public class ASTToTargetAST { } }); - // Type variables with bounds that are also type variables of the method or type variables of fields + // Type variables with bounds that are also type variables of fields for (var typeVariable : new HashSet<>(typeVariables)) { for (var pair : simplifiedConstraints) { - if (pair.left.equals(typeVariable) && (typeVariables.contains(pair.right) || typeVariablesOfFields.contains(pair.right))) { + if (pair.left.equals(typeVariable) && typeVariablesOfFields.contains(pair.right)) { result.add(new PairTPHsmallerTPH(pair.left, equality.getOrDefault(pair.right, pair.right))); typeVariables.add(pair.right); } diff --git a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java index 279e3625..86c4e8de 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java @@ -11,6 +11,7 @@ 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 de.dhbwstuttgart.target.tree.type.TargetSpecializedType; import de.dhbwstuttgart.target.tree.type.TargetType; import java.util.List; @@ -135,12 +136,12 @@ public class StatementToTargetExpression implements StatementVisitor { var receiverType = converter.convert(methodCall.receiver.getType()); var isFunNType = receiverType instanceof TargetFunNType; var returnType = converter.convert(methodCall.getType()); - var receiverName = new JavaClassName(((TargetRefType) converter.convert(methodCall.receiver.getType())).name()); + var receiverName = new JavaClassName(((TargetSpecializedType) converter.convert(methodCall.receiver.getType())).name()); var argList = methodCall.arglist.getArguments().stream().map(expr -> converter.convert(expr.getType())).toList(); java.lang.reflect.Method foundMethod = null; - if (converter.sourceFile.imports.contains(receiverName)) { + if (converter.sourceFile != null && converter.sourceFile.imports.contains(receiverName)) { try { var clazz = converter.classLoader.loadClass(receiverName.toString()); 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 531aae1c..9012a868 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetFunNType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetFunNType.java @@ -8,6 +8,11 @@ public record TargetFunNType(int N, List params) implements TargetSp return "Fun" + N + "$$"; } + @Override + public String name() { + return getName(); + } + @Override public String toSignature() { return "L" + getName() + ";"; diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSpecializedType.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSpecializedType.java index c1f4dfc9..8bece183 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSpecializedType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSpecializedType.java @@ -18,4 +18,6 @@ public sealed interface TargetSpecializedType extends TargetType permits TargetF ret += ";"; return ret; } + + String name(); } diff --git a/src/test/java/targetast/TestComplete.java b/src/test/java/targetast/TestComplete.java index f75520df..f1271108 100644 --- a/src/test/java/targetast/TestComplete.java +++ b/src/test/java/targetast/TestComplete.java @@ -359,6 +359,13 @@ public class TestComplete { var m = tph5.getDeclaredMethod("m", Object.class, Object.class); } + @Test + public void tph7Test() throws Exception { + var classFiles = generateClassFiles("Tph7.jav", new ByteArrayClassLoader()); + var tph5 = classFiles.get("Tph7"); + var instance = tph5.getDeclaredConstructor().newInstance(); + } + @Test public void typedIdTest() throws Exception { var classFiles = generateClassFiles("TypedID.jav", new ByteArrayClassLoader()); diff --git a/src/test/resources/bytecode/javFiles/Tph7.jav b/src/test/resources/bytecode/javFiles/Tph7.jav new file mode 100644 index 00000000..e62e2288 --- /dev/null +++ b/src/test/resources/bytecode/javFiles/Tph7.jav @@ -0,0 +1,10 @@ +public class Tph7 { + m(a,b) { + var c = m2(b); + return m2(b); + } + + m2(b) { + return b; + } +} \ No newline at end of file From fa5a29c682430a45d2d8aa4d92b7c34547236c69 Mon Sep 17 00:00:00 2001 From: "pl@gohorb.ba-horb.de" Date: Sat, 6 Aug 2022 14:10:25 +0200 Subject: [PATCH 61/69] modified: src/test/resources/bytecode/javFiles/Inf.jav Kommentare erweitert --- src/test/resources/bytecode/javFiles/Inf.jav | 46 +++++++++++++++++--- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/src/test/resources/bytecode/javFiles/Inf.jav b/src/test/resources/bytecode/javFiles/Inf.jav index 3c785a6e..788fca8d 100644 --- a/src/test/resources/bytecode/javFiles/Inf.jav +++ b/src/test/resources/bytecode/javFiles/Inf.jav @@ -12,8 +12,44 @@ public class Inf { b=a; } } -// v w -// \ / -// z y b -// \ / \ / -// x a \ No newline at end of file + +/* +TPH M m(TPH N x, TPH O y, TPH P a)({ + TPH Q z; + TPH R v; + TPH S w; + TPH T b; + (y)::TPH O = (x)::TPH N; + (z)::TPH Q = (x)::TPH N; + (v)::TPH R = (y)::TPH O; + (w)::TPH S = (y)::TPH O; + (y)::TPH O = (a)::TPH P; + (b)::TPH T = (a)::TPH P; + return; + })::TPH U + + Inf()({ + super(()); + })::TPH X + +} +// v::R w::S +// \ / +// z::Q y::O b::T +// \ / \ / +// x::N a::P + +RESULT Final: [[(TPH O < TPH S), (TPH P < TPH O), (TPH O < TPH R), (TPH P < TPH T), (TPH M = void), (TPH N < TPH O), (TPH N < TPH Q)]] +Simplified constraints: [(TPH O < TPH S), (TPH P < TPH O), (TPH O < TPH R), (TPH P < TPH T), (TPH N < TPH O), (TPH N < TPH Q)] +m: [(TPH DDV = java.lang.Object), (TPH DDX = java.lang.Object), (TPH DDX < TPH DDV), (TPH N < TPH DDX), (TPH P < TPH DDX)] +Class Inf: [] +Inf: [] + +Unify nach Oder-Constraints-Anpassung: +UND:[(void =. M, , -1 WC: false, IT: false), (N <. O, 1 WC: false, IT: false, 1 WC: false, IT: false), (P <. O, 1 WC: false, IT: false, 1 WC: false, IT: false), (N <. Q, 1 WC: false, IT: false, 0 WC: true, IT: false), (O <. S, 1 WC: false, IT: false, 0 WC: true, IT: false), (O <. R, 1 WC: false, IT: false, 0 WC: true, IT: false), (P <. T, 1 WC: false, IT: false, 0 WC: true, IT: false)] +isInherited = false +isStatement = false + +ODER: +*/ + From 092d066774deefc598e1b0555bf1df189fd0b879 Mon Sep 17 00:00:00 2001 From: "pl@gohorb.ba-horb.de" Date: Sat, 6 Aug 2022 22:17:49 +0200 Subject: [PATCH 62/69] modified: ../../java/targetast/TphTest.java Test fuer Tph7 so angepasst, dass ueberprueft wird ob die richtigen Typvariablen generiert werden --- src/test/java/targetast/TphTest.java | 70 +++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 7 deletions(-) diff --git a/src/test/java/targetast/TphTest.java b/src/test/java/targetast/TphTest.java index 198bea5b..a1a1a214 100644 --- a/src/test/java/targetast/TphTest.java +++ b/src/test/java/targetast/TphTest.java @@ -5,6 +5,8 @@ import org.junit.BeforeClass; import org.junit.Test; import java.lang.reflect.Method; +import java.lang.reflect.TypeVariable; +import java.util.Arrays; import static org.junit.Assert.assertEquals; @@ -12,23 +14,77 @@ public class TphTest { private static Class classToTest; private static Object instanceOfClass; - + @BeforeClass public static void setUpBeforeClass() throws Exception { var classFiles = TestCodegen.generateClassFiles("Tph.jav", new ByteArrayClassLoader()); classToTest = classFiles.get("Tph"); instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); - classFiles = TestCodegen.generateClassFiles("Tph7.jav", new ByteArrayClassLoader()); - classToTest = classFiles.get("Tph7"); - instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); } @Test public void test1() throws Exception { + var classFiles = TestCodegen.generateClassFiles("Tph7.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("Tph7"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + + //public DZU m(DZL, DZM); Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class); - Object result = m.invoke(instanceOfClass, 1,2); - - assertEquals(1,result); + + //System.out.println(m.toString()); + + //Argumenttypes of the method m + var paraTypes = m.getGenericParameterTypes(); + + //Typeparameters of the method m + var typeParaTypes = m.getTypeParameters(); + + //Typeparameters are extracted from the argumenttypes + //Conditions for the extracted typeparameters are set + + //paraTypes[0] = DLZ + var boundFstArg = Arrays.stream(typeParaTypes) + .filter(x -> x.equals(paraTypes[0])).findFirst().get().getBounds(); + + //Bound of DLZ has to be Object + assertEquals(Object.class, Arrays.stream(boundFstArg).findFirst().get()); + + //paraTypes[0] = DZM + var boundSndArg = Arrays.stream(typeParaTypes) + .filter(x -> x.equals(paraTypes[1])).findFirst().get().getBounds(); + + //Bound of DZM has to be the return type of m + assertEquals(Arrays.stream(boundSndArg).findFirst().get(), m.getGenericReturnType()); + + //Bound of the bound of DZM + var boundBoundSndArg = Arrays.stream(typeParaTypes).filter(x -> x.equals(Arrays.stream(boundSndArg) + .findFirst().get())).findFirst().get().getBounds(); + + //boundBoundSndArg have to be a type variable (type of the local variable c) + assertEquals(true, Arrays.stream(boundBoundSndArg).findFirst().get() instanceof TypeVariable); + m.getGenericParameterTypes(); + + //public DZU m2(DZU); + Method m2 = classToTest.getDeclaredMethod("m2", Object.class); + + //Argumenttypes of the method m2 + var paraTypesm2 = m2.getGenericParameterTypes(); + + //Typeparameters of the method m2 + var typeParaTypesm2 = m2.getTypeParameters(); + + //Typeparameters are extracted from the argumenttypes + //Conditions for the extracted typeparameters are set + + //paraTypes[0] = DZU + var fstArgm2 = Arrays.stream(typeParaTypesm2) + .filter(x -> x.equals(paraTypesm2[0])).findFirst().get(); + + //Bound of DZU has to be Object + assertEquals(Object.class, Arrays.stream(fstArgm2.getBounds()).findFirst().get()); + + //DZU has to be the return type of m + assertEquals(fstArgm2, m2.getGenericReturnType()); } @Test From bca02137a67f7c0c1fb65ec249743027a893b3a7 Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Sun, 7 Aug 2022 20:09:57 +0200 Subject: [PATCH 63/69] Fix method calls in matrixOp --- pom.xml | 4 +- .../target/bytecode/Codegen.java | 69 ++++++++++------- .../target/generate/ASTToTargetAST.java | 61 +++++++++------ .../generate/StatementToTargetExpression.java | 77 +++++++++++++------ .../target/tree/TargetClass.java | 2 +- .../target/tree/TargetConstructor.java | 2 +- .../tree/type/TargetExtendsWildcard.java | 9 ++- .../target/tree/type/TargetFunNType.java | 6 +- .../target/tree/type/TargetGenericType.java | 4 +- .../target/tree/type/TargetPrimitiveType.java | 4 +- .../target/tree/type/TargetRefType.java | 6 +- .../tree/type/TargetSpecializedType.java | 4 +- .../target/tree/type/TargetSuperWildcard.java | 11 ++- .../target/tree/type/TargetType.java | 6 +- src/test/java/targetast/TphTest.java | 3 - 15 files changed, 162 insertions(+), 106 deletions(-) diff --git a/pom.xml b/pom.xml index c2ee1230..3f7cc7e3 100644 --- a/pom.xml +++ b/pom.xml @@ -122,8 +122,8 @@ http://maven.apache.org/maven-v4_0_0.xsd"> org.apache.maven.plugins maven-compiler-plugin - 18 - 18 + 17 + 17 --enable-preview diff --git a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java index c361c893..774a4f01 100755 --- a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java @@ -2,10 +2,7 @@ package de.dhbwstuttgart.target.bytecode; import de.dhbwstuttgart.target.tree.*; import de.dhbwstuttgart.target.tree.expression.*; -import de.dhbwstuttgart.target.tree.type.TargetFunNType; -import de.dhbwstuttgart.target.tree.type.TargetPrimitiveType; -import de.dhbwstuttgart.target.tree.type.TargetRefType; -import de.dhbwstuttgart.target.tree.type.TargetType; +import de.dhbwstuttgart.target.tree.type.*; import org.objectweb.asm.*; import java.lang.invoke.CallSite; @@ -13,10 +10,9 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; -import java.util.Objects; import java.util.Set; -import java.util.stream.IntStream; import static org.objectweb.asm.Opcodes.*; import static de.dhbwstuttgart.target.tree.expression.TargetBinaryOp.*; @@ -26,6 +22,8 @@ public class Codegen { private final TargetClass clazz; private final ClassWriter cw; public final String className; + private int lambdaCounter = 0; + private final HashMap lambdas = new HashMap<>(); public Codegen(TargetClass clazz) { this.clazz = clazz; @@ -62,7 +60,6 @@ public class Codegen { private static class State { Scope scope = new Scope(null); int localCounter; - int lambdaCounter; MethodVisitor mv; State(MethodVisitor mv, int localCounter) { @@ -243,7 +240,7 @@ public class Codegen { mv.visitInsn(I2D); } else { boxPrimitive(state, source); - mv.visitTypeInsn(CHECKCAST, dest.getName()); + mv.visitTypeInsn(CHECKCAST, dest.getInternalName()); unboxPrimitive(state, dest); } } @@ -578,7 +575,7 @@ public class Codegen { } else if (op.expr() instanceof TargetFieldVar fieldVar) { generate(state, fieldVar.left()); mv.visitInsn(SWAP); - mv.visitFieldInsn(PUTFIELD, fieldVar.owner().getName(), fieldVar.right(), fieldVar.type().toSignature()); + mv.visitFieldInsn(PUTFIELD, fieldVar.owner().getInternalName(), fieldVar.right(), fieldVar.type().toSignature()); } } @@ -702,12 +699,19 @@ public class Codegen { private void generateLambdaExpression(State state, TargetLambdaExpression lambda) { var mv = state.mv; - var name = "lambda$" + state.lambdaCounter; - var impl = new TargetMethod( - 0, name, Set.of(), - lambda.params(), lambda.returnType(), lambda.block() - ); - generateMethod(impl); + + TargetMethod impl; + if (lambdas.containsKey(lambda)) { + impl = lambdas.get(lambda); + } else { + var name = "lambda$" + lambdaCounter++; + impl = new TargetMethod( + 0, name, Set.of(), + lambda.params(), lambda.returnType(), lambda.block() + ); + generateMethod(impl); + lambdas.put(lambda, impl); + } var mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, MethodType.class, MethodHandle.class, MethodType.class); @@ -715,7 +719,7 @@ public class Codegen { var bootstrap = new Handle(H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "metafactory", mt.toMethodDescriptorString(), false); var handle = new Handle( - H_INVOKEVIRTUAL, clazz.getName(), name, + H_INVOKEVIRTUAL, clazz.getName(), impl.name(), impl.getDescriptor(), false ); @@ -731,8 +735,6 @@ public class Codegen { mv.visitVarInsn(ALOAD, 0); mv.visitInvokeDynamicInsn("apply", TargetMethod.getDescriptor(lambda.type(), new TargetRefType(clazz.qualifiedName())), bootstrap, Type.getType(desugared), handle, Type.getType(impl.getDescriptor())); - - state.lambdaCounter++; } private void generate(State state, TargetExpression expr) { @@ -760,7 +762,7 @@ public class Codegen { convertTo(state, cast.expr().type(), cast.type()); break; case TargetInstanceOf instanceOf: - mv.visitTypeInsn(INSTANCEOF, instanceOf.right().getName()); + mv.visitTypeInsn(INSTANCEOF, instanceOf.right().getInternalName()); break; case TargetLiteral literal: switch (literal) { @@ -823,7 +825,7 @@ public class Codegen { if (dot.isStatic()) mv.visitInsn(DUP); else mv.visitInsn(DUP_X1); - mv.visitFieldInsn(dot.isStatic() ? PUTSTATIC : PUTFIELD, dot.owner().getName(), dot.right(), dot.type().toSignature()); + mv.visitFieldInsn(dot.isStatic() ? PUTSTATIC : PUTFIELD, dot.owner().getInternalName(), dot.right(), dot.type().toSignature()); break; } default: @@ -840,7 +842,7 @@ public class Codegen { case TargetFieldVar dot: { if (!dot.isStatic()) generate(state, dot.left()); - mv.visitFieldInsn(dot.isStatic() ? GETSTATIC : GETFIELD, dot.left().type().getName(), dot.right(), dot.type().toSignature()); + mv.visitFieldInsn(dot.isStatic() ? GETSTATIC : GETFIELD, dot.left().type().getInternalName(), dot.right(), dot.type().toSignature()); unboxPrimitive(state, dot.type()); break; } @@ -926,11 +928,11 @@ public class Codegen { ); mv.visitMethodInsn(call.isInterface() ? INVOKEINTERFACE : call.isStatic() ? INVOKESTATIC: call.name().equals("") ? INVOKESPECIAL : INVOKEVIRTUAL, - call.owner().getName(), call.name(), descriptor, call.isInterface()); + call.owner().getInternalName(), call.name(), descriptor, call.isInterface()); if (call.returnType() != null && !(call.returnType() instanceof TargetPrimitiveType)) { - if (!call.returnType().equals(call.type())) - mv.visitTypeInsn(CHECKCAST, call.type().getName()); + if (!call.returnType().equals(call.type()) && !(call.type() instanceof TargetGenericType)) + mv.visitTypeInsn(CHECKCAST, call.type().getInternalName()); else unboxPrimitive(state, call.type()); } break; @@ -939,13 +941,13 @@ public class Codegen { generateLambdaExpression(state, lambda); break; case TargetNew _new: { - mv.visitTypeInsn(NEW, _new.type().getName()); + mv.visitTypeInsn(NEW, _new.type().getInternalName()); mv.visitInsn(DUP); for (TargetExpression e : _new.params()) { generate(state, e); boxPrimitive(state, e.type()); } - mv.visitMethodInsn(INVOKESPECIAL, _new.type().getName(), "", _new.getDescriptor(), false); + mv.visitMethodInsn(INVOKESPECIAL, _new.type().getInternalName(), "", _new.getDescriptor(), false); break; } default: @@ -963,7 +965,18 @@ public class Codegen { var state = new State(mv, 1); for (var param: constructor.parameters()) state.createVariable(param.name(), param.type()); - generate(state, constructor.block()); + + var stmts = constructor.block().statements(); + generate(state, stmts.get(0)); + if (constructor.fieldInitializer() != null) { + var stmts2 = constructor.fieldInitializer().statements(); + for (var i = 1; i < stmts2.size(); i++) { + generate(state, stmts2.get(i)); + } + } + for (var i = 1; i < stmts.size(); i++) + generate(state, stmts.get(i)); + mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); @@ -996,7 +1009,7 @@ public class Codegen { public byte[] generate() { cw.visit(V1_8, clazz.modifiers() | ACC_PUBLIC, clazz.qualifiedName(), - generateSignature(clazz), clazz.superType() != null ? clazz.superType().getName(): "java/lang/Object", + generateSignature(clazz), clazz.superType() != null ? clazz.superType().getInternalName(): "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 310d24a3..bd122e55 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -1,6 +1,7 @@ package de.dhbwstuttgart.target.generate; import de.dhbwstuttgart.bytecode.funN.FunNGenerator; +import de.dhbwstuttgart.core.JavaTXCompiler; import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; @@ -174,9 +175,7 @@ public class ASTToTargetAST { if (methodCall.receiver instanceof ExpressionReceiver expressionReceiver) { if (expressionReceiver.expr instanceof This) { - var optMethod = owner.getMethods().stream().filter( - m -> m.name.equals(methodCall.name) && parameterEquals(methodCall.getArgumentList(), methodCall.getArgumentList().getArguments()) - ).findFirst(); + var optMethod = findMethod(owner, methodCall.name, methodCall.getArgumentList()); if (optMethod.isEmpty()) return; var method = optMethod.get(); if (visitedMethods.contains(method)) return; @@ -451,19 +450,6 @@ public class ASTToTargetAST { } } - private boolean parameterEquals(ArgumentList argumentList, List arguments) { - if (argumentList.getArguments().size() != arguments.size()) - return false; - - for (var i = 0; i < argumentList.getArguments().size(); i++) { - var type1 = convert(argumentList.getArguments().get(i).getType()); - var type2 = convert(arguments.get(i).getType()); - if (!type1.equals(type2)) return false; - } - - return true; - } - protected ByteArrayClassLoader classLoader; protected SourceFile sourceFile; @@ -571,6 +557,27 @@ public class ASTToTargetAST { return cycles; } + Optional findMethod(ClassOrInterface owner, String name, ArgumentList argumentList) { + return owner.getMethods().stream().filter( + m -> m.name.equals(name) && parameterEquals(m.getParameterList(), argumentList) + ).findFirst(); + } + + boolean parameterEquals(ParameterList parameterList, ArgumentList argumentList) { + var pars = parameterList.getFormalparalist(); + var arguments = argumentList.getArguments(); + if (pars.size() != arguments.size()) + return false; + + for (var i = 0; i < pars.size(); i++) { + var type1 = convert(pars.get(i).getType()); + var type2 = convert(arguments.get(i).getType()); + if (!type1.equals(type2)) return false; + } + + return true; + } + Set convert(Set> result) { return result.stream().map(p -> { if (p instanceof PairTPHsmallerTPH pair) { @@ -584,12 +591,18 @@ public class ASTToTargetAST { } public TargetClass convert(ClassOrInterface input) { + currentClass = input; + TargetBlock fieldInitializer = null; + if (input.getfieldInitializations().isPresent()) + fieldInitializer = convert(input.getfieldInitializations().get().block); + TargetBlock finalFieldInitializer = fieldInitializer; + return new TargetClass(input.getModifiers(), input.getClassName().toString(), convert(input.getSuperClass()), convert(sigma.generics(input)), input.getSuperInterfaces().stream().map(this::convert).toList(), - input.getConstructors().stream().map(constructor -> this.convert(input, constructor)).flatMap(List::stream).toList(), + input.getConstructors().stream().map(constructor -> this.convert(constructor, finalFieldInitializer)).flatMap(List::stream).toList(), input.getFieldDecl().stream().map(this::convert).toList(), - input.getMethods().stream().map(method -> this.convert(input, method)).flatMap(List::stream).toList() + input.getMethods().stream().map(this::convert).flatMap(List::stream).toList() ); } @@ -598,18 +611,17 @@ public class ASTToTargetAST { .map(param -> new MethodParameter(convert(param.getType()), param.getName())).toList(); } - private List convert(ClassOrInterface owner, Constructor input) { - currentClass = owner; + private List convert(Constructor input, TargetBlock fieldInitializer) { sigma = all.get(0); List result = new ArrayList<>(); Set> parameterSet = new HashSet<>(); for (var s : all) { sigma = s; - var generics = sigma.generics(owner, input); + var generics = sigma.generics(currentClass, input); List params = convert(input.getParameterList()); if (parameterSet.stream().noneMatch(p -> p.equals(params))) { - result.add(new TargetConstructor(input.modifier, convert(generics), params, convert(input.block))); + result.add(new TargetConstructor(input.modifier, convert(generics), params, convert(input.block), fieldInitializer)); parameterSet.add(params); } } @@ -617,15 +629,14 @@ public class ASTToTargetAST { return result; } - private List convert(ClassOrInterface owner, Method input) { - currentClass = owner; + private List convert(Method input) { sigma = all.get(0); List result = new ArrayList<>(); Set> parameterSet = new HashSet<>(); for (var s : all) { sigma = s; - var generics = sigma.generics(owner, input); + var generics = sigma.generics(currentClass, input); List params = convert(input.getParameterList()); if (parameterSet.stream().noneMatch(p -> p.equals(params))) { result.add(new TargetMethod( diff --git a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java index 86c4e8de..5a8a2235 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java @@ -3,7 +3,7 @@ package de.dhbwstuttgart.target.generate; import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; import de.dhbwstuttgart.parser.scope.JavaClassName; -import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.StatementVisitor; import de.dhbwstuttgart.syntaxtree.statement.*; import de.dhbwstuttgart.syntaxtree.type.RefType; @@ -14,7 +14,10 @@ import de.dhbwstuttgart.target.tree.type.TargetRefType; import de.dhbwstuttgart.target.tree.type.TargetSpecializedType; import de.dhbwstuttgart.target.tree.type.TargetType; +import java.lang.reflect.Method; import java.util.List; +import java.util.Objects; +import java.util.Optional; import java.util.stream.Stream; import java.util.stream.StreamSupport; @@ -131,36 +134,60 @@ public class StatementToTargetExpression implements StatementVisitor { result = new TargetVarDecl(converter.convert(localVarDecl.getType()), localVarDecl.getName(), null); } + static boolean convertsTo(TargetType from, TargetType to) { + if (to.equals(TargetType.Object)) return true; // TODO Consider type coercion and suptyping + return to.equals(from); + } + + Method findMethod(JavaClassName className, String name, List args) { + if (converter.sourceFile != null && converter.sourceFile.imports.contains(className)) { + try { + var clazz = converter.classLoader.loadClass(className.toString()); + + outer: for (var method : clazz.getMethods()) { + if (method.getParameterTypes().length != args.size()) continue; + if (!method.getName().equals(name)) continue; + + for (var i = 0; i < method.getParameterTypes().length; i++) { + var param = method.getParameterTypes()[i]; + var arg = args.get(i); + if (param.isPrimitive()) { + arg = TargetType.toPrimitive(arg); + } + if (!convertsTo(arg, Objects.requireNonNull(TargetType.toTargetType(param)))) continue outer; + } + return method; + } + } catch (ClassNotFoundException ignored) {} + } + if (converter.sourceFile != null) { // TODO Multiple source files + var thisClass = converter.sourceFile.KlassenVektor.stream() + .filter(classOrInterface -> classOrInterface.getClassName().equals(className)).findFirst(); + + if (thisClass.isPresent()) { + var superClass = thisClass.get().getSuperClass().getName(); + return findMethod(superClass, name, args); + } + } + return null; + } + @Override public void visit(MethodCall methodCall) { var receiverType = converter.convert(methodCall.receiver.getType()); var isFunNType = receiverType instanceof TargetFunNType; - var returnType = converter.convert(methodCall.getType()); - var receiverName = new JavaClassName(((TargetSpecializedType) converter.convert(methodCall.receiver.getType())).name()); - + var returnType = isFunNType ? TargetType.Object : converter.convert(methodCall.getType()); + var receiverName = new JavaClassName(converter.convert(methodCall.receiver.getType()).name()); var argList = methodCall.arglist.getArguments().stream().map(expr -> converter.convert(expr.getType())).toList(); - java.lang.reflect.Method foundMethod = null; - if (converter.sourceFile != null && converter.sourceFile.imports.contains(receiverName)) { - try { - var clazz = converter.classLoader.loadClass(receiverName.toString()); - - outer: for (var method : clazz.getMethods()) { - if (method.getParameterTypes().length != argList.size()) continue; - if (!method.getName().equals(methodCall.name)) continue; - - for (var i = 0; i < method.getParameterTypes().length; i++) { - var param = method.getParameterTypes()[i]; - var arg = argList.get(i); - if (param.isPrimitive()) { - arg = TargetType.toPrimitive(arg); - } - if (!TargetType.toTargetType(param).equals(arg)) continue outer; - } - foundMethod = method; - break; - } - } catch (ClassNotFoundException ignored) {} + Method foundMethod = null; + if (methodCall.receiver instanceof ExpressionReceiver expressionReceiver && expressionReceiver.expr instanceof This) { + var thisMethod = converter.findMethod(converter.currentClass, methodCall.name, methodCall.arglist); + if (thisMethod.isEmpty()) { + foundMethod = findMethod(converter.currentClass.getSuperClass().getName(), methodCall.name, argList); + } + } else { + foundMethod = findMethod(receiverName, methodCall.name, argList); } if (foundMethod != null) { diff --git a/src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java index 407b71b2..50cb9f71 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java @@ -33,7 +33,7 @@ public record TargetClass(int modifiers, String qualifiedName, TargetType superT } public void addConstructor(int access, Set generics, List paramterTypes, TargetBlock block) { - this.constructors.add(new TargetConstructor(access, generics, paramterTypes, block)); + this.constructors.add(new TargetConstructor(access, generics, paramterTypes, block, null)); } public void addConstructor(int access, List paramterTypes, TargetBlock block) { diff --git a/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java index dc7f01ac..4d2cca14 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java @@ -6,7 +6,7 @@ import de.dhbwstuttgart.target.tree.type.TargetType; import java.util.List; import java.util.Set; -public record TargetConstructor(int access, Set generics, List parameters, TargetBlock block) { +public record TargetConstructor(int access, Set generics, List parameters, TargetBlock block, TargetBlock fieldInitializer) { 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/type/TargetExtendsWildcard.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java index d5b67745..7e5ab002 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java @@ -12,8 +12,13 @@ public record TargetExtendsWildcard(TargetType innerType) implements TargetType } @Override - public String getName() { - return innerType.getName(); + public String getInternalName() { + return innerType.getInternalName(); + } + + @Override + public String name() { + return innerType.name(); } } 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 9012a868..e9379de6 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetFunNType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetFunNType.java @@ -4,17 +4,17 @@ import java.util.List; public record TargetFunNType(int N, List params) implements TargetSpecializedType { @Override - public String getName() { + public String getInternalName() { return "Fun" + N + "$$"; } @Override public String name() { - return getName(); + return getInternalName(); } @Override public String toSignature() { - return "L" + getName() + ";"; + return "L" + getInternalName() + ";"; } } 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 cc9e4bb2..15900fb4 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetGenericType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetGenericType.java @@ -8,11 +8,11 @@ public record TargetGenericType(String name) implements TargetType { @Override public String toGenericSignature() { - return "T" + getName() + ";"; + return "T" + getInternalName() + ";"; } @Override - public String getName() { + public String getInternalName() { return name; } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetPrimitiveType.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetPrimitiveType.java index 3f170d18..9d3bbf46 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetPrimitiveType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetPrimitiveType.java @@ -4,7 +4,7 @@ public record TargetPrimitiveType(String name) implements TargetType { @Override public String toSignature() { - return getName(); + return getInternalName(); } @Override @@ -13,7 +13,7 @@ public record TargetPrimitiveType(String name) implements TargetType { } @Override - public String getName() { + public String getInternalName() { return name; } } 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 bdd92e03..0d043555 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetRefType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetRefType.java @@ -1,7 +1,5 @@ package de.dhbwstuttgart.target.tree.type; -import de.dhbwstuttgart.target.tree.type.TargetType; - import java.util.List; import java.util.Objects; @@ -10,13 +8,13 @@ public record TargetRefType(String name, List params) implements Tar this(name, List.of()); } - public String getName() { + public String getInternalName() { return this.name.replaceAll("\\.", "/"); } @Override public String toSignature() { - return "L" + getName() + ";"; + return "L" + getInternalName() + ";"; } // Type erasure means we need to override hashCode and equals to only consider the name diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSpecializedType.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSpecializedType.java index 8bece183..2a74307c 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSpecializedType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSpecializedType.java @@ -7,7 +7,7 @@ public sealed interface TargetSpecializedType extends TargetType permits TargetF @Override default String toGenericSignature() { - String ret = "L" + getName(); + String ret = "L" + getInternalName(); if (params().size() > 0) { ret += "<"; for (var param : params()) { @@ -18,6 +18,4 @@ public sealed interface TargetSpecializedType extends TargetType permits TargetF ret += ";"; return ret; } - - String name(); } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java index b1a78907..bf16e143 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java @@ -12,7 +12,14 @@ public record TargetSuperWildcard(TargetType innerType) implements TargetType { } @Override - public String getName() { - return innerType.getName(); + public String getInternalName() { + return innerType.getInternalName(); + } + + @Override + public String name() { + return innerType.name(); } } + + 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 63cbb945..36d71af1 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetType.java @@ -1,7 +1,5 @@ package de.dhbwstuttgart.target.tree.type; -import java.util.List; - public sealed interface TargetType permits TargetExtendsWildcard, TargetGenericType, TargetSpecializedType, TargetSuperWildcard, TargetPrimitiveType { @@ -50,10 +48,12 @@ public sealed interface TargetType if (clazz.equals(float.class)) return float_; if (clazz.equals(double.class)) return double_; } + if (clazz.equals(void.class)) return null; return new TargetRefType(clazz.getName()); } String toSignature(); String toGenericSignature(); - String getName(); + String getInternalName(); + String name(); } diff --git a/src/test/java/targetast/TphTest.java b/src/test/java/targetast/TphTest.java index 198bea5b..c2bb9835 100644 --- a/src/test/java/targetast/TphTest.java +++ b/src/test/java/targetast/TphTest.java @@ -18,9 +18,6 @@ public class TphTest { var classFiles = TestCodegen.generateClassFiles("Tph.jav", new ByteArrayClassLoader()); classToTest = classFiles.get("Tph"); instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); - classFiles = TestCodegen.generateClassFiles("Tph7.jav", new ByteArrayClassLoader()); - classToTest = classFiles.get("Tph7"); - instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); } @Test From 56f68e84e49658e686630b33952f895204b89273 Mon Sep 17 00:00:00 2001 From: "pl@gohorb.ba-horb.de" Date: Mon, 8 Aug 2022 11:09:19 +0200 Subject: [PATCH 64/69] modified: ../../java/targetast/TestComplete.java Test Tph2Test eingefue=gt modified: ../bytecode/javFiles/Tph2.jav Zeilen auskommentiert, die bereits in anderen Tests enthalten --- src/test/java/targetast/TestComplete.java | 6 ++++++ src/test/resources/bytecode/javFiles/Tph2.jav | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/test/java/targetast/TestComplete.java b/src/test/java/targetast/TestComplete.java index f1271108..d0e07540 100644 --- a/src/test/java/targetast/TestComplete.java +++ b/src/test/java/targetast/TestComplete.java @@ -337,6 +337,12 @@ public class TestComplete { var instance = classFiles.get("SubMatrix").getDeclaredConstructor().newInstance(); } + @Test + public void tph2Test() throws Exception { + var classFiles = generateClassFiles("Tph2.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("Tph2").getDeclaredConstructor().newInstance(); + } + @Test public void tph3Test() throws Exception { var classFiles = generateClassFiles("Tph3.jav", new ByteArrayClassLoader()); diff --git a/src/test/resources/bytecode/javFiles/Tph2.jav b/src/test/resources/bytecode/javFiles/Tph2.jav index 760e4fa7..2f9c53e6 100644 --- a/src/test/resources/bytecode/javFiles/Tph2.jav +++ b/src/test/resources/bytecode/javFiles/Tph2.jav @@ -4,7 +4,7 @@ public class Tph2 { return id.apply(x); } - +/* m(a,b){ var c = m2(a,b); //m2(a,b); @@ -14,4 +14,5 @@ public class Tph2 { m2(a,b){ return b; } +*/ } \ No newline at end of file From d54cd5e20a5c2de68f8278070445f937dea0a202 Mon Sep 17 00:00:00 2001 From: "pl@gohorb.ba-horb.de" Date: Mon, 8 Aug 2022 14:45:58 +0200 Subject: [PATCH 65/69] modified: ../../../../pom.xml wieder auf Java-18 umgestellt modified: ../../java/targetast/TestComplete.java Test Tph4Test eingefuegt --- pom.xml | 8 ++++---- src/test/java/targetast/TestComplete.java | 7 +++++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 3f7cc7e3..7c12ddfd 100644 --- a/pom.xml +++ b/pom.xml @@ -122,8 +122,8 @@ http://maven.apache.org/maven-v4_0_0.xsd"> org.apache.maven.plugins maven-compiler-plugin - 17 - 17 + 18 + 18 --enable-preview @@ -138,8 +138,8 @@ http://maven.apache.org/maven-v4_0_0.xsd"> UTF-8 UTF-8 - 17 - 17 + 18 + 18 --enable-preview diff --git a/src/test/java/targetast/TestComplete.java b/src/test/java/targetast/TestComplete.java index d0e07540..c30dfed0 100644 --- a/src/test/java/targetast/TestComplete.java +++ b/src/test/java/targetast/TestComplete.java @@ -349,6 +349,13 @@ public class TestComplete { var instance = classFiles.get("Tph3").getDeclaredConstructor().newInstance(); } + @Test + public void tph4Test() throws Exception { + var classFiles = generateClassFiles("Tph4.jav", new ByteArrayClassLoader()); + var tph5 = classFiles.get("Tph4"); + var instance = tph5.getDeclaredConstructor().newInstance(); + } + @Test public void tph5Test() throws Exception { var classFiles = generateClassFiles("Tph5.jav", new ByteArrayClassLoader()); From f36f981ca8cea11c3d61262c8cbe2782208d6ddf Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Mon, 8 Aug 2022 14:50:43 +0200 Subject: [PATCH 66/69] Lambda captures --- .../target/bytecode/Codegen.java | 27 +++++++---- .../generate/StatementToTargetExpression.java | 45 +++++++++++++++++-- .../generate/TracingStatementVisitor.java | 2 +- .../expression/TargetLambdaExpression.java | 3 +- src/test/java/targetast/TestCodegen.java | 2 +- src/test/java/targetast/TphTest.java | 4 +- 6 files changed, 66 insertions(+), 17 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java index 774a4f01..04bee492 100755 --- a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java @@ -1,5 +1,6 @@ package de.dhbwstuttgart.target.bytecode; +import de.dhbwstuttgart.syntaxtree.statement.Block; import de.dhbwstuttgart.target.tree.*; import de.dhbwstuttgart.target.tree.expression.*; import de.dhbwstuttgart.target.tree.type.*; @@ -9,10 +10,7 @@ import java.lang.invoke.CallSite; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; import static org.objectweb.asm.Opcodes.*; import static de.dhbwstuttgart.target.tree.expression.TargetBinaryOp.*; @@ -705,9 +703,12 @@ public class Codegen { impl = lambdas.get(lambda); } else { var name = "lambda$" + lambdaCounter++; + var parameters = new ArrayList<>(lambda.captures()); + parameters.addAll(lambda.params()); + impl = new TargetMethod( 0, name, Set.of(), - lambda.params(), lambda.returnType(), lambda.block() + parameters, lambda.returnType(), lambda.block() ); generateMethod(impl); lambdas.put(lambda, impl); @@ -732,9 +733,19 @@ public class Codegen { desugared += "Ljava/lang/Object;"; else desugared += "V"; + var params = new ArrayList(); + params.add(new TargetRefType(clazz.qualifiedName())); + params.addAll(lambda.captures().stream().map(MethodParameter::type).toList()); + + var descriptor = TargetMethod.getDescriptor(lambda.type(), params.toArray(TargetType[]::new)); mv.visitVarInsn(ALOAD, 0); - mv.visitInvokeDynamicInsn("apply", TargetMethod.getDescriptor(lambda.type(), new TargetRefType(clazz.qualifiedName())), - bootstrap, Type.getType(desugared), handle, Type.getType(impl.getDescriptor())); + for (var capture : lambda.captures()) + mv.visitVarInsn(ALOAD, state.scope.get(capture.name()).index); + + mv.visitInvokeDynamicInsn("apply", descriptor, + bootstrap, Type.getType(desugared), handle, + Type.getType(TargetMethod.getDescriptor(impl.returnType(), lambda.params().stream().map(MethodParameter::type).toArray(TargetType[]::new))) + ); } private void generate(State state, TargetExpression expr) { @@ -933,7 +944,7 @@ public class Codegen { if (call.returnType() != null && !(call.returnType() instanceof TargetPrimitiveType)) { if (!call.returnType().equals(call.type()) && !(call.type() instanceof TargetGenericType)) mv.visitTypeInsn(CHECKCAST, call.type().getInternalName()); - else unboxPrimitive(state, call.type()); + unboxPrimitive(state, call.type()); } break; } diff --git a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java index 5a8a2235..8ca6e052 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java @@ -15,9 +15,7 @@ import de.dhbwstuttgart.target.tree.type.TargetSpecializedType; import de.dhbwstuttgart.target.tree.type.TargetType; import java.lang.reflect.Method; -import java.util.List; -import java.util.Objects; -import java.util.Optional; +import java.util.*; import java.util.stream.Stream; import java.util.stream.StreamSupport; @@ -41,9 +39,48 @@ public class StatementToTargetExpression implements StatementVisitor { .stream(lambdaExpression.params.spliterator(), false) .map(p -> new MethodParameter(converter.convert(p.getType()), p.getName())) .toList(); + + List captures = new ArrayList<>(); + lambdaExpression.methodBody.accept(new TracingStatementVisitor() { + // TODO The same mechanism is implemented in Codegen, maybe use it from there? + final Stack> localVariables = new Stack<>(); + { localVariables.push(new HashSet<>()); } + + boolean hasLocalVar(String name) { + for (var localVariables : this.localVariables) { + if (localVariables.contains(name)) return true; + } + return false; + } + + @Override + public void visit(Block block) { + localVariables.push(new HashSet<>()); + super.visit(block); + localVariables.pop(); + } + + @Override + public void visit(LocalVar localVar) { + super.visit(localVar); + var capture = new MethodParameter(converter.convert(localVar.getType()), localVar.name); + if (!hasLocalVar(localVar.name) && !parameters.contains(capture) && !captures.contains(capture)) + captures.add(capture); + } + + @Override + public void visit(LocalVarDecl varDecl) { + var localVariables = this.localVariables.peek(); + localVariables.add(varDecl.getName()); + } + + @Override + public void visit(LambdaExpression lambda) {} // Don't look at lambda expressions + }); + result = new TargetLambdaExpression( new TargetFunNType(parameters.size(), parameters.stream().map(MethodParameter::type).toList()), - parameters, converter.convert(lambdaExpression.getReturnType()), converter.convert(lambdaExpression.methodBody) + captures, parameters, converter.convert(lambdaExpression.getReturnType()), converter.convert(lambdaExpression.methodBody) ); } diff --git a/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java b/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java index 7a7352ad..6fc9c248 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java @@ -144,7 +144,7 @@ public abstract class TracingStatementVisitor implements StatementVisitor { @Override public void visit(ExpressionReceiver expressionReceiver) { - + expressionReceiver.expr.accept(this); } @Override diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLambdaExpression.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLambdaExpression.java index c0a5a811..718fb663 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLambdaExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLambdaExpression.java @@ -1,9 +1,10 @@ package de.dhbwstuttgart.target.tree.expression; import de.dhbwstuttgart.target.tree.MethodParameter; +import de.dhbwstuttgart.target.tree.TargetField; import de.dhbwstuttgart.target.tree.type.TargetType; import java.util.List; -public record TargetLambdaExpression(TargetType type, List params, TargetType returnType, TargetBlock block) implements TargetExpression { +public record TargetLambdaExpression(TargetType type, List captures, List params, TargetType returnType, TargetBlock block) implements TargetExpression { } diff --git a/src/test/java/targetast/TestCodegen.java b/src/test/java/targetast/TestCodegen.java index 165dff72..46c4c834 100644 --- a/src/test/java/targetast/TestCodegen.java +++ b/src/test/java/targetast/TestCodegen.java @@ -330,7 +330,7 @@ public class TestCodegen { targetClass.addMethod(Opcodes.ACC_PUBLIC, "lambda", List.of(), TargetType.Integer, new TargetBlock(List.of( new TargetVarDecl(interfaceType, "by2", - new TargetLambdaExpression(interfaceType, List.of(new MethodParameter(TargetType.Integer, "num")), TargetType.Integer, + new TargetLambdaExpression(interfaceType, List.of(), List.of(new MethodParameter(TargetType.Integer, "num")), TargetType.Integer, new TargetBlock(List.of( new TargetReturn(new TargetBinaryOp.Mul(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "num"), diff --git a/src/test/java/targetast/TphTest.java b/src/test/java/targetast/TphTest.java index a1a1a214..c3f29c7f 100644 --- a/src/test/java/targetast/TphTest.java +++ b/src/test/java/targetast/TphTest.java @@ -25,8 +25,8 @@ public class TphTest { @Test public void test1() throws Exception { var classFiles = TestCodegen.generateClassFiles("Tph7.jav", new ByteArrayClassLoader()); - classToTest = classFiles.get("Tph7"); - instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + var classToTest = classFiles.get("Tph7"); + var instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); //public DZU m(DZL, DZM); Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class); From c933160dcbc5de5eac1287840a57f9d41ae43d3e Mon Sep 17 00:00:00 2001 From: "pl@gohorb.ba-horb.de" Date: Mon, 8 Aug 2022 15:24:46 +0200 Subject: [PATCH 67/69] modified: ../../java/targetast/TestComplete.java Test Tph7.jav in integriert. --- src/test/java/targetast/TestComplete.java | 75 +++++++++++++++++++++-- 1 file changed, 69 insertions(+), 6 deletions(-) diff --git a/src/test/java/targetast/TestComplete.java b/src/test/java/targetast/TestComplete.java index c30dfed0..7c22c388 100644 --- a/src/test/java/targetast/TestComplete.java +++ b/src/test/java/targetast/TestComplete.java @@ -4,6 +4,9 @@ import de.dhbwstuttgart.target.ByteArrayClassLoader; import org.junit.Ignore; import org.junit.Test; +import java.lang.reflect.Method; +import java.lang.reflect.TypeVariable; +import java.util.Arrays; import java.util.Vector; import static org.junit.Assert.*; @@ -372,12 +375,72 @@ public class TestComplete { var m = tph5.getDeclaredMethod("m", Object.class, Object.class); } - @Test - public void tph7Test() throws Exception { - var classFiles = generateClassFiles("Tph7.jav", new ByteArrayClassLoader()); - var tph5 = classFiles.get("Tph7"); - var instance = tph5.getDeclaredConstructor().newInstance(); - } + + @Test + public void Tph7Test() throws Exception { + var classFiles = TestCodegen.generateClassFiles("Tph7.jav", new ByteArrayClassLoader()); + var classToTest = classFiles.get("Tph7"); + var instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + + //public DZU m(DZL, DZM); + Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class); + + //System.out.println(m.toString()); + + //Argumenttypes of the method m + var paraTypes = m.getGenericParameterTypes(); + + //Typeparameters of the method m + var typeParaTypes = m.getTypeParameters(); + + //Typeparameters are extracted from the argumenttypes + //Conditions for the extracted typeparameters are set + + //paraTypes[0] = DLZ + var boundFstArg = Arrays.stream(typeParaTypes) + .filter(x -> x.equals(paraTypes[0])).findFirst().get().getBounds(); + + //Bound of DLZ has to be Object + assertEquals(Object.class, Arrays.stream(boundFstArg).findFirst().get()); + + //paraTypes[0] = DZM + var boundSndArg = Arrays.stream(typeParaTypes) + .filter(x -> x.equals(paraTypes[1])).findFirst().get().getBounds(); + + //Bound of DZM has to be the return type of m + assertEquals(Arrays.stream(boundSndArg).findFirst().get(), m.getGenericReturnType()); + + //Bound of the bound of DZM + var boundBoundSndArg = Arrays.stream(typeParaTypes).filter(x -> x.equals(Arrays.stream(boundSndArg) + .findFirst().get())).findFirst().get().getBounds(); + + //boundBoundSndArg have to be a type variable (type of the local variable c) + assertEquals(true, Arrays.stream(boundBoundSndArg).findFirst().get() instanceof TypeVariable); + m.getGenericParameterTypes(); + + //public DZU m2(DZU); + Method m2 = classToTest.getDeclaredMethod("m2", Object.class); + + //Argumenttypes of the method m2 + var paraTypesm2 = m2.getGenericParameterTypes(); + + //Typeparameters of the method m2 + var typeParaTypesm2 = m2.getTypeParameters(); + + //Typeparameters are extracted from the argumenttypes + //Conditions for the extracted typeparameters are set + + //paraTypes[0] = DZU + var fstArgm2 = Arrays.stream(typeParaTypesm2) + .filter(x -> x.equals(paraTypesm2[0])).findFirst().get(); + + //Bound of DZU has to be Object + assertEquals(Object.class, Arrays.stream(fstArgm2.getBounds()).findFirst().get()); + + //DZU has to be the return type of m + assertEquals(fstArgm2, m2.getGenericReturnType()); + } + @Test public void typedIdTest() throws Exception { From bca1bd622fe75da63a628f3a4d1d394ceef878db Mon Sep 17 00:00:00 2001 From: "pl@gohorb.ba-horb.de" Date: Tue, 9 Aug 2022 09:50:47 +0200 Subject: [PATCH 68/69] modified: ../bytecode/javFiles/SimpleCycle.jav Simple cycle aktiviert --- src/test/resources/bytecode/javFiles/SimpleCycle.jav | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/resources/bytecode/javFiles/SimpleCycle.jav b/src/test/resources/bytecode/javFiles/SimpleCycle.jav index 8e19ea41..2f45aa18 100644 --- a/src/test/resources/bytecode/javFiles/SimpleCycle.jav +++ b/src/test/resources/bytecode/javFiles/SimpleCycle.jav @@ -1,11 +1,11 @@ public class SimpleCycle { m(a,b,d){ - /* var g; + var g; var h; g = h; h = g; - + /* var y; var z; y=z; @@ -18,8 +18,8 @@ public class SimpleCycle { var f = d; b = x; var l = c; - a = l; */ - + a = l; + */ } } \ No newline at end of file From edf85dca7f227ba4f42f4677707ac0e3aa11a4eb Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Tue, 9 Aug 2022 12:59:23 +0200 Subject: [PATCH 69/69] Fix Tph4-6 --- .../target/generate/ASTToTargetAST.java | 15 ++++++++++++++- src/test/java/targetast/TestComplete.java | 6 ++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index bd122e55..61be1e8c 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -1,5 +1,6 @@ package de.dhbwstuttgart.target.generate; +import com.google.j2objc.annotations.LoopTranslation; import de.dhbwstuttgart.bytecode.funN.FunNGenerator; import de.dhbwstuttgart.core.JavaTXCompiler; import de.dhbwstuttgart.parser.NullToken; @@ -145,7 +146,7 @@ public class ASTToTargetAST { findTypeVariables(field.getType(), typeVariablesOfFields); } - findTypeVariables(method.getReturnType(), typeVariables); + //findTypeVariables(method.getReturnType(), typeVariables); for (var arg : method.getParameterList().getFormalparalist()) { findTypeVariables(arg.getType(), typeVariables); } @@ -155,6 +156,15 @@ public class ASTToTargetAST { public void visit(LocalVarDecl localVarDecl) { findTypeVariables(localVarDecl.getType(), typeVariables); } + + @Override + public void visit(MethodCall methodCall) { + super.visit(methodCall); + findTypeVariables(methodCall.getType(), typeVariables); + } + + @Override + public void visit(Assign assign) {} }); // Type variables with bounds that are also type variables of the method @@ -221,6 +231,7 @@ public class ASTToTargetAST { for (var pair2 : simplifiedConstraints) { if (!(pair2.right.equals(tph2) && pair2.left.equals(type))) continue; + if (tph.equals(tph2)) continue; var newPair = new PairTPHsmallerTPH(tph, tph2); newPairs.add(newPair); @@ -572,6 +583,8 @@ public class ASTToTargetAST { for (var i = 0; i < pars.size(); i++) { var type1 = convert(pars.get(i).getType()); var type2 = convert(arguments.get(i).getType()); + if (type2 instanceof TargetGenericType && type1 instanceof TargetGenericType) + return true; if (!type1.equals(type2)) return false; } diff --git a/src/test/java/targetast/TestComplete.java b/src/test/java/targetast/TestComplete.java index d0e07540..ab45a81f 100644 --- a/src/test/java/targetast/TestComplete.java +++ b/src/test/java/targetast/TestComplete.java @@ -349,6 +349,12 @@ public class TestComplete { var instance = classFiles.get("Tph3").getDeclaredConstructor().newInstance(); } + @Test + public void tph4Test() throws Exception { + var classFiles = generateClassFiles("Tph4.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("Tph4").getDeclaredConstructor().newInstance(); + } + @Test public void tph5Test() throws Exception { var classFiles = generateClassFiles("Tph5.jav", new ByteArrayClassLoader());