From 352531d68053275d6cfe22b6a02276b94b5c06ff Mon Sep 17 00:00:00 2001 From: Jochen Seyfried Date: Wed, 8 May 2024 10:40:44 +0200 Subject: [PATCH 01/10] Added SuperStatementExpression --- Source/TypeCheck/AbstractType.java | 2 +- .../StatementExpression/AssignStatementExpression.java | 2 +- .../StatementExpression/SuperStatementExpression.java | 10 ++++++++++ 3 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 Source/abstractSyntaxTree/StatementExpression/SuperStatementExpression.java diff --git a/Source/TypeCheck/AbstractType.java b/Source/TypeCheck/AbstractType.java index 068b139..ea2fd30 100644 --- a/Source/TypeCheck/AbstractType.java +++ b/Source/TypeCheck/AbstractType.java @@ -12,4 +12,4 @@ public abstract class AbstractType { public TypeCheckResult getTypeCheckResult() { return typeCheckResult; } -} +} \ No newline at end of file diff --git a/Source/abstractSyntaxTree/StatementExpression/AssignStatementExpression.java b/Source/abstractSyntaxTree/StatementExpression/AssignStatementExpression.java index 11c7fb1..5538467 100644 --- a/Source/abstractSyntaxTree/StatementExpression/AssignStatementExpression.java +++ b/Source/abstractSyntaxTree/StatementExpression/AssignStatementExpression.java @@ -38,7 +38,7 @@ public class AssignStatementExpression extends AbstractType implements IExpressi right.CodeGen(mv); if (left instanceof VarRefExpression varRef) { - //TODO: Implement the handling of a variable reference --> I need a lis of local variables + //TODO: Implement the handling of a variable reference --> I need a list of local variables // for that to determine if the variable is a local or field variable } else if (left instanceof InstVarExpression instVar) { mv.visitInsn(Opcodes.DUP_X1); diff --git a/Source/abstractSyntaxTree/StatementExpression/SuperStatementExpression.java b/Source/abstractSyntaxTree/StatementExpression/SuperStatementExpression.java new file mode 100644 index 0000000..61fa3cc --- /dev/null +++ b/Source/abstractSyntaxTree/StatementExpression/SuperStatementExpression.java @@ -0,0 +1,10 @@ +package abstractSyntaxTree.StatementExpression; + +import abstractSyntaxTree.Expression.IExpression; +import java.util.List; + +public class SuperStatementExpression extends MethodCallStatementExpression{ + public SuperStatementExpression(String methodName, List arguments) { + super(methodName, arguments); + } +} From 62c7f144bba6a80b61aeb0777404a758cc8c5117 Mon Sep 17 00:00:00 2001 From: Julian Murek Date: Wed, 8 May 2024 11:01:13 +0200 Subject: [PATCH 02/10] Added "src" directory to conform to Mavens project structure and added preliminary Tests and Testsuite. --- src/test/java/AST/TestRunner.java | 273 ++++ src/test/java/All/TestRunner.java | 1254 +++++++++++++++++ src/test/java/CodeGen/TestRunner.java | 356 +++++ src/test/java/Helper/MockGenerator.java | 965 +++++++++++++ src/test/java/Helper/ReflectLoader.java | 104 ++ src/test/java/Helper/Resources.java | 42 + src/test/java/TAST/TestRunner.java | 324 +++++ src/test/java/TestSuite.java | 10 + src/test/java/initialTest/initialTest.java | 12 + src/test/resources/Comments.java | 19 + .../resources/EmptyClassWithConstructor.java | 7 + src/test/resources/EmtpyClass.java | 1 + .../resources/FailTests/AssignWrongType.java | 11 + .../resources/FailTests/BoolAssignedInt.java | 9 + .../resources/FailTests/DivideByZero.java | 9 + .../FailTests/DuplicateFieldDeclaration.java | 6 + .../resources/FailTests/DuplicateMethod.java | 9 + .../resources/FailTests/FaultyForLoop.java | 11 + .../FailTests/MethodAccessTests.java | 18 + .../FailTests/MismatchingReturnType.java | 9 + src/test/resources/FailTests/ScopeTest.java | 23 + src/test/resources/IntegerWrapper.java | 20 + src/test/resources/Integration/Dijkstra.java | 366 +++++ src/test/resources/Integration/LOFOI.java | 23 + .../resources/Integration/LinkedList.java | 80 ++ src/test/resources/Integration/Stack.java | 55 + .../resources/Integration/StringList.java | 48 + src/test/resources/NotTested/BinaryTests.java | 31 + src/test/resources/NotTested/CharWrapper.java | 19 + src/test/resources/NotTested/ClassStress.java | 33 + src/test/resources/NotTested/Fib.java | 16 + .../NotTested/FibIntegerWrapper.java | 37 + src/test/resources/NotTested/IfTest.java | 30 + src/test/resources/NotTested/TwoClasses.java | 9 + .../NotTested/TwoClassesReferences.java | 27 + src/test/resources/NotTested/VoidMethod.java | 10 + .../resources/NotTested/VoidMethodReturn.java | 10 + src/test/resources/NotTested/WhileTest.java | 19 + src/test/resources/NotTested/ggt.java | 25 + src/test/resources/SimpleTests/AndVorOr.java | 13 + .../SimpleTests/AutoAccessModifierField.java | 7 + .../resources/SimpleTests/CharArgument.java | 15 + .../resources/SimpleTests/ClassFields.java | 9 + src/test/resources/SimpleTests/Comments.java | 21 + .../SimpleTests/ConditionalEvaluation.java | 16 + .../SimpleTests/ConstructorParams.java | 9 + .../SimpleTests/ConstructorThisDot.java | 11 + src/test/resources/SimpleTests/DecTest.java | 17 + src/test/resources/SimpleTests/DivMethod.java | 9 + .../resources/SimpleTests/EmptyClass.java | 3 + .../EmptyClassWithConstructor.java | 9 + .../SimpleTests/ExplicitNullAssign.java | 10 + .../SimpleTests/ExtendedNotTest.java | 18 + .../resources/SimpleTests/FieldWithExpr.java | 7 + src/test/resources/SimpleTests/ForTest.java | 11 + .../resources/SimpleTests/FourClasses.java | 63 + .../SimpleTests/FourClassesFieldAssign.java | 64 + .../SimpleTests/FourClassesSetter.java | 65 + .../resources/SimpleTests/GetterFunction.java | 15 + .../resources/SimpleTests/IfConstructor.java | 11 + .../SimpleTests/IfElseIfStatement.java | 15 + .../IfElseIfStatementWithOneReturn.java | 17 + .../IfElseIfStatementWithoutReturn.java | 17 + .../SimpleTests/IfElseStatement.java | 13 + .../resources/SimpleTests/IfStatement.java | 12 + .../SimpleTests/IncDecStressTest.java | 26 + src/test/resources/SimpleTests/IncTest.java | 17 + .../resources/SimpleTests/IntCompare.java | 9 + src/test/resources/SimpleTests/IntMethod.java | 9 + .../SimpleTests/KlammerVorPunkt.java | 9 + .../resources/SimpleTests/MainMethodTest.java | 9 + .../resources/SimpleTests/MethodCall.java | 15 + .../SimpleTests/MethodCallParams.java | 15 + .../SimpleTests/MethodCallStressTest.java | 34 + .../SimpleTests/MethodCallsInWhile.java | 23 + .../resources/SimpleTests/MiniLinkedList.java | 25 + .../resources/SimpleTests/MinusMethod.java | 9 + src/test/resources/SimpleTests/ModMethod.java | 7 + src/test/resources/SimpleTests/MulMethod.java | 9 + .../resources/SimpleTests/MultClasses.java | 9 + .../SimpleTests/MultClassesReference.java | 26 + .../MultipleClassesMethodCalls.java | 22 + .../SimpleTests/MultipleClassesStress.java | 24 + src/test/resources/SimpleTests/NotMethod.java | 7 + .../SimpleTests/OperatorStacking.java | 21 + .../resources/SimpleTests/OperatorTest.java | 86 ++ .../resources/SimpleTests/OverridingTest.java | 32 + .../SimpleTests/OverridingTestNull.java | 35 + .../OverridingTestNullMultiple.java | 37 + .../resources/SimpleTests/ParamMethod.java | 7 + .../resources/SimpleTests/PlusMethod.java | 9 + .../resources/SimpleTests/PunktVorStrich.java | 13 + .../SimpleTests/RealConstructor.java | 11 + .../resources/SimpleTests/RealMethod.java | 7 + src/test/resources/SimpleTests/RealWhile.java | 14 + .../resources/SimpleTests/SelfReference.java | 20 + .../SimpleTests/SystemOutPrintln.java | 9 + .../SimpleTests/SystemOutPrintlnString.java | 9 + .../SimpleTests/ThisDotMethodCall.java | 15 + .../SimpleTests/ValueAdapterTests.java | 29 + .../resources/SimpleTests/VoidMethod.java | 7 + .../resources/SimpleTests/VoidReturn.java | 9 + src/test/resources/SimpleTests/WhileTest.java | 13 + src/test/resources/basicClasses/emptyClass | 1 + .../resources/basicClasses/publicEmptyClass | 0 105 files changed, 5495 insertions(+) create mode 100644 src/test/java/AST/TestRunner.java create mode 100644 src/test/java/All/TestRunner.java create mode 100644 src/test/java/CodeGen/TestRunner.java create mode 100644 src/test/java/Helper/MockGenerator.java create mode 100644 src/test/java/Helper/ReflectLoader.java create mode 100644 src/test/java/Helper/Resources.java create mode 100644 src/test/java/TAST/TestRunner.java create mode 100644 src/test/java/TestSuite.java create mode 100644 src/test/java/initialTest/initialTest.java create mode 100644 src/test/resources/Comments.java create mode 100644 src/test/resources/EmptyClassWithConstructor.java create mode 100644 src/test/resources/EmtpyClass.java create mode 100644 src/test/resources/FailTests/AssignWrongType.java create mode 100644 src/test/resources/FailTests/BoolAssignedInt.java create mode 100644 src/test/resources/FailTests/DivideByZero.java create mode 100644 src/test/resources/FailTests/DuplicateFieldDeclaration.java create mode 100644 src/test/resources/FailTests/DuplicateMethod.java create mode 100644 src/test/resources/FailTests/FaultyForLoop.java create mode 100644 src/test/resources/FailTests/MethodAccessTests.java create mode 100644 src/test/resources/FailTests/MismatchingReturnType.java create mode 100644 src/test/resources/FailTests/ScopeTest.java create mode 100644 src/test/resources/IntegerWrapper.java create mode 100644 src/test/resources/Integration/Dijkstra.java create mode 100644 src/test/resources/Integration/LOFOI.java create mode 100644 src/test/resources/Integration/LinkedList.java create mode 100644 src/test/resources/Integration/Stack.java create mode 100644 src/test/resources/Integration/StringList.java create mode 100644 src/test/resources/NotTested/BinaryTests.java create mode 100644 src/test/resources/NotTested/CharWrapper.java create mode 100644 src/test/resources/NotTested/ClassStress.java create mode 100644 src/test/resources/NotTested/Fib.java create mode 100644 src/test/resources/NotTested/FibIntegerWrapper.java create mode 100644 src/test/resources/NotTested/IfTest.java create mode 100644 src/test/resources/NotTested/TwoClasses.java create mode 100644 src/test/resources/NotTested/TwoClassesReferences.java create mode 100644 src/test/resources/NotTested/VoidMethod.java create mode 100644 src/test/resources/NotTested/VoidMethodReturn.java create mode 100644 src/test/resources/NotTested/WhileTest.java create mode 100644 src/test/resources/NotTested/ggt.java create mode 100644 src/test/resources/SimpleTests/AndVorOr.java create mode 100644 src/test/resources/SimpleTests/AutoAccessModifierField.java create mode 100644 src/test/resources/SimpleTests/CharArgument.java create mode 100644 src/test/resources/SimpleTests/ClassFields.java create mode 100644 src/test/resources/SimpleTests/Comments.java create mode 100644 src/test/resources/SimpleTests/ConditionalEvaluation.java create mode 100644 src/test/resources/SimpleTests/ConstructorParams.java create mode 100644 src/test/resources/SimpleTests/ConstructorThisDot.java create mode 100644 src/test/resources/SimpleTests/DecTest.java create mode 100644 src/test/resources/SimpleTests/DivMethod.java create mode 100644 src/test/resources/SimpleTests/EmptyClass.java create mode 100644 src/test/resources/SimpleTests/EmptyClassWithConstructor.java create mode 100644 src/test/resources/SimpleTests/ExplicitNullAssign.java create mode 100644 src/test/resources/SimpleTests/ExtendedNotTest.java create mode 100644 src/test/resources/SimpleTests/FieldWithExpr.java create mode 100644 src/test/resources/SimpleTests/ForTest.java create mode 100644 src/test/resources/SimpleTests/FourClasses.java create mode 100644 src/test/resources/SimpleTests/FourClassesFieldAssign.java create mode 100644 src/test/resources/SimpleTests/FourClassesSetter.java create mode 100644 src/test/resources/SimpleTests/GetterFunction.java create mode 100644 src/test/resources/SimpleTests/IfConstructor.java create mode 100644 src/test/resources/SimpleTests/IfElseIfStatement.java create mode 100644 src/test/resources/SimpleTests/IfElseIfStatementWithOneReturn.java create mode 100644 src/test/resources/SimpleTests/IfElseIfStatementWithoutReturn.java create mode 100644 src/test/resources/SimpleTests/IfElseStatement.java create mode 100644 src/test/resources/SimpleTests/IfStatement.java create mode 100644 src/test/resources/SimpleTests/IncDecStressTest.java create mode 100644 src/test/resources/SimpleTests/IncTest.java create mode 100644 src/test/resources/SimpleTests/IntCompare.java create mode 100644 src/test/resources/SimpleTests/IntMethod.java create mode 100644 src/test/resources/SimpleTests/KlammerVorPunkt.java create mode 100644 src/test/resources/SimpleTests/MainMethodTest.java create mode 100644 src/test/resources/SimpleTests/MethodCall.java create mode 100644 src/test/resources/SimpleTests/MethodCallParams.java create mode 100644 src/test/resources/SimpleTests/MethodCallStressTest.java create mode 100644 src/test/resources/SimpleTests/MethodCallsInWhile.java create mode 100644 src/test/resources/SimpleTests/MiniLinkedList.java create mode 100644 src/test/resources/SimpleTests/MinusMethod.java create mode 100644 src/test/resources/SimpleTests/ModMethod.java create mode 100644 src/test/resources/SimpleTests/MulMethod.java create mode 100644 src/test/resources/SimpleTests/MultClasses.java create mode 100644 src/test/resources/SimpleTests/MultClassesReference.java create mode 100644 src/test/resources/SimpleTests/MultipleClassesMethodCalls.java create mode 100644 src/test/resources/SimpleTests/MultipleClassesStress.java create mode 100644 src/test/resources/SimpleTests/NotMethod.java create mode 100644 src/test/resources/SimpleTests/OperatorStacking.java create mode 100644 src/test/resources/SimpleTests/OperatorTest.java create mode 100644 src/test/resources/SimpleTests/OverridingTest.java create mode 100644 src/test/resources/SimpleTests/OverridingTestNull.java create mode 100644 src/test/resources/SimpleTests/OverridingTestNullMultiple.java create mode 100644 src/test/resources/SimpleTests/ParamMethod.java create mode 100644 src/test/resources/SimpleTests/PlusMethod.java create mode 100644 src/test/resources/SimpleTests/PunktVorStrich.java create mode 100644 src/test/resources/SimpleTests/RealConstructor.java create mode 100644 src/test/resources/SimpleTests/RealMethod.java create mode 100644 src/test/resources/SimpleTests/RealWhile.java create mode 100644 src/test/resources/SimpleTests/SelfReference.java create mode 100644 src/test/resources/SimpleTests/SystemOutPrintln.java create mode 100644 src/test/resources/SimpleTests/SystemOutPrintlnString.java create mode 100644 src/test/resources/SimpleTests/ThisDotMethodCall.java create mode 100644 src/test/resources/SimpleTests/ValueAdapterTests.java create mode 100644 src/test/resources/SimpleTests/VoidMethod.java create mode 100644 src/test/resources/SimpleTests/VoidReturn.java create mode 100644 src/test/resources/SimpleTests/WhileTest.java create mode 100644 src/test/resources/basicClasses/emptyClass create mode 100644 src/test/resources/basicClasses/publicEmptyClass diff --git a/src/test/java/AST/TestRunner.java b/src/test/java/AST/TestRunner.java new file mode 100644 index 0000000..2b36f3f --- /dev/null +++ b/src/test/java/AST/TestRunner.java @@ -0,0 +1,273 @@ +package AST; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.InputStream; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import Helper.MockGenerator; +import Helper.Resources; +import common.AccessModifier; +import common.BaseType; +import common.Compiler; +import common.Primitives; +import common.PrintableVector; +import syntaxtree.structure.ClassDecl; +import syntaxtree.structure.ConstructorDecl; +import syntaxtree.structure.FieldDecl; +import syntaxtree.structure.Program; + +@DisplayName("Abstract Syntax Tree Generation") +public class TestRunner { + + @Test + @DisplayName("Control Test") + void controlTest() { + var first = MockGenerator.getConstructorParameterAst(); + var second = MockGenerator.getConstructorParameterAst(); + + assertEquals(first, second); + } + + @Test + @DisplayName("Empty Class") + void emptyClass() { + InputStream file = Resources.getFileAsStream("SimpleTests/EmptyClass.java"); + Program ast = Compiler.getFactory().getAstAdapter().getAst(file); + PrintableVector constructors = new PrintableVector<>(); + constructors.add(new ConstructorDecl()); + ClassDecl classDecl = new ClassDecl("EmptyClass", new PrintableVector<>(), constructors, + new PrintableVector<>()); + PrintableVector classDecls = new PrintableVector<>(); + classDecls.add(classDecl); + var generatedAst = new Program(classDecls); + + assertEquals(generatedAst, ast); + + } + + @Test + @DisplayName("EmptyClassWithConstructor") + void emptyClassWithConstructor() { + InputStream file = Resources.getFileAsStream("SimpleTests/EmptyClassWithConstructor.java"); + Program generatedAst = Compiler.getFactory().getAstAdapter().getAst(file); + + PrintableVector constructors = new PrintableVector<>(); + constructors.add(new ConstructorDecl()); + ClassDecl classDecl = new ClassDecl("EmptyClassWithConstructor", new PrintableVector<>(), constructors, + new PrintableVector<>()); + PrintableVector classDecls = new PrintableVector<>(); + classDecls.add(classDecl); + var ast = new Program(classDecls); + assertEquals(ast, generatedAst); + + } + + @Test + @DisplayName("ClassFields") + void classFields() { + Program generatedAst = Resources.getProgram("SimpleTests/ClassFields.java"); + + Program expectedAst = MockGenerator.getClassFieldsAst(); + + assertEquals(expectedAst, generatedAst); + } + + @Test + @DisplayName("ClassField without AccessModifier") + void classFieldWithoutAccessModifier() { + Program generatedAst = Resources.getProgram("SimpleTests/AutoAccessModifierField.java"); + + Program expectedAst = MockGenerator.getAutoClassFieldAst(); + + assertEquals(expectedAst, generatedAst); + } + + @Test + @DisplayName("Comments") + void commentTest() { + InputStream file = Resources.getFileAsStream("SimpleTests/Comments.java"); + Program generatedAst = Compiler.getFactory().getAstAdapter().getAst(file); + + PrintableVector constructors = new PrintableVector<>(); + constructors.add(new ConstructorDecl()); + PrintableVector fields = new PrintableVector<>(); + + FieldDecl lorem = new FieldDecl("lorem", AccessModifier.PRIVATE); + lorem.setType(new BaseType(Primitives.INT)); + fields.add(lorem); + + FieldDecl ipsum = new FieldDecl("ipsum", AccessModifier.PRIVATE); + ipsum.setType(new BaseType(Primitives.BOOL)); + fields.add(ipsum); + + ClassDecl classDecl = new ClassDecl("Comments", fields, constructors, new PrintableVector<>()); + PrintableVector classDecls = new PrintableVector<>(); + classDecls.add(classDecl); + var expectedAst = new Program(classDecls); + assertEquals(expectedAst, generatedAst); + + } + + @Test + @DisplayName("Constructor With Parameters") + void constructorWithParameters() { + Program generatedAst = Resources.getProgram("SimpleTests/ConstructorParams.java"); + Program expectedAst = MockGenerator.getConstructorParameterAst(); + + assertEquals(expectedAst, generatedAst); + } + + @Test + @DisplayName("Constructor With this. assign body") + void constructorWithThisAssignBody() { + Program generatedAst = Resources.getProgram("SimpleTests/ConstructorThisDot.java"); + Program expectedAst = MockGenerator.getConstructorThisDotAst(); + + assertEquals(expectedAst, generatedAst); + } + + @Test + @DisplayName("VoidMethod") + void voidMethod() { + Program generatedAst = Resources.getProgram("SimpleTests/VoidMethod.java"); + Program expectedAst = MockGenerator.getVoidMethodAst(); + + assertEquals(expectedAst, generatedAst); + } + + @Test + @DisplayName("RealConstructor") + void realConstructor() { + Program generatedAst = Resources.getProgram("SimpleTests/RealConstructor.java"); + Program expectedAst = MockGenerator.getRealConstructorAst(); + + assertEquals(expectedAst, generatedAst); + } + + @Test + @DisplayName("MethodCall") + void methodCall() { + Program generatedAst = Resources.getProgram("SimpleTests/MethodCall.java"); + Program expectedAst = MockGenerator.getMethodCallAst(); + + assertEquals(expectedAst, generatedAst); + } + + @Test + @DisplayName("ThisDotMethodCall") + void thisDotMethodCall() { + Program generatedAst = Resources.getProgram("SimpleTests/ThisDotMethodCall.java"); + Program expectedAst = MockGenerator.getThisDotMethodCallAst(); + + assertEquals(expectedAst, generatedAst); + } + + @Test + @DisplayName("MethodCallWithParameters") + void methodCallWithParameters() { + Program generatedAst = Resources.getProgram("SimpleTests/MethodCallParams.java"); + Program expectedAst = MockGenerator.getMethodCallWithParameterAst(); + + assertEquals(expectedAst, generatedAst); + } + + @Test + @DisplayName("GetterFunction") + void getterFunction() { + Program generatedAst = Resources.getProgram("SimpleTests/GetterFunction.java"); + Program expectedAst = MockGenerator.getGetterFunctionAst(); + + System.out.println(generatedAst); + + assertEquals(expectedAst, generatedAst); + } + + @Test + @DisplayName("CharArgument") + void charArgument() { + Program generatedAst = Resources.getProgram("SimpleTests/CharArgument.java"); + Program expectedAst = MockGenerator.getCharArgumentAst(); + + assertEquals(expectedAst, generatedAst); + } + + @Test + @DisplayName("ExplicitNullAssign") + void explicitNullAssign() { + Program generatedAst = Resources.getProgram("SimpleTests/ExplicitNullAssign.java"); + Program expectedAst = MockGenerator.getExplicitNullAssignAst(); + + assertEquals(expectedAst, generatedAst); + } + + @Test + @DisplayName("SelfReference") + void selfReference() { + Program generatedAst = Resources.getProgram("SimpleTests/SelfReference.java"); + Program expectedAst = MockGenerator.getSelfReferenceAst(); + + assertEquals(expectedAst, generatedAst); + } + + @Test + @DisplayName("ValueAdapterTests") + void valueAdapterTest() { + Program generatedAst = Resources.getProgram("SimpleTests/ValueAdapterTests.java"); + Program expectedAst = MockGenerator.getValueAdapterTestAst(); + + assertEquals(expectedAst, generatedAst); + } + + @Test + @DisplayName("System.out.println Test") + void systemOutPrintlnTest() { + Program generatedAst = Resources.getProgram("SimpleTests/SystemOutPrintln.java"); + Program expectedAst = MockGenerator.getSystemOutPrintlnAst(); + + assertEquals(expectedAst, generatedAst); + } + + @Test + @DisplayName("System.out.print-String Test") + void systemOutPrintStringTest() { + Program generatedAst = Resources.getProgram("SimpleTests/SystemOutPrintlnString.java"); + Program expectedAst = MockGenerator.getSystemOutPrintStringAst(); + assertEquals(expectedAst, generatedAst); + } + + @Test + @DisplayName("MainMethodTest") + void mainMethodTest() { + Program generatedAst = Resources.getProgram("SimpleTests/MainMethodTest.java"); + Program expectedAst = MockGenerator.getMainMethodTestAst(); + assertEquals(expectedAst, generatedAst); + } + + @Test + @DisplayName("ForTest") + void forTest() { + Program generatedAst = Resources.getProgram("SimpleTests/ForTest.java"); + Program expectedAst = MockGenerator.getForTestAst(); + assertEquals(expectedAst, generatedAst); + } + + @Test + @DisplayName("IncTest") + void incTest() { + Program generatedAst = Resources.getProgram("SimpleTests/IncTest.java"); + Program expectedAst = MockGenerator.getIncTestAst(); + assertEquals(expectedAst, generatedAst); + } + + @Test + @DisplayName("DecTest") + void decTest() { + Program generatedAst = Resources.getProgram("SimpleTests/DecTest.java"); + Program expectedAst = MockGenerator.getDecTestAst(); + assertEquals(expectedAst, generatedAst); + } + +} diff --git a/src/test/java/All/TestRunner.java b/src/test/java/All/TestRunner.java new file mode 100644 index 0000000..8433ea5 --- /dev/null +++ b/src/test/java/All/TestRunner.java @@ -0,0 +1,1254 @@ +package All; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.PrintStream; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import Helper.ReflectLoader; +import Helper.Resources; +import common.Compiler; +import semantic.exceptions.SemanticError; +import syntaxtree.structure.Program; + +@DisplayName("All") +public class TestRunner { + + private final ByteArrayOutputStream outContent = new ByteArrayOutputStream(); + private final ByteArrayOutputStream errContent = new ByteArrayOutputStream(); + private final PrintStream originalOut = System.out; + private final PrintStream originalErr = System.err; + + /** + * @throws Exception + */ + @Test + @DisplayName("Empty Class") + void emptyClass() throws Exception { + InputStream file = Resources.getFileAsStream("SimpleTests/EmptyClass.java"); + Program ast = Compiler.getFactory().getAstAdapter().getAst(file); + Program tast = Compiler.getFactory().getTastAdapter().getTast(ast); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("EmptyClass"); + + Object o = c.getDeclaredConstructor().newInstance(); + assertEquals("EmptyClass", o.getClass().getName()); + } + + /** + * @throws Exception + */ + @Test + @DisplayName("EmptyClassWithConstructor") + void emptyClassWithConstructor() throws Exception { + InputStream file = Resources.getFileAsStream("SimpleTests/EmptyClassWithConstructor.java"); + Program ast = Compiler.getFactory().getAstAdapter().getAst(file); + Program tast = Compiler.getFactory().getTastAdapter().getTast(ast); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("EmptyClassWithConstructor"); + + Object o = c.getDeclaredConstructor().newInstance(); + assertEquals("EmptyClassWithConstructor", o.getClass().getName()); + } + + @Test + @DisplayName("ClassFields - privateAccess") + void classFieldsPrivate() { + Program program = Resources.getProgram("SimpleTests/ClassFields.java"); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + try { + var autoAccess = loader.getField("ClassFields", "privateAccess"); + + assertEquals(Modifier.PRIVATE, autoAccess.getModifiers()); + } catch (Exception e) { + fail(e.getLocalizedMessage()); + } + } + + @Test + @DisplayName("ClassFields - publicAccess") + void classFieldsPublic() { + Program program = Resources.getProgram("SimpleTests/ClassFields.java"); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + try { + var publicAccess = loader.getField("ClassFields", "publicAccess"); + assertEquals(Modifier.PUBLIC, publicAccess.getModifiers()); + } catch (Exception e) { + fail(e.getLocalizedMessage()); + } + } + + @Test + @DisplayName("ClassFields - protectedAccess") + void classFieldsProtected() { + Program program = Resources.getProgram("SimpleTests/ClassFields.java"); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + try { + var protectedAccess = loader.getField("ClassFields", "protectedAccess"); + assertEquals(Modifier.PROTECTED, protectedAccess.getModifiers()); + } catch (Exception e) { + fail(e.getLocalizedMessage()); + } + } + + /** + * @throws Exception + */ + @Test + @DisplayName("Comments") + void comments() throws Exception { + InputStream file = Resources.getFileAsStream("SimpleTests/Comments.java"); + Program ast = Compiler.getFactory().getAstAdapter().getAst(file); + Program tast = Compiler.getFactory().getTastAdapter().getTast(ast); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("Comments"); + Field lorem = loader.getField(c.getName(), "lorem"); + assertEquals("int", lorem.getType().toString()); + } + + @Test + @DisplayName("Constructor With Parameters") + void constructorWithParameters() { + Program program = Resources.getProgram("SimpleTests/ConstructorParams.java"); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("ConstructorParams"); + try { + Object o = c.getDeclaredConstructor(int.class).newInstance(1); + assertEquals("ConstructorParams", o.getClass().getName()); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("Constructor with this. assign body") + void constructorWithThisAssignBody() { + Program program = Resources.getProgram("SimpleTests/ConstructorThisDot.java"); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("ConstructorThisDot"); + try { + Object o = c.getDeclaredConstructor().newInstance(); + var i = loader.getField("ConstructorThisDot", "i"); + var ivalue = i.get(o); + assertEquals(5, ivalue); + } catch (Exception e) { + fail(e.getLocalizedMessage()); + } + } + + @Test + @DisplayName("VoidMethod") + void voidMethod() { + Program program = Resources.getProgram("SimpleTests/VoidMethod.java"); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("VoidMethod"); + try { + Object o = c.getDeclaredConstructor().newInstance(); + var voidMethod = loader.getMethod("VoidMethod", "foo"); + voidMethod.invoke(o); + assertEquals("foo", voidMethod.getName()); + } catch (Exception e) { + + fail(e.getLocalizedMessage()); + } + } + + @Test + @DisplayName("RealConstructor - params&this-assigns") + void realConstructor() { + Program program = Resources.getProgram("SimpleTests/RealConstructor.java"); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("RealConstructor"); + try { + int randomI = 2; + Object o = c.getDeclaredConstructor(int.class).newInstance(randomI); + var i = loader.getField("RealConstructor", "i"); + var ivalue = i.get(o); + assertEquals(randomI, ivalue); + } catch (Exception e) { + fail(e.getLocalizedMessage()); + } + } + + @Test + @DisplayName("MethodCall") + void methodCall() { + ReflectLoader loader = new ReflectLoader("SimpleTests/MethodCall.java"); + Class c = loader.findClass("MethodCall"); + Object o = null; + int value = 1; + try { + o = c.getDeclaredConstructor().newInstance(); + var i = loader.getField("MethodCall", "i"); + int ivalue = (int) i.get(o); + assertEquals(value, ivalue); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("MethodCallWithParameters") + void methodCallParams() { + ReflectLoader loader = new ReflectLoader("SimpleTests/MethodCallParams.java"); + Class c = loader.findClass("MethodCallParams"); + Object o = null; + int value = 5; + try { + o = c.getDeclaredConstructor(int.class).newInstance(value); + var i = loader.getField("MethodCallParams", "i"); + int ivalue = (int) i.get(o); + assertEquals(value, ivalue); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("CharArgument") + void charArgument() { + ReflectLoader loader = new ReflectLoader("SimpleTests/CharArgument.java"); + Class clazz = loader.findClass("CharArgument"); + Object o = null; + char value = 'a'; + try { + o = clazz.getDeclaredConstructor().newInstance(); + var cField = loader.getField("CharArgument", "c"); + char ivalue = (char) cField.get(o); + assertEquals(value, ivalue); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("MultClasses") + void multClasses() { + Program program = Resources.getProgram("SimpleTests/MultClassesReference.java"); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + System.out.println(program); + System.out.println(tast); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + if (bc.size() != 2) { + fail("Bytecode map should hold 2 Classes but got " + bc.size()); + return; + } + var loader = new ReflectLoader(bc); + int value = 5; + try { + var clazz1 = loader.findClass("MultClassesReference2"); + Object multclassref2 = null; + multclassref2 = clazz1.getDeclaredConstructor(int.class).newInstance(value); + var testMethod = loader.getMethod("MultClassesReference2", "test"); + var ivalue = testMethod.invoke(multclassref2); + assertEquals(value, ivalue); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("IfStatement") + void ifStatement() { + Program program = Resources.getProgram("SimpleTests/IfStatement.java"); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class clazz = loader.findClass("IfStatement"); + Object o = null; + int value = -1; + int result; + if (value == 1) { + result = 10; + } else { + result = 100; + } + try { + o = clazz.getDeclaredConstructor().newInstance(); + var foo = loader.getMethod("IfStatement", "foo", int.class); + var ivalue = (int) foo.invoke(o, value); + assertEquals(result, ivalue); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("IfElseStatement") + void ifElseStatement() { + Program program = Resources.getProgram("SimpleTests/IfElseStatement.java"); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class clazz = loader.findClass("IfElseStatement"); + Object o = null; + int value = -1; + int result; + if (value == 1) { + result = 10; + } else { + result = 100; + } + try { + o = clazz.getDeclaredConstructor().newInstance(); + var foo = loader.getMethod("IfElseStatement", "foo", int.class); + var ivalue = (int) foo.invoke(o, value); + assertEquals(result, ivalue); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("IfElseIfStatement") + void ifElseIfStatement() { + Program program = Resources.getProgram("SimpleTests/IfElseIfStatement.java"); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + System.out.println(tast); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class clazz = loader.findClass("IfElseIfStatement"); + Object o = null; + int value = 3; + int result; + if (value == 1) { + result = 10; + } else if (value == 2) { + result = 40000; + } else { + result = 42000; + } + try { + o = clazz.getDeclaredConstructor().newInstance(); + var foo = loader.getMethod("IfElseIfStatement", "foo", int.class); + var ivalue = (int) foo.invoke(o, value); + assertEquals(result, ivalue); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("IfElseIfStatementWithoutReturn") + void ifElseIfStatementWithoutReturn() { + Program program = Resources.getProgram("SimpleTests/IfElseIfStatementWithoutReturn.java"); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + System.out.println(tast); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class clazz = loader.findClass("IfElseIfStatementWithoutReturn"); + Object o = null; + int value = 3; + int result; + if (value == 1) { + result = 10; + } else if (value == 2) { + result = 20; + } else { + result = 30; + } + try { + o = clazz.getDeclaredConstructor().newInstance(); + var foo = loader.getMethod("IfElseIfStatementWithoutReturn", "foo", int.class); + var ivalue = (int) foo.invoke(o, value); + assertEquals(result, ivalue); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("IfElseIfStatementWithOneReturn") + void ifElseIfStatementWithOneReturn() { + Program program = Resources.getProgram("SimpleTests/IfElseIfStatementWithOneReturn.java"); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + System.out.println(tast); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class clazz = loader.findClass("IfElseIfStatementWithOneReturn"); + Object o = null; + int value = 3; + int result; + if (value == 1) { + result = 10; + } else if (value == 2) { + result = 20; + } else { + result = 30; + } + try { + o = clazz.getDeclaredConstructor().newInstance(); + var foo = loader.getMethod("IfElseIfStatementWithOneReturn", "foo", int.class); + var ivalue = (int) foo.invoke(o, value); + assertEquals(result, ivalue); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("FourClasses") + void fourClasses() { + Program program = Resources.getProgram("SimpleTests/FourClasses.java"); + + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + System.out.println(tast); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class clazz = loader.findClass("FourClasses"); + Object o = null; + int result = 10; + try { + o = clazz.getDeclaredConstructor().newInstance(); + var main = loader.getMethod("FourClasses", "main", int.class); + var ivalue = (int) main.invoke(o, result); + assertEquals(result * 2, ivalue); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("FourClassesFieldAssign") + void fourClassesFieldAssign() { + Program program = Resources.getProgram("SimpleTests/FourClassesFieldAssign.java"); + + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + System.out.println(tast); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class clazz = loader.findClass("FourClassesFieldAssign"); + Object o = null; + int result = 10; + try { + o = clazz.getDeclaredConstructor().newInstance(); + var main = loader.getMethod("FourClassesFieldAssign", "fieldAssign", int.class); + var ivalue = (int) main.invoke(o, result); + assertEquals(result, ivalue); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("FourClassesSetter") + void fourClassesSetter() { + Program program = Resources.getProgram("SimpleTests/FourClassesSetter.java"); + + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + System.out.println(tast); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class clazz = loader.findClass("FourClassesSetter"); + Object o = null; + int result = 10; + try { + o = clazz.getDeclaredConstructor().newInstance(); + var main = loader.getMethod("FourClassesSetter", "setFieldTest", int.class); + var ivalue = (int) main.invoke(o, result); + assertEquals(result, ivalue); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("MinusMethod") + void minusMethod() { + Program program = Resources.getProgram("SimpleTests/MinusMethod.java"); + + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class clazz = loader.findClass("MinusMethod"); + Object o = null; + int result = 10; + try { + o = clazz.getDeclaredConstructor().newInstance(); + var foo = loader.getMethod("MinusMethod", "foo", int.class); + var ivalue = (int) foo.invoke(o, result); + assertEquals(0, ivalue); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("PlusMethod") + void plusMethod() { + Program program = Resources.getProgram("SimpleTests/PlusMethod.java"); + + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class clazz = loader.findClass("PlusMethod"); + Object o = null; + int result = 10; + try { + o = clazz.getDeclaredConstructor().newInstance(); + var foo = loader.getMethod("PlusMethod", "foo", int.class); + var ivalue = (int) foo.invoke(o, result); + assertEquals(20, ivalue); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("MulMethod") + void mulMethod() { + Program program = Resources.getProgram("SimpleTests/MulMethod.java"); + + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class clazz = loader.findClass("MulMethod"); + Object o = null; + int result = 10; + try { + o = clazz.getDeclaredConstructor().newInstance(); + var foo = loader.getMethod("MulMethod", "foo", int.class); + var ivalue = (int) foo.invoke(o, result); + assertEquals(100, ivalue); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("DivMethod") + void divMethod() { + Program program = Resources.getProgram("SimpleTests/DivMethod.java"); + + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class clazz = loader.findClass("DivMethod"); + Object o = null; + int result = 10; + try { + o = clazz.getDeclaredConstructor().newInstance(); + var foo = loader.getMethod("DivMethod", "foo", int.class); + var ivalue = (int) foo.invoke(o, result); + assertEquals(1, ivalue); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("PunktVorStrich") + void punktVorStrich() { + Program program = Resources.getProgram("SimpleTests/PunktVorStrich.java"); + + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class clazz = loader.findClass("PunktVorStrich"); + Object o = null; + int a = 10; + int b = 20; + int c = 30; + int result = a + b * c; + int result2 = a * b + c; + try { + o = clazz.getDeclaredConstructor().newInstance(); + var foo = loader.getMethod("PunktVorStrich", "foo", int.class, int.class, int.class); + var bar = loader.getMethod("PunktVorStrich", "bar", int.class, int.class, int.class); + var ivalue = (int) foo.invoke(o, a, b, c); + assertEquals(result2, ivalue); + var ivalue2 = (int) bar.invoke(o, a, b, c); + assertEquals(result, ivalue2); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("AndVorOr") + void andVorOr() { + Program program = Resources.getProgram("SimpleTests/AndVorOr.java"); + + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class clazz = loader.findClass("AndVorOr"); + Object o = null; + boolean a = true; + boolean b = true; + boolean c = false; + boolean result = a || b && c; + boolean result2 = a || b && c || b && c; + try { + o = clazz.getDeclaredConstructor().newInstance(); + var foo = loader.getMethod("AndVorOr", "foo", boolean.class, boolean.class, boolean.class); + var bar = loader.getMethod("AndVorOr", "foo", boolean.class, boolean.class, boolean.class); + var ivalue = (boolean) foo.invoke(o, a, b, c); + assertEquals(result, ivalue); + ivalue = (boolean) bar.invoke(o, a, b, c); + assertEquals(result2, ivalue); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("KlammerVorPunkt") + void klammerVorPunkt() { + Program program = Resources.getProgram("SimpleTests/KlammerVorPunkt.java"); + + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class clazz = loader.findClass("KlammerVorPunkt"); + Object o = null; + int a = 10; + int b = 20; + int c = 30; + int result = a * (b + c); + try { + o = clazz.getDeclaredConstructor().newInstance(); + var foo = loader.getMethod("KlammerVorPunkt", "foo", int.class, int.class, int.class); + var ivalue = (int) foo.invoke(o, a, b, c); + assertEquals(result, ivalue); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("ModMethod") + void modMethod() { + Program program = Resources.getProgram("SimpleTests/ModMethod.java"); + + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class clazz = loader.findClass("ModMethod"); + Object o = null; + int a = 4; + int b = 260; + int result = b % a; + try { + o = clazz.getDeclaredConstructor().newInstance(); + var foo = loader.getMethod("ModMethod", "foo", int.class, int.class); + var ivalue = (int) foo.invoke(o, b, a); + assertEquals(result, ivalue); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("NotMethod") + void notMethod() { + Program program = Resources.getProgram("SimpleTests/NotMethod.java"); + + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class clazz = loader.findClass("NotMethod"); + Object o = null; + boolean a = true; + boolean result = !a; + try { + o = clazz.getDeclaredConstructor().newInstance(); + var foo = loader.getMethod("NotMethod", "foo", boolean.class); + var ivalue = (boolean) foo.invoke(o, a); + assertEquals(result, ivalue); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("OperatorFullTest") + void operatorFullTest() { + Program program = Resources.getProgram("SimpleTests/OperatorTest.java"); + + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + System.out.println(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class clazz = loader.findClass("OperatorTest"); + Object o = null; + int x = 452; + int y = 87; + + boolean a = true; + boolean b = false; + try { + o = clazz.getDeclaredConstructor().newInstance(); + var assign = loader.getMethod("OperatorTest", "assign", int.class).invoke(o, x); + assertEquals(x, assign); + var plus = loader.getMethod("OperatorTest", "plus", int.class, int.class).invoke(o, x, y); + assertEquals(x + y, plus); + var minus = loader.getMethod("OperatorTest", "minus", int.class, int.class).invoke(o, x, y); + assertEquals(x - y, minus); + var mult = loader.getMethod("OperatorTest", "mult", int.class, int.class).invoke(o, x, y); + assertEquals(x * y, mult); + var div = loader.getMethod("OperatorTest", "div", int.class, int.class).invoke(o, x, y); + assertEquals(x / y, div); + var mod = loader.getMethod("OperatorTest", "mod", int.class, int.class).invoke(o, x, y); + assertEquals(x % y, mod); + var gt = loader.getMethod("OperatorTest", "gt", int.class, int.class).invoke(o, x, y); + assertEquals(x > y, gt); + var lt = loader.getMethod("OperatorTest", "lt", int.class, int.class).invoke(o, x, y); + assertEquals(x < y, lt); + var gte = loader.getMethod("OperatorTest", "gte", int.class, int.class).invoke(o, x, y); + assertEquals(x >= y, gte); + var lte = loader.getMethod("OperatorTest", "lte", int.class, int.class).invoke(o, x, y); + assertEquals(x <= y, lte); + var eq = loader.getMethod("OperatorTest", "eq", int.class, int.class).invoke(o, x, y); + assertEquals(x == y, eq); + var neq = loader.getMethod("OperatorTest", "neq", int.class, int.class).invoke(o, x, y); + assertEquals(x != y, neq); + + var beq = loader.getMethod("OperatorTest", "beq", boolean.class, boolean.class).invoke(o, true, true); + assertEquals(true, beq); + var beq2 = loader.getMethod("OperatorTest", "beq", boolean.class, boolean.class).invoke(o, true, false); + assertEquals(false, beq2); + var beq3 = loader.getMethod("OperatorTest", "beq", boolean.class, boolean.class).invoke(o, false, true); + assertEquals(false, beq3); + var beq4 = loader.getMethod("OperatorTest", "beq", boolean.class, boolean.class).invoke(o, false, false); + assertEquals(true, beq4); + + var bneq = loader.getMethod("OperatorTest", "bneq", boolean.class, boolean.class).invoke(o, true, true); + assertEquals(false, bneq); + + var and = loader.getMethod("OperatorTest", "and", boolean.class, boolean.class).invoke(o, a, b); + assertEquals(a && b, and); + var and2 = loader.getMethod("OperatorTest", "and", boolean.class, boolean.class).invoke(o, a, !b); + assertEquals(a && !b, and2); + var or = loader.getMethod("OperatorTest", "or", boolean.class, boolean.class).invoke(o, a, b); + assertEquals(a || b, or); + var not = loader.getMethod("OperatorTest", "not", boolean.class).invoke(o, + a); + assertEquals(!a, not); + + var icEq = loader.getMethod("OperatorTest", "icEq", int.class, char.class).invoke(o, x, (char) x); + assertEquals(true, icEq); + + var icLt = loader.getMethod("OperatorTest", "icLt", int.class, char.class).invoke(o, x, (char) y); + assertEquals(x < (char) y, icLt); + + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("ExtendedNotTest") + void extendedNotTest() { + Program program = Resources.getProgram("SimpleTests/ExtendedNotTest.java"); + + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class clazz = loader.findClass("ExtendedNotTest"); + Object o = null; + boolean a = true; + boolean b = false; + int x = 87; + int y = 452; + try { + o = clazz.getDeclaredConstructor().newInstance(); + var notequal = loader.getMethod("ExtendedNotTest", "notequal", int.class, int.class); + + assertEquals(false, notequal.invoke(o, x, x)); + assertEquals(true, notequal.invoke(o, x, y)); + + var multiple = loader.getMethod("ExtendedNotTest", "multiple", boolean.class, boolean.class); + assertEquals(!(!a || b), multiple.invoke(o, a, b)); + + var notWithAssigns = loader.getMethod("ExtendedNotTest", "notWithAssigns", boolean.class); + assertEquals(a, notWithAssigns.invoke(o, a)); + + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("SelfReference") + void SelfReference() { + Program program = Resources.getProgram("SimpleTests/SelfReference.java"); + + System.out.println(program); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + } + + @Test + @DisplayName("MultipleClassesMethodCalls") + void multipleClassesMethodCalls() { + Program program = Resources.getProgram("SimpleTests/MultipleClassesMethodCalls.java"); + + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + System.out.println(tast); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + int x = 10; + try { + Object o = loader.getConstructor("MultipleClassesMethodCalls").newInstance(); + var mainMethod = loader.getMethod("MultipleClassesMethodCalls", "main", int.class); + var returnValue = mainMethod.invoke(o, x); + assertEquals(x, returnValue); + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + + } + + @Test + @DisplayName("RealWhile") + void realWhile() { + Program program = Resources.getProgram("SimpleTests/RealWhile.java"); + + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + System.out.println(tast); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + int x = 10; + try { + Object o = loader.getConstructor("RealWhile").newInstance(); + var mainMethod = loader.getMethod("RealWhile", "foo", int.class); + var returnValue = mainMethod.invoke(o, x); + assertEquals(x * 2, returnValue); + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + + } + + @Test + @DisplayName("LinkedList") + void linkedList() { + Program program = Resources.getProgram("Integration/LinkedList.java"); + + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + System.out.println(tast); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + try { + Object executer = loader.getConstructor("Executer").newInstance(); + var foo = loader.getMethod("Executer", "foo"); + foo.invoke(executer); + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + @Test + @DisplayName("StringLinkedList") + void stringLinkedList() { + Program program = Resources.getProgram("Integration/StringList.java"); + + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + System.out.println(tast); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + try { + Object o = loader.getConstructor("StringList", char.class).newInstance('H'); + var add = loader.getMethod("StringList", "add", char.class); + var print = loader.getMethod("StringList", "print"); + add.invoke(o, 'e'); + add.invoke(o, 'l'); + add.invoke(o, 'l'); + add.invoke(o, 'o'); + add.invoke(o, ' '); + add.invoke(o, 'W'); + add.invoke(o, 'o'); + add.invoke(o, 'r'); + add.invoke(o, 'l'); + add.invoke(o, 'd'); + add.invoke(o, '!'); + print.invoke(o); + System.setOut(new PrintStream(outContent)); + print.invoke(o); + var expected = new String("Hello World!").replaceAll("\\p{C}", ""); + var actual = new String(outContent.toByteArray()).replaceAll("\\p{C}", ""); + assertEquals(expected, actual); + System.setOut(originalOut); + + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + @Test + @DisplayName("SystemOutPrintln Test") + void systemOutPrintlnTest() { + Program program = Resources.getProgram("Integration/SystemOutPrintln.java"); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("SystemOutPrintln"); + Object o = null; + try { + o = c.getDeclaredConstructor().newInstance(); + var foo = loader.getMethod("SystemOutPrintln", "foo"); + var bar = loader.getMethod("SystemOutPrintln", "bar"); + var baz = loader.getMethod("SystemOutPrintln", "baz"); + var errortest = loader.getMethod("SystemOutPrintln", "errorTest"); + System.setOut(new PrintStream(outContent)); + System.setErr(new PrintStream(errContent)); + foo.invoke(o); + bar.invoke(o); + baz.invoke(o); + errortest.invoke(o); + var expected = new String("c\n\tcd\n\t100\n\ttrue\n\t").replaceAll("\\p{C}", ""); + ; + var actual = new String(outContent.toByteArray()).replaceAll("\\p{C}", ""); + assertEquals(expected, actual); + var expectedErr = new String("a\n\t").replaceAll("\\p{C}", ""); + var actualErr = new String(errContent.toByteArray()).replaceAll("\\p{C}", ""); + assertEquals(expectedErr, actualErr); + System.setOut(originalOut); + System.setErr(originalErr); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("StackTest") + void stackTest() { + Program program = Resources.getProgram("Integration/Stack.java"); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("Executer"); + Object o = null; + try { + o = c.getDeclaredConstructor().newInstance(); + var foo = loader.getMethod("Executer", "foo"); + foo.invoke(o); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("OverridingTest") + void OverridingTest() { + Program program = Resources.getProgram("SimpleTests/OverridingTest.java"); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("OverridingTest"); + Object o = null; + try { + o = c.getDeclaredConstructor().newInstance(); + var foo = loader.getMethod("OverridingTest", "foo", int.class); + assertEquals(1337, foo.invoke(o, 30)); + assertEquals(8, foo.invoke(o, 8)); + assertEquals(0, foo.invoke(o, 2)); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("OverridingTestNull") + void OverridingTestNull() { + Program program = Resources.getProgram("SimpleTests/OverridingTestNull.java"); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + System.out.println(tast); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("OverridingTestNull"); + Object o = null; + try { + o = c.getDeclaredConstructor().newInstance(); + var foo = loader.getMethod("OverridingTestNull", "foo", int.class); + assertEquals(1337, foo.invoke(o, 40)); + assertEquals(1337, foo.invoke(o, 15)); + assertEquals(8, foo.invoke(o, 8)); + assertEquals(0, foo.invoke(o, 2)); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("OverridingTestNullMultiple") + void OverridingTestNullMultiple() { + Program program = Resources.getProgram("SimpleTests/OverridingTestNullMultiple.java"); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + System.out.println(tast); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("OverridingTestNullMultiple"); + Object o = null; + try { + o = c.getDeclaredConstructor().newInstance(); + var foo = loader.getMethod("OverridingTestNullMultiple", "foo", int.class); + assertEquals(1337, foo.invoke(o, 40)); + assertEquals(1337, foo.invoke(o, 20)); + assertEquals(1337, foo.invoke(o, 15)); + assertEquals(8, foo.invoke(o, 8)); + assertEquals(0, foo.invoke(o, 2)); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("MultipleMethodsConflictTest") + void MultipleMethodsConflictTest() { + Program program = Resources.getProgram("FailTests/MultipleMethodsConflict.java"); + System.err.print(assertThrows( + SemanticError.class, + () -> Compiler.getFactory().getTastAdapter().getTast(program), + "Expected SemanticError to be thrown").getMessage()); + } + + @Test + @DisplayName("LOFOI") + void lOFOITest() { + Program program = Resources.getProgram("Integration/LOFOI.java"); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("LOFOI"); + Object o = null; + try { + o = c.getDeclaredConstructor().newInstance(); + var foo = loader.getMethod("LOFOI", "foo"); + var bar = loader.getMethod("LOFOI", "bar"); + assertEquals(20, foo.invoke(o)); + assertEquals(10, bar.invoke(o)); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("LOFOIFailTest") + void lOFOIFailTest() { + Program program = Resources.getProgram("FailTests/LOFOI.java"); + System.err.print(assertThrows( + SemanticError.class, + () -> Compiler.getFactory().getTastAdapter().getTast(program), + "Expected SemanticError to be thrown").getMessage()); + } + + @Test + @DisplayName("MethodCallsInWhile") + void methodCallsInWhile() { + Program program = Resources.getProgram("SimpleTests/MethodCallsInWhile.java"); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + // Just checks if no error is thrown + } + + @Test + @DisplayName("MethodCallStressTest") + void methodCallStressTest() { + Program program = Resources.getProgram("SimpleTests/MethodCallStressTest.java"); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + + } + + // Stream outContent = new ByteArrayOutputStream(); + // private final ByteArrayOutputStream errContent = new ByteArrayOutputStream(); + // private final PrintStream originalOut = System.out; + // private final PrintStream originalErr = System.err; + + @Test + @DisplayName("DijsktraTest") + void dijsktraTest() { + Program program = Resources.getProgram("Integration/Dijkstra.java"); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("Dijkstra"); + Object o = null; + try { + o = c.getDeclaredConstructor().newInstance(); + var foo = loader.getMethod("Dijkstra", "main"); + foo.invoke(o); + System.setOut(new PrintStream(outContent)); + foo.invoke(o); + var expected = new String( + "Shortest path from 1 to 8: 1 10 8 With a distance of 2Shortest path from 1 to 12: 1 10 8 12 With a distance of 3Shortest path from 4 to 12: 4 8 12 With a distance of 2Shortest path from 4 to 9: 4 3 5 9 With a distance of 3Shortest path from 6 to 9: 6 5 9 With a distance of 2") + .replaceAll("\\p{C}", ""); + var actual = new String(outContent.toByteArray()).replaceAll("\\p{C}", ""); + assertEquals(expected, actual); + System.setOut(originalOut); + + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("VoidReturn") + void voidReturn() { + // private final ByteArrayOutput + Program program = Resources.getProgram("SimpleTests/VoidReturn.java"); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + // ReflectLoader loader = new ReflectLoader(bc); + + } + + @Test + @DisplayName("OperatorStacking") + void operatorStacking() { + Program program = Resources.getProgram("SimpleTests/OperatorStacking.java"); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("OperatorStacking"); + Object o = null; + try { + o = c.getDeclaredConstructor().newInstance(); + var foo = loader.getMethod("OperatorStacking", "foo"); + var bar = loader.getMethod("OperatorStacking", "bar"); + assertEquals(true, foo.invoke(o)); + assertEquals(1 + 2 * 3 - 4 % 6, bar.invoke(o)); + } catch (Exception e) { + fail(e.getMessage()); + } + + } + + @Test + @DisplayName("ConditionalEvaluation") + void conditionalEval() { + Program program = Resources.getProgram("SimpleTests/ConditionalEvaluation.java"); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("ConditionalEvaluation"); + Object o = null; + try { + o = c.getDeclaredConstructor().newInstance(); + var foo = loader.getMethod("ConditionalEvaluation", "foo"); + var bar = loader.getMethod("ConditionalEvaluation", "bar"); + System.setOut(new PrintStream(outContent)); + assertEquals(true, bar.invoke(o)); + assertEquals(true, foo.invoke(o)); + var expected = new String("bar\n\tfoo\n\tfoo").replaceAll("\\p{C}", ""); + var actual = new String(outContent.toByteArray()).replaceAll("\\p{C}", ""); + assertEquals(expected, actual); + System.setOut(originalOut); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("ForTest") + void forTest() { + // private final ByteArrayOutput + Program program = Resources.getProgram("SimpleTests/ForTest.java"); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + // ReflectLoader loader = new ReflectLoader(bc); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("ForTest"); + Object o = null; + try { + o = c.getDeclaredConstructor().newInstance(); + var foo = loader.getMethod("ForTest", "foo"); + foo.invoke(o); + System.setOut(new PrintStream(outContent)); + foo.invoke(o); + var expected = new String("0123456789").replaceAll("\\p{C}", ""); + var actual = new String(outContent.toByteArray()).replaceAll("\\p{C}", ""); + assertEquals(expected, actual); + System.setOut(originalOut); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("IncDecStressTest") + void incDecTest() { + Program program = Resources.getProgram("SimpleTests/IncDecStressTest.java"); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("IncDecStressTest"); + Object o = null; + int value = 5; + try { + o = c.getDeclaredConstructor().newInstance(); + var incrementThenReturn = loader.getMethod("IncDecStressTest", "incrementThenReturn", int.class); + var returnThenIncrement = loader.getMethod("IncDecStressTest", "returnThenIncrement", int.class); + var decrementThenReturn = loader.getMethod("IncDecStressTest", "decrementThenReturn", int.class); + var returnThenDecrement = loader.getMethod("IncDecStressTest", "returnThenDecrement", int.class); + var callInline = loader.getMethod("IncDecStressTest", "callInline", int.class); + + var shouldBeIncremented = incrementThenReturn.invoke(o, value); + var shouldBeSame = returnThenIncrement.invoke(o, value); + var shouldBeDecremented = decrementThenReturn.invoke(o, value); + var shouldBeSame2 = returnThenDecrement.invoke(o, value); + var shouldBeIncremented2 = callInline.invoke(o, value); + + assertEquals(value + 1, shouldBeIncremented); + assertEquals(value, shouldBeSame); + assertEquals(value - 1, shouldBeDecremented); + assertEquals(value, shouldBeSame2); + assertEquals(value + 1, shouldBeIncremented2); + + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("Div0Test") + void div0() { + Program program = Resources.getProgram("FailTests/Div0.java"); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + try { + Class c = loader.findClass("Div0"); + var main = c.getMethod("main", String[].class); + main.invoke(null, new Object[] { new String[] {} }); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + System.err.println(); + assertEquals("/ by zero", e.getCause().getMessage()); + return; + } + fail("Should have thrown an exception"); + + } +} diff --git a/src/test/java/CodeGen/TestRunner.java b/src/test/java/CodeGen/TestRunner.java new file mode 100644 index 0000000..eff363b --- /dev/null +++ b/src/test/java/CodeGen/TestRunner.java @@ -0,0 +1,356 @@ +package CodeGen; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import Helper.MockGenerator; +import Helper.ReflectLoader; +import Helper.Resources; +import common.Compiler; +import common.PrintableVector; +import syntaxtree.structure.ClassDecl; +import syntaxtree.structure.ConstructorDecl; +import syntaxtree.structure.Program; + +@DisplayName("Bytecode Generation") +public class TestRunner { + + private final ByteArrayOutputStream outContent = new ByteArrayOutputStream(); + private final ByteArrayOutputStream errContent = new ByteArrayOutputStream(); + private final PrintStream originalOut = System.out; + private final PrintStream originalErr = System.err; + + @Test + @DisplayName("Empty Class") + void main() { + ClassDecl emptyClass = new ClassDecl("EmptyClass", new PrintableVector<>(), new PrintableVector<>(), + new PrintableVector<>()); + PrintableVector classDecls = new PrintableVector<>(); + classDecls.add(emptyClass); + + var tast = new Program(classDecls); + + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("EmptyClass"); + Object o; + try { + o = c.getDeclaredConstructor().newInstance(); + assertEquals(o.getClass().getName(), "EmptyClass"); + } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException + | NoSuchMethodException | SecurityException e) { + fail(e.getLocalizedMessage()); + } + } + + @Test + @DisplayName("EmptyClassWithConstructor") + void emptyClassWithConstructor() { + PrintableVector constructors = new PrintableVector<>(); + constructors.add(new ConstructorDecl()); + ClassDecl classDecl = new ClassDecl("EmptyClassWithConstructor", new PrintableVector<>(), constructors, + new PrintableVector<>()); + PrintableVector classDecls = new PrintableVector<>(); + classDecls.add(classDecl); + var tast = new Program(classDecls); + + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("EmptyClassWithConstructor"); + Object o; + try { + o = c.getDeclaredConstructor().newInstance(); + assertEquals(o.getClass().getName(), "EmptyClassWithConstructor"); + } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException + | NoSuchMethodException | SecurityException e) { + fail(e.getLocalizedMessage()); + } + } + + @Test + @DisplayName("Constructor With Parameters") + void constructorWithParameters() { + Program tast = MockGenerator.getConstructorParameterTast(); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("ConstructorParams"); + Object o = null; + try { + o = c.getDeclaredConstructor(int.class).newInstance(1); + assertEquals(o.getClass().getName(), "ConstructorParams"); + } catch (Exception e) { + fail(e.getLocalizedMessage()); + } + + } + + @Test + @DisplayName("Constructor With this. assign body") + void constructorWithThisAssignBody() { + Program tast = MockGenerator.getConstructorThisDotTast(); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("ConstructorThisDot"); + Object o = null; + try { + o = c.getDeclaredConstructor().newInstance(); + var i = loader.getField("ConstructorThisDot", "i"); + var ivalue = i.get(o); + assertEquals(5, ivalue); + } catch (Exception e) { + fail(e.getLocalizedMessage()); + } + + } + + @Test + @DisplayName("ClassFields - autoAccess") + void classFieldsAuto() { + Program tast = MockGenerator.getAutoClassFieldAst(); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + try { + var autoAccess = loader.getField("AutoAccessModifierField", "autoAccess"); + System.out.println(autoAccess.getModifiers()); + assertEquals(0, autoAccess.getModifiers()); + + } catch (Exception e) { + fail(e.getLocalizedMessage()); + } + + } + + @Test + @DisplayName("ClassFields - privateAccess") + void classFieldsPrivate() { + Program tast = MockGenerator.getClassFieldsTast(); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + try { + var autoAccess = loader.getField("ClassFields", "privateAccess"); + assertEquals(Modifier.PRIVATE, autoAccess.getModifiers()); + } catch (Exception e) { + fail(e.getLocalizedMessage()); + } + + } + + @Test + @DisplayName("ClassFields - publicAccess") + void classFieldsPublic() { + Program tast = MockGenerator.getClassFieldsTast(); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + try { + var autoAccess = loader.getField("ClassFields", "publicAccess"); + assertEquals(Modifier.PUBLIC, autoAccess.getModifiers()); + } catch (Exception e) { + fail(e.getLocalizedMessage()); + } + + } + + @Test + @DisplayName("ClassFields - protectedAccess") + void classFieldsProtected() { + Program tast = MockGenerator.getClassFieldsTast(); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + try { + var autoAccess = loader.getField("ClassFields", "protectedAccess"); + + assertEquals(Modifier.PROTECTED, autoAccess.getModifiers()); + } catch (Exception e) { + fail(e.getLocalizedMessage()); + } + + } + + @Test + @DisplayName("VoidMethod") + void voidMethod() { + Program tast = MockGenerator.getVoidMethodTast(); + + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("VoidMethod"); + Object o = null; + try { + o = c.getDeclaredConstructor().newInstance(); + var m = loader.getMethod("VoidMethod", "foo"); + m.invoke(o); + assertEquals("foo", m.getName()); + } catch (Exception e) { + fail(e.getLocalizedMessage()); + } + + } + + @Test + @DisplayName("RealConstructor") + void realConstructor() { + Program tast = MockGenerator.getRealConstructorTast(); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("RealConstructor"); + try { + int randomI = 2; + var constructor = c.getDeclaredConstructor(int.class); + Object o = constructor.newInstance(randomI); + var i = loader.getField("RealConstructor", "i"); + int ivalue = (int) i.get(o); + assertEquals(randomI, ivalue); + } catch (NoSuchFieldException e) { + fail("No such field"); + } catch (Exception e) { + fail(e.getCause()); + } + } + + @Test + @DisplayName("MethodCall") + void methodCall() { + Program tast = MockGenerator.getMethodCallTast(); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("MethodCall"); + Object o = null; + int value = 1; + try { + o = c.getDeclaredConstructor().newInstance(); + var i = loader.getField("MethodCall", "i"); + int ivalue = (int) i.get(o); + assertEquals(value, ivalue); + } catch (Exception e) { + fail(e.getMessage()); + } + + } + + @Test + @DisplayName("MiniLinkedList") + void miniLinkedList() { + Program program = Resources.getProgram("SimpleTests/MiniLinkedList.java"); + + System.out.println(program); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + } + + @Test + @DisplayName("SystemOutPrintln Test") + void systemOutPrintlnTest() { + Program tast = MockGenerator.getSystemOutPrintlnTast(); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("SystemOutPrintln"); + Object o = null; + try { + o = c.getDeclaredConstructor().newInstance(); + var m = loader.getMethod("SystemOutPrintln", "foo"); + m.invoke(o); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("SystemOutPrintlnString Test") + void systemOutPrintlnStringTest() { + Program tast = MockGenerator.getSystemOutPrintStringTast(); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("SystemOutPrintlnString"); + Object o = null; + try { + o = c.getDeclaredConstructor().newInstance(); + var m = loader.getMethod("SystemOutPrintlnString", "foo"); + m.invoke(o); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("MainMethodTest") + void mainMethodTest() { + Program tast = MockGenerator.getMainMethodTestTast(); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("MainMethodTest"); + try { + var m = c.getMethod("main", String[].class); + m.invoke(null, new Object[] { new String[] {} }); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("IncTest") + void incTest() { + Program tast = MockGenerator.getIncTestTast(); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("IncTest"); + Object o = null; + try { + o = c.getDeclaredConstructor().newInstance(); + var foo = loader.getMethod("IncTest", "foo"); + var bar = loader.getMethod("IncTest", "bar"); + foo.invoke(o); + bar.invoke(o); + System.setOut(new PrintStream(outContent)); + foo.invoke(o); + var expected = new String("0123456789").replaceAll("\\p{C}", ""); + var actual = new String(outContent.toByteArray()).replaceAll("\\p{C}", ""); + outContent.reset(); + assertEquals(expected, actual); + bar.invoke(o); + actual = new String(outContent.toByteArray()).replaceAll("\\p{C}", ""); + assertEquals(expected, actual); + System.setOut(originalOut); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + @DisplayName("DecTest") + void decTest() { + Program tast = MockGenerator.getDecTestTast(); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + ReflectLoader loader = new ReflectLoader(bc); + Class c = loader.findClass("DecTest"); + Object o = null; + try { + o = c.getDeclaredConstructor().newInstance(); + var foo = loader.getMethod("DecTest", "foo"); + var bar = loader.getMethod("DecTest", "bar"); + foo.invoke(o); + bar.invoke(o); + System.setOut(new PrintStream(outContent)); + foo.invoke(o); + var expected = new String("10987654321").replaceAll("\\p{C}", ""); + var actual = new String(outContent.toByteArray()).replaceAll("\\p{C}", ""); + outContent.reset(); + assertEquals(expected, actual); + bar.invoke(o); + actual = new String(outContent.toByteArray()).replaceAll("\\p{C}", ""); + assertEquals(expected, actual); + System.setOut(originalOut); + } catch (Exception e) { + fail(e.getMessage()); + } + } + +} diff --git a/src/test/java/Helper/MockGenerator.java b/src/test/java/Helper/MockGenerator.java new file mode 100644 index 0000000..7354976 --- /dev/null +++ b/src/test/java/Helper/MockGenerator.java @@ -0,0 +1,965 @@ +package Helper; + +import common.AccessModifier; +import common.BaseType; +import common.Operator; +import common.Primitives; +import common.PrintableVector; +import common.ReferenceType; +import syntaxtree.expressions.Binary; +import syntaxtree.expressions.BoolExpr; +import syntaxtree.expressions.CharExpr; +import syntaxtree.expressions.IExpression; +import syntaxtree.expressions.InstVar; +import syntaxtree.expressions.IntegerExpr; +import syntaxtree.expressions.LocalOrFieldVar; +import syntaxtree.expressions.Null; +import syntaxtree.expressions.StringExpr; +import syntaxtree.expressions.This; +import syntaxtree.statementexpression.Assign; +import syntaxtree.statementexpression.CrementStmtExpr; +import syntaxtree.statementexpression.MethodCall; +import syntaxtree.statementexpression.NewDecl; +import syntaxtree.statements.Block; +import syntaxtree.statements.ForStmt; +import syntaxtree.statements.IStatement; +import syntaxtree.statements.LocalVarDecl; +import syntaxtree.statements.ReturnStmt; +import syntaxtree.structure.ClassDecl; +import syntaxtree.structure.ConstructorDecl; +import syntaxtree.structure.FieldDecl; +import syntaxtree.structure.MainMethodDecl; +import syntaxtree.structure.MethodDecl; +import syntaxtree.structure.MethodParameter; +import syntaxtree.structure.Program; + +public abstract class MockGenerator { + + /** + * @param className + * @return Program + */ + public static Program getEmptyProgram(String className) { + + PrintableVector classes = new PrintableVector<>(); + classes.add(getEmptyClass(className)); + + return new Program(classes); + } + + /** + * @param id + * @return ClassDecl + */ + public static ClassDecl getEmptyClass(String id) { + return new ClassDecl(id, new PrintableVector<>(), new PrintableVector<>(), new PrintableVector<>()); + } + + /** + * @param expressions + * @return Block + */ + public static Block getBlock(IStatement... expressions) { + PrintableVector expressionsVector = new PrintableVector<>(); + for (IStatement expression : expressions) { + expressionsVector.add(expression); + } + return new Block(expressionsVector); + } + + /** + * @return Block + */ + public static Block getEmptyBlock() { + return new Block(); + } + + /** + * @param expressions + * @return PrintableVector + */ + public static PrintableVector getArguments(IExpression... expressions) { + PrintableVector arguments = new PrintableVector<>(); + for (IExpression expression : expressions) { + arguments.add(expression); + } + return arguments; + } + + /** + * @param constructors + * @return PrintableVector + */ + public static PrintableVector getConstructors(ConstructorDecl... constructors) { + PrintableVector cons = new PrintableVector<>(); + if (constructors.length == 0) + cons.add(new ConstructorDecl()); + for (ConstructorDecl constructor : constructors) { + cons.add(constructor); + } + return cons; + } + + /** + * @return PrintableVector + */ + public static PrintableVector getEmptyParameters() { + return new PrintableVector<>(); + } + + /** + * @param parameters + * @return PrintableVector + */ + public static PrintableVector getParameters(MethodParameter... parameters) { + PrintableVector parametersVector = new PrintableVector<>(); + for (MethodParameter parameter : parameters) { + parametersVector.add(parameter); + } + return parametersVector; + } + + /** + * @return Program + */ + public static Program getClassFieldsTast() { + return getClassFieldsAst(); + } + + /** + * @return Program + */ + public static Program getClassFieldsAst() { + Program expectedAst = getEmptyProgram("ClassFields"); + + expectedAst.getClasses().firstElement().getConstructorDeclarations().add(new ConstructorDecl()); + + FieldDecl privateField = new FieldDecl("privateAccess", AccessModifier.PRIVATE); + privateField.setType(new BaseType(Primitives.INT)); + FieldDecl publicField = new FieldDecl("publicAccess", AccessModifier.PUBLIC); + publicField.setType(new BaseType(Primitives.INT)); + FieldDecl protectedField = new FieldDecl("protectedAccess", AccessModifier.PROTECTED); + protectedField.setType(new BaseType(Primitives.INT)); + + PrintableVector fields = expectedAst.getClasses().firstElement().getFieldDelcarations(); + fields.add(privateField); + fields.add(publicField); + fields.add(protectedField); + + return expectedAst; + } + + /** + * @return Program + */ + public static Program getAutoClassFieldAst() { + Program expectedAst = getEmptyProgram("AutoAccessModifierField"); + + FieldDecl autoField = new FieldDecl(new BaseType(Primitives.INT), "autoAccess"); + + expectedAst.getClasses().firstElement().getConstructorDeclarations().add(new ConstructorDecl()); + + PrintableVector fields = expectedAst.getClasses().firstElement().getFieldDelcarations(); + fields.add(autoField); + return expectedAst; + } + + /** + * @return Program + */ + public static Program getAutoClassFieldTast() { + return getAutoClassFieldAst(); + } + + /** + * @return Program + */ + public static Program getConstructorParameterTast() { + return getConstructorParameterAst(); + } + + /** + * @return Program + */ + public static Program getConstructorParameterAst() { + Program expectedAst = getEmptyProgram("ConstructorParams"); + + ClassDecl classDecl = expectedAst.getClasses().firstElement(); + + MethodParameter parameter = new MethodParameter(Primitives.INT, "i"); + + PrintableVector parameters = new PrintableVector<>(); + parameters.add(parameter); + + classDecl.getConstructorDeclarations() + .add(new ConstructorDecl(AccessModifier.PUBLIC, parameters, getEmptyBlock())); + + return expectedAst; + } + + /** + * @return Program + */ + public static Program getConstructorThisDotAst() { + + Program expectedAst = getEmptyProgram("ConstructorThisDot"); + + FieldDecl i = new FieldDecl("i", AccessModifier.PUBLIC); + i.setType(new BaseType(Primitives.INT)); + + PrintableVector fields = expectedAst.getClasses().firstElement().getFieldDelcarations(); + fields.add(i); + + ClassDecl classDecl = expectedAst.getClasses().firstElement(); + + Block block = getEmptyBlock(); + + Assign assign = new Assign(new InstVar("i", new This()), new IntegerExpr(5)); + block.getStatements().add(assign); + + classDecl.getConstructorDeclarations() + .add(new ConstructorDecl(AccessModifier.PUBLIC, getParameters(), block)); + System.out.println(classDecl); + return expectedAst; + + } + + /** + * @return Program + */ + public static Program getConstructorThisDotTast() { + Program expectedTast = getEmptyProgram("ConstructorThisDot"); + + FieldDecl i = new FieldDecl("i", AccessModifier.PUBLIC); + i.setType(new BaseType(Primitives.INT)); + + PrintableVector fields = expectedTast.getClasses().firstElement().getFieldDelcarations(); + fields.add(i); + + ClassDecl classDecl = expectedTast.getClasses().firstElement(); + + Block block = getEmptyBlock(); + + var thisi = new InstVar("i", new This("ConstructorThisDot")); + thisi.setType(Primitives.INT); + + Assign assign = new Assign(thisi, new IntegerExpr(5)); + assign.setType(Primitives.INT); + block.getStatements().add(assign); + + classDecl.getConstructorDeclarations() + .add(new ConstructorDecl(AccessModifier.PUBLIC, getEmptyParameters(), block)); + + return expectedTast; + } + + /** + * @return Program + */ + public static Program getVoidMethodAst() { + Program expectedAst = getEmptyProgram("VoidMethod"); + + ClassDecl classDecl = expectedAst.getClasses().firstElement(); + + expectedAst.getClasses().firstElement().getConstructorDeclarations().add(new ConstructorDecl()); + + PrintableVector methods = classDecl.getMethodDeclarations(); + MethodDecl foo = new MethodDecl(new BaseType(Primitives.VOID), "foo", getEmptyParameters(), + getEmptyBlock()); + methods.add(foo); + + return expectedAst; + } + + /** + * @return Program + */ + public static Program getVoidMethodTast() { + return getVoidMethodAst(); + } + + /** + * @return Program + */ + public static Program getRealMethodAst() { + Program expectedAst = getEmptyProgram("RealMethod"); + + ClassDecl classDecl = expectedAst.getClasses().firstElement(); + + Block block = getEmptyBlock(); + ReturnStmt returnStmt = new ReturnStmt(new LocalOrFieldVar("i")); + block.getStatements().add(returnStmt); + + var parameters = getEmptyParameters(); + parameters.add(new MethodParameter(Primitives.INT, "i")); + + PrintableVector methods = classDecl.getMethodDeclarations(); + MethodDecl foo = new MethodDecl(new BaseType(Primitives.INT), "foo", parameters, block); + methods.add(foo); + + return expectedAst; + } + + /** + * @return Program + */ + public static Program getRealConstructorAst() { + Program expectedAst = getEmptyProgram("RealConstructor"); + + ClassDecl classDecl = expectedAst.getClasses().firstElement(); + + FieldDecl i = new FieldDecl(AccessModifier.PRIVATE, new BaseType(Primitives.INT), "i"); + + classDecl.getFieldDelcarations().add(i); + Assign assignStmt = new Assign(new InstVar(new This(), "i"), new LocalOrFieldVar("i")); + Block block = getBlock(assignStmt); + + var parameters = getParameters(new MethodParameter(Primitives.INT, "i")); + + PrintableVector constructors = classDecl.getConstructorDeclarations(); + ConstructorDecl constructor = new ConstructorDecl(AccessModifier.PUBLIC, parameters, block); + constructors.add(constructor); + + return expectedAst; + } + + /** + * @return Program + */ + public static Program getRealConstructorTast() { + String className = "RealConstructor"; + Program expectedTast = getEmptyProgram(className); + + ClassDecl classDecl = expectedTast.getClasses().firstElement(); + FieldDecl i = new FieldDecl(AccessModifier.PRIVATE, new BaseType(Primitives.INT), "i"); + + classDecl.getFieldDelcarations().add(i); + Assign assignStmt = new Assign(new InstVar(new BaseType(Primitives.INT), new This( + className), "i"), new LocalOrFieldVar(new BaseType(Primitives.INT), "i")); + + assignStmt.setType(new BaseType(Primitives.INT)); + + Block block = getBlock(assignStmt); + + var parameters = getParameters(new MethodParameter(Primitives.INT, "i")); + + PrintableVector constructors = classDecl.getConstructorDeclarations(); + ConstructorDecl constructor = new ConstructorDecl(AccessModifier.PUBLIC, parameters, block); + constructors.add(constructor); + + return expectedTast; + } + + /** + * @return Program + */ + public static Program getMethodCallAst() { + Program expectedAst = getEmptyProgram("MethodCall"); + + ClassDecl classDecl = expectedAst.getClasses().firstElement(); + var fields = classDecl.getFieldDelcarations(); + fields.add(new FieldDecl(new BaseType(Primitives.INT), "i")); + PrintableVector constructors = classDecl.getConstructorDeclarations(); + + Block block = getBlock( + new Assign(new InstVar(new This(), "i"), + new MethodCall(new This(), "foo", getArguments()))); + constructors.add(new ConstructorDecl(AccessModifier.PUBLIC, getParameters(), block)); + + Block fooBlock = getBlock(new ReturnStmt(new IntegerExpr(1))); + PrintableVector methods = classDecl.getMethodDeclarations(); + methods.add(new MethodDecl(new BaseType(Primitives.INT), "foo", getEmptyParameters(), fooBlock)); + + return expectedAst; + } + + /** + * @return Program + */ + public static Program getMethodCallTast() { + Program expectedTast = getEmptyProgram("MethodCall"); + + ClassDecl classDecl = expectedTast.getClasses().firstElement(); + var fields = classDecl.getFieldDelcarations(); + fields.add(new FieldDecl(new BaseType(Primitives.INT), "i")); + PrintableVector constructors = classDecl.getConstructorDeclarations(); + + Block block = getBlock( + new Assign(new BaseType( + Primitives.INT), + new InstVar(new BaseType(Primitives.INT), new This("MethodCall"), "i"), + new MethodCall(new BaseType(Primitives.INT), new This("MethodCall"), + "foo", getArguments()))); + constructors.add(new ConstructorDecl(AccessModifier.PUBLIC, getParameters(), block)); + + Block fooBlock = getBlock(new ReturnStmt(new BaseType(Primitives.INT), new IntegerExpr(1))); + fooBlock.setType(Primitives.INT); + PrintableVector methods = classDecl.getMethodDeclarations(); + methods.add(new MethodDecl(new BaseType(Primitives.INT), "foo", getEmptyParameters(), fooBlock)); + + return expectedTast; + } + + /** + * @return Program + */ + public static Program getMethodCallWithParameterAst() { + Program expectedAst = getEmptyProgram("MethodCallParams"); + + ClassDecl classDecl = expectedAst.getClasses().firstElement(); + var fields = classDecl.getFieldDelcarations(); + fields.add(new FieldDecl(new BaseType(Primitives.INT), "i")); + PrintableVector constructors = classDecl.getConstructorDeclarations(); + + Block block = getBlock( + new Assign(new InstVar(new This(), "i"), + new MethodCall(new This(), "foo", + getArguments(new LocalOrFieldVar("i"))))); + constructors.add(new ConstructorDecl(AccessModifier.PUBLIC, + getParameters(new MethodParameter(Primitives.INT, "i")), block)); + + Block fooBlock = getBlock(new ReturnStmt(new LocalOrFieldVar("i"))); + PrintableVector methods = classDecl.getMethodDeclarations(); + methods.add(new MethodDecl(new BaseType(Primitives.INT), "foo", + getParameters(new MethodParameter(Primitives.INT, "i")), fooBlock)); + + return expectedAst; + } + + /** + * @return Program + */ + public static Program getCharArgumentAst() { + Program expectedAst = getEmptyProgram("CharArgument"); + + ClassDecl classDecl = expectedAst.getClasses().firstElement(); + var fields = classDecl.getFieldDelcarations(); + fields.add(new FieldDecl(new BaseType(Primitives.CHAR), "c")); + PrintableVector constructors = classDecl.getConstructorDeclarations(); + + Block block = getBlock( + new Assign(new InstVar(new This(), "c"), + new MethodCall(new This(), "foo", getArguments(new CharExpr('a'))))); + constructors.add(new ConstructorDecl(AccessModifier.PUBLIC, + getParameters(), block)); + + Block fooBlock = getBlock(new ReturnStmt(new LocalOrFieldVar("c"))); + PrintableVector methods = classDecl.getMethodDeclarations(); + methods.add(new MethodDecl(new BaseType(Primitives.CHAR), "foo", + getParameters(new MethodParameter(Primitives.CHAR, "c")), fooBlock)); + + return expectedAst; + } + + /** + * @return Program + */ + public static Program getGetterFunctionAst() { + Program expectedAst = getEmptyProgram("GetterFunction"); + + ClassDecl classDecl = expectedAst.getClasses().firstElement(); + + FieldDecl i = new FieldDecl(AccessModifier.PRIVATE, new BaseType(Primitives.INT), "i"); + + classDecl.getFieldDelcarations().add(i); + Assign assignStmt = new Assign(new InstVar(new This(), "i"), new LocalOrFieldVar("i")); + Block block = getBlock(assignStmt); + + var parameters = getParameters(new MethodParameter(Primitives.INT, "i")); + + PrintableVector constructors = classDecl.getConstructorDeclarations(); + ConstructorDecl constructor = new ConstructorDecl(AccessModifier.PUBLIC, parameters, block); + constructors.add(constructor); + + var getI = new MethodDecl(AccessModifier.PUBLIC, new BaseType(Primitives.INT), "getI", getParameters(), + getBlock(new ReturnStmt(new InstVar(new This(), "i")))); + + classDecl.getMethodDeclarations().add(getI); + + return expectedAst; + } + + public static Program getExplicitNullAssignAst() { + Program expectedAst = getEmptyProgram("ExplicitNullAssign"); + + ClassDecl classDecl = expectedAst.getClasses().firstElement(); + + FieldDecl i = new FieldDecl(AccessModifier.PACKAGE_PRIVATE, new ReferenceType("ExplicitNullAssign"), + "e"); + + classDecl.getFieldDelcarations().add(i); + + var test = new MethodDecl(AccessModifier.PACKAGE_PRIVATE, new BaseType(Primitives.VOID), "test", + getParameters(), + getBlock(new Assign(new LocalOrFieldVar("e"), new Null()))); + + classDecl.getMethodDeclarations().add(test); + + classDecl.getConstructorDeclarations().add(new ConstructorDecl()); + + return expectedAst; + } + + public static Program getSelfReferenceAst() { + Program expectedAst = getEmptyProgram("SelfReference"); + + ClassDecl classDecl = expectedAst.getClasses().firstElement(); + + FieldDecl i = new FieldDecl(AccessModifier.PACKAGE_PRIVATE, new ReferenceType("SelfReference"), + "selfRef"); + + classDecl.getFieldDelcarations().add(i); + + var foo = new MethodDecl(AccessModifier.PACKAGE_PRIVATE, new BaseType(Primitives.INT), "foo", + getParameters(), + getBlock(new ReturnStmt(new MethodCall(new This(), "baz", getArguments())))); + + var baz = new MethodDecl(AccessModifier.PACKAGE_PRIVATE, new BaseType(Primitives.INT), "baz", + getParameters(), + getBlock(new ReturnStmt(new IntegerExpr(10)))); + + var bar = new MethodDecl(AccessModifier.PACKAGE_PRIVATE, new BaseType(Primitives.INT), "bar", + getParameters(), + getBlock( + new LocalVarDecl(new ReferenceType("SelfReference"), "self", + new NewDecl("SelfReference", getArguments())), + new ReturnStmt(new MethodCall( + new InstVar(new LocalOrFieldVar("self"), "selfRef"), + "foo", + getArguments())))); + + classDecl.getMethodDeclarations().add(foo); + classDecl.getMethodDeclarations().add(baz); + classDecl.getMethodDeclarations().add(bar); + + classDecl.getConstructorDeclarations().add(new ConstructorDecl()); + + return expectedAst; + } + + public static Program getSelfReferenceTast() { + Program expectedAst = getEmptyProgram("SelfReference"); + + ClassDecl classDecl = expectedAst.getClasses().firstElement(); + + FieldDecl i = new FieldDecl(AccessModifier.PACKAGE_PRIVATE, new ReferenceType("SelfReference"), + "selfRef"); + + classDecl.getFieldDelcarations().add(i); + + Block fooBlock = getBlock(new ReturnStmt(new BaseType(Primitives.INT), + new MethodCall(new BaseType(Primitives.INT), new This("SelfReference"), "baz", + getArguments()))); + fooBlock.setType(new BaseType(Primitives.INT)); + + Block bazBlock = getBlock(new ReturnStmt(new BaseType(Primitives.INT), new IntegerExpr(10))); + bazBlock.setType(new BaseType(Primitives.INT)); + + Block barBlock = getBlock( + new LocalVarDecl(new ReferenceType("SelfReference"), "self", + new NewDecl("SelfReference", getArguments())), + new ReturnStmt(new BaseType(Primitives.INT), + new MethodCall(new BaseType(Primitives.INT), + new InstVar(new ReferenceType("SelfReference"), + new LocalOrFieldVar(new ReferenceType( + "SelfReference"), + "self"), + "selfRef"), + "foo", + getArguments()))); + + barBlock.setType(new BaseType(Primitives.INT)); + + var foo = new MethodDecl(AccessModifier.PACKAGE_PRIVATE, new BaseType(Primitives.INT), "foo", + getParameters(), fooBlock); + + var baz = new MethodDecl(AccessModifier.PACKAGE_PRIVATE, new BaseType(Primitives.INT), "baz", + getParameters(), bazBlock); + + var bar = new MethodDecl(AccessModifier.PACKAGE_PRIVATE, new BaseType(Primitives.INT), "bar", + getParameters(), + barBlock); + + classDecl.getMethodDeclarations().add(foo); + classDecl.getMethodDeclarations().add(baz); + classDecl.getMethodDeclarations().add(bar); + + classDecl.getConstructorDeclarations().add(new ConstructorDecl()); + + return expectedAst; + } + + public static Program getThisDotMethodCallAst() { + Program expectedAst = getEmptyProgram("ThisDotMethodCall"); + + ClassDecl classDecl = expectedAst.getClasses().firstElement(); + var fields = classDecl.getFieldDelcarations(); + fields.add(new FieldDecl(new BaseType(Primitives.INT), "i")); + PrintableVector constructors = classDecl.getConstructorDeclarations(); + + Block block = getBlock( + new Assign(new InstVar(new This(), "i"), + new MethodCall(new This(), "foo", getArguments()))); + constructors.add(new ConstructorDecl(AccessModifier.PUBLIC, getParameters(), block)); + + Block fooBlock = getBlock(new ReturnStmt(new IntegerExpr(1))); + PrintableVector methods = classDecl.getMethodDeclarations(); + methods.add(new MethodDecl(new BaseType(Primitives.INT), "foo", getEmptyParameters(), fooBlock)); + + return expectedAst; + } + + public static Program getValueAdapterTestAst() { + Program expectedAst = getEmptyProgram("ValueAdapterTests"); + + Block readsTrueBlock = getBlock(new ReturnStmt(new BoolExpr(true))); + + Block readsFalseBlock = getBlock(new ReturnStmt(new BoolExpr(false))); + + Block readsTrueAndFalseBlock = getBlock(new ReturnStmt(new Binary(new BoolExpr(true), + Operator.AND, new BoolExpr(false)))); + + Block readsIntBlock = getBlock(new ReturnStmt(new IntegerExpr(1))); + + Block readsIntAndIntBlock = getBlock(new ReturnStmt(new Binary(new IntegerExpr(1), + Operator.PLUS, new IntegerExpr(1)))); + + Block readsCharBlock = getBlock(new ReturnStmt(new CharExpr('a'))); + + MethodDecl readsTrue = new MethodDecl(new BaseType(Primitives.BOOL), "readsTrue", getEmptyParameters(), + readsTrueBlock); + + MethodDecl readsFalse = new MethodDecl(new BaseType(Primitives.BOOL), "readsFalse", + getEmptyParameters(), + readsFalseBlock); + + MethodDecl readsTrueAndFalse = new MethodDecl(new BaseType(Primitives.BOOL), "readsTrueAndFalse", + getEmptyParameters(), readsTrueAndFalseBlock); + + MethodDecl readsInt = new MethodDecl(new BaseType(Primitives.INT), "readsInt", getEmptyParameters(), + readsIntBlock); + + MethodDecl readsIntAndInt = new MethodDecl(new BaseType(Primitives.INT), "readsIntAndInt", + getEmptyParameters(), + readsIntAndIntBlock); + + MethodDecl readsChar = new MethodDecl(new BaseType(Primitives.CHAR), "readsChar", getEmptyParameters(), + readsCharBlock); + + var methods = expectedAst.getClasses().firstElement().getMethodDeclarations(); + + methods.add(readsTrue); + methods.add(readsFalse); + methods.add(readsTrueAndFalse); + methods.add(readsInt); + methods.add(readsIntAndInt); + methods.add(readsChar); + + expectedAst.getClasses().firstElement().getConstructorDeclarations().add(new ConstructorDecl()); + + return expectedAst; + + } + + public static Program getSystemOutPrintlnTast() { + Program expectedAst = getEmptyProgram("SystemOutPrintln"); + var iv = new InstVar(new ReferenceType("java/io/PrintStream"), + new LocalOrFieldVar(new ReferenceType("java/lang/System"), "System"), "out"); + iv.setAccessModifier(AccessModifier.PUBLIC_STATIC); + Block block = getBlock( + new MethodCall(new BaseType(Primitives.VOID), + iv, + "println", + getArguments(new IntegerExpr(1)))); + + var method = new MethodDecl(new BaseType(Primitives.VOID), "foo", getEmptyParameters(), block); + + expectedAst.getClasses().firstElement().getMethodDeclarations().add(method); + + expectedAst.getClasses().firstElement().getConstructorDeclarations().add(new ConstructorDecl()); + + return expectedAst; + } + + public static Program getSystemOutPrintlnAst() { + Program expectedAst = getEmptyProgram("SystemOutPrintln"); + + Block block = getBlock( + new MethodCall(new InstVar(new LocalOrFieldVar("System"), "out"), "println", + getArguments(new IntegerExpr(1)))); + + var method = new MethodDecl(new BaseType(Primitives.VOID), "foo", getEmptyParameters(), block); + + expectedAst.getClasses().firstElement().getMethodDeclarations().add(method); + + expectedAst.getClasses().firstElement().getConstructorDeclarations().add(new ConstructorDecl()); + + return expectedAst; + } + + public static Program getSystemOutPrintStringAst() { + Program expectedAst = getEmptyProgram("SystemOutPrintlnString"); + + Block block = getBlock( + new MethodCall(new InstVar(new LocalOrFieldVar("System"), "out"), "println", + getArguments(new StringExpr("Das ist ein String")))); + + var method = new MethodDecl(new BaseType(Primitives.VOID), "foo", getEmptyParameters(), block); + + expectedAst.getClasses().firstElement().getMethodDeclarations().add(method); + + expectedAst.getClasses().firstElement().getConstructorDeclarations().add(new ConstructorDecl()); + + return expectedAst; + } + + public static Program getSystemOutPrintStringTast() { + Program expectedAst = getEmptyProgram("SystemOutPrintlnString"); + var iv = new InstVar(new ReferenceType("java/io/PrintStream"), + new LocalOrFieldVar(new ReferenceType("java/lang/System"), "System"), "out"); + iv.setAccessModifier(AccessModifier.PUBLIC_STATIC); + Block block = getBlock( + new MethodCall(new BaseType(Primitives.VOID), + iv, + "println", + getArguments(new StringExpr("Das ist ein String")))); + + var method = new MethodDecl(new BaseType(Primitives.VOID), "foo", getEmptyParameters(), block); + + expectedAst.getClasses().firstElement().getMethodDeclarations().add(method); + + expectedAst.getClasses().firstElement().getConstructorDeclarations().add(new ConstructorDecl()); + + return expectedAst; + } + + public static Program getMainMethodTestAst() { + Program expectedAst = getEmptyProgram("MainMethodTest"); + Block block = getBlock( + new MethodCall(new InstVar(new LocalOrFieldVar("System"), "out"), "println", + getArguments(new StringExpr("maintest")))); + + var method = new MainMethodDecl(block); + + expectedAst.getClasses().firstElement().getMethodDeclarations().add(method); + + expectedAst.getClasses().firstElement().getConstructorDeclarations().add(new ConstructorDecl()); + + return expectedAst; + } + + public static Program getMainMethodTestTast() { + Program expectedAst = getEmptyProgram("MainMethodTest"); + var iv = new InstVar(new ReferenceType("java/io/PrintStream"), + new LocalOrFieldVar(new ReferenceType("java/lang/System"), "System"), "out"); + iv.setAccessModifier(AccessModifier.PUBLIC_STATIC); + Block block = getBlock( + new MethodCall(new BaseType(Primitives.VOID), + iv, + "println", + getArguments(new StringExpr("maintest")))); + + var method = new MainMethodDecl(block); + + expectedAst.getClasses().firstElement().getMethodDeclarations().add(method); + + expectedAst.getClasses().firstElement().getConstructorDeclarations().add(new ConstructorDecl()); + + return expectedAst; + } + + public static Program getForTestAst() { + Program expectedAst = getEmptyProgram("ForTest"); + Block forBlock = getBlock(new MethodCall(new InstVar(new LocalOrFieldVar("System"), "out"), "println", + getArguments(new LocalOrFieldVar("i")))); + Block block = getBlock( + new ForStmt(new LocalVarDecl(new BaseType(Primitives.INT), "i", new IntegerExpr(0)), + new Binary(new LocalOrFieldVar("i"), new IntegerExpr(10), + Operator.LESS), + new Assign(new LocalOrFieldVar("i"), + new Binary(new LocalOrFieldVar("i"), new IntegerExpr(1), + Operator.PLUS)), + forBlock)); + + var method = new MethodDecl(new BaseType(Primitives.VOID), "foo", getEmptyParameters(), block); + + expectedAst.getClasses().firstElement().getMethodDeclarations().add(method); + + expectedAst.getClasses().firstElement().getConstructorDeclarations().add(new ConstructorDecl()); + + return expectedAst; + } + + public static Program getForTestTast() { + Program expectedAst = getEmptyProgram("ForTest"); + var iv = new InstVar(new ReferenceType("java/io/PrintStream"), + new LocalOrFieldVar(new ReferenceType("java/lang/System"), "System"), "out"); + iv.setAccessModifier(AccessModifier.PUBLIC_STATIC); + Block forBlock = getBlock(new MethodCall(new BaseType(Primitives.VOID), + iv, + "println", + getArguments(new LocalOrFieldVar(new BaseType(Primitives.INT), "i")))); + Block block = getBlock( + new ForStmt(new LocalVarDecl(new BaseType(Primitives.INT), "i", new IntegerExpr(0)), + new Binary(new BaseType(Primitives.BOOL), + new LocalOrFieldVar(new BaseType(Primitives.INT), "i"), + new IntegerExpr(10), + Operator.LESS), + new Assign(new BaseType(Primitives.INT), + new LocalOrFieldVar(new BaseType(Primitives.INT), "i"), + new Binary(new BaseType(Primitives.INT), + new LocalOrFieldVar(new BaseType( + Primitives.INT), "i"), + new IntegerExpr(1), + Operator.PLUS)), + forBlock)); + var method = new MethodDecl(new BaseType(Primitives.VOID), "foo", getEmptyParameters(), block); + + expectedAst.getClasses().firstElement().getMethodDeclarations().add(method); + + expectedAst.getClasses().firstElement().getConstructorDeclarations().add(new ConstructorDecl()); + + return expectedAst; + } + + public static Program getIncTestAst() { + Program expectedAst = getEmptyProgram("IncTest"); + Block forBlock = getBlock(new MethodCall(new InstVar(new LocalOrFieldVar("System"), "out"), "println", + getArguments(new LocalOrFieldVar("i")))); + Block blockfoo = getBlock( + new ForStmt(new LocalVarDecl(new BaseType(Primitives.INT), "i", new IntegerExpr(0)), + new Binary(new LocalOrFieldVar("i"), new IntegerExpr(10), + Operator.LESS), + new CrementStmtExpr(new LocalOrFieldVar("i"), Operator.INCSUF), + forBlock)); + + Block blockbar = getBlock( + new ForStmt(new LocalVarDecl(new BaseType(Primitives.INT), "i", new IntegerExpr(0)), + new Binary(new LocalOrFieldVar("i"), new IntegerExpr(10), + Operator.LESS), + new CrementStmtExpr(new LocalOrFieldVar("i"), Operator.INCPRE), + forBlock)); + + var foo = new MethodDecl(new BaseType(Primitives.VOID), "foo", getEmptyParameters(), blockfoo); + + var bar = new MethodDecl(new BaseType(Primitives.VOID), "bar", getEmptyParameters(), blockbar); + + expectedAst.getClasses().firstElement().getMethodDeclarations().add(foo); + expectedAst.getClasses().firstElement().getMethodDeclarations().add(bar); + + expectedAst.getClasses().firstElement().getConstructorDeclarations().add(new ConstructorDecl()); + + return expectedAst; + } + + public static Program getIncTestTast() { + Program expectedAst = getEmptyProgram("IncTest"); + var iv = new InstVar(new ReferenceType("java/io/PrintStream"), + new LocalOrFieldVar(new ReferenceType("java/lang/System"), "System"), "out"); + iv.setAccessModifier(AccessModifier.PUBLIC_STATIC); + Block forBlock = getBlock(new MethodCall(new BaseType(Primitives.VOID), + iv, + "println", + getArguments(new LocalOrFieldVar(new BaseType(Primitives.INT), "i")))); + Block fooblock = getBlock( + new ForStmt(new LocalVarDecl(new BaseType(Primitives.INT), "i", new IntegerExpr(0)), + new Binary(new BaseType(Primitives.BOOL), + new LocalOrFieldVar(new BaseType(Primitives.INT), "i"), + new IntegerExpr(10), + Operator.LESS), + new CrementStmtExpr(new BaseType(Primitives.INT), + new LocalOrFieldVar(new BaseType(Primitives.INT), "i"), + Operator.INCSUF), + forBlock)); + Block barblock = getBlock( + new ForStmt(new LocalVarDecl(new BaseType(Primitives.INT), "i", new IntegerExpr(0)), + new Binary(new BaseType(Primitives.BOOL), + new LocalOrFieldVar(new BaseType(Primitives.INT), "i"), + new IntegerExpr(10), + Operator.LESS), + new CrementStmtExpr(new BaseType(Primitives.INT), + new LocalOrFieldVar(new BaseType(Primitives.INT), "i"), + Operator.INCPRE), + forBlock)); + var foo = new MethodDecl(new BaseType(Primitives.VOID), "foo", getEmptyParameters(), fooblock); + var bar = new MethodDecl(new BaseType(Primitives.VOID), "bar", getEmptyParameters(), barblock); + + expectedAst.getClasses().firstElement().getMethodDeclarations().add(foo); + expectedAst.getClasses().firstElement().getMethodDeclarations().add(bar); + + expectedAst.getClasses().firstElement().getConstructorDeclarations().add(new ConstructorDecl()); + + return expectedAst; + } + + public static Program getDecTestAst() { + Program expectedAst = getEmptyProgram("DecTest"); + Block forBlock = getBlock(new MethodCall(new InstVar(new LocalOrFieldVar("System"), "out"), "println", + getArguments(new LocalOrFieldVar("i")))); + Block blockfoo = getBlock( + new ForStmt(new LocalVarDecl(new BaseType(Primitives.INT), "i", new IntegerExpr(10)), + new Binary(new LocalOrFieldVar("i"), new IntegerExpr(0), + Operator.GREATER), + new CrementStmtExpr(new LocalOrFieldVar("i"), Operator.DECSUF), + forBlock)); + + Block blockbar = getBlock( + new ForStmt(new LocalVarDecl(new BaseType(Primitives.INT), "i", new IntegerExpr(10)), + new Binary(new LocalOrFieldVar("i"), new IntegerExpr(0), + Operator.GREATER), + new CrementStmtExpr(new LocalOrFieldVar("i"), Operator.DECPRE), + forBlock)); + + var foo = new MethodDecl(new BaseType(Primitives.VOID), "foo", getEmptyParameters(), blockfoo); + + var bar = new MethodDecl(new BaseType(Primitives.VOID), "bar", getEmptyParameters(), blockbar); + + expectedAst.getClasses().firstElement().getMethodDeclarations().add(foo); + expectedAst.getClasses().firstElement().getMethodDeclarations().add(bar); + + expectedAst.getClasses().firstElement().getConstructorDeclarations().add(new ConstructorDecl()); + + return expectedAst; + } + + public static Program getDecTestTast() { + Program expectedAst = getEmptyProgram("DecTest"); + var iv = new InstVar(new ReferenceType("java/io/PrintStream"), + new LocalOrFieldVar(new ReferenceType("java/lang/System"), "System"), "out"); + iv.setAccessModifier(AccessModifier.PUBLIC_STATIC); + Block forBlock = getBlock(new MethodCall(new BaseType(Primitives.VOID), + iv, + "println", + getArguments(new LocalOrFieldVar(new BaseType(Primitives.INT), "i")))); + Block fooblock = getBlock( + new ForStmt(new LocalVarDecl(new BaseType(Primitives.INT), "i", new IntegerExpr(10)), + new Binary(new BaseType(Primitives.BOOL), + new LocalOrFieldVar(new BaseType(Primitives.INT), "i"), + new IntegerExpr(0), + Operator.GREATER), + new CrementStmtExpr(new BaseType(Primitives.INT), + new LocalOrFieldVar(new BaseType(Primitives.INT), "i"), + Operator.DECSUF), + forBlock)); + Block barblock = getBlock( + new ForStmt(new LocalVarDecl(new BaseType(Primitives.INT), "i", new IntegerExpr(10)), + new Binary(new BaseType(Primitives.BOOL), + new LocalOrFieldVar(new BaseType(Primitives.INT), "i"), + new IntegerExpr(0), + Operator.GREATER), + new CrementStmtExpr(new BaseType(Primitives.INT), + new LocalOrFieldVar(new BaseType(Primitives.INT), "i"), + Operator.DECPRE), + forBlock)); + var foo = new MethodDecl(new BaseType(Primitives.VOID), "foo", getEmptyParameters(), fooblock); + var bar = new MethodDecl(new BaseType(Primitives.VOID), "bar", getEmptyParameters(), barblock); + + expectedAst.getClasses().firstElement().getMethodDeclarations().add(foo); + expectedAst.getClasses().firstElement().getMethodDeclarations().add(bar); + + expectedAst.getClasses().firstElement().getConstructorDeclarations().add(new ConstructorDecl()); + + return expectedAst; + } + +} diff --git a/src/test/java/Helper/ReflectLoader.java b/src/test/java/Helper/ReflectLoader.java new file mode 100644 index 0000000..4570553 --- /dev/null +++ b/src/test/java/Helper/ReflectLoader.java @@ -0,0 +1,104 @@ +package Helper; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +import common.Compiler; +import syntaxtree.structure.Program; + +public class ReflectLoader extends ClassLoader { + private byte[] byteCode; + private Map byteCodes; + private Map> classes = new HashMap<>(); + + public ReflectLoader(byte[] byteCode) { + byteCodes = new HashMap<>(); + this.byteCode = byteCode; + } + + public ReflectLoader(String fileName) { + Program program = Resources.getProgram(fileName); + Program tast = Compiler.getFactory().getTastAdapter().getTast(program); + var bc = Compiler.getFactory().getProgramGenerator().generateBytecode(tast); + this.byteCodes = bc; + } + + /** + * @param fileName + * @param className + * @return Class + * @throws Exception + */ + public static Class getClass(String fileName, String className) throws Exception { + ReflectLoader loader = new ReflectLoader(fileName); + return loader.findClass(className); + } + + public ReflectLoader(Map byteCodes) { + this.byteCodes = byteCodes; + } + + /** + * @param name + * @return Class + */ + @Override + public Class findClass(String name) { + if (!byteCodes.containsKey(name)) { + if (byteCode != null) { + byteCodes.put(name, byteCode); + byteCode = null; + } else { + return null; + } + } + if (classes.containsKey(name)) { + return classes.get(name); + } else { + Class clazz = defineClass(name, byteCodes.get(name), 0, byteCodes.get(name).length); + classes.put(name, clazz); + return clazz; + } + } + + /** + * @param className + * @param method + * @param parameterTypes + * @return Method + * @throws NoSuchMethodException + */ + public Method getMethod(String className, String method, Class... parameterTypes) throws NoSuchMethodException { + Method method1 = findClass(className).getDeclaredMethod(method, parameterTypes); + method1.setAccessible(true); + return method1; + } + + /** + * @param className + * @param field + * @return Field + * @throws NoSuchFieldException + */ + public Field getField(String className, String field) throws NoSuchFieldException { + Field field1 = findClass(className).getDeclaredField(field); + field1.setAccessible(true); + return field1; + } + + /** + * @param classname + * @param parameterTyped + * @return Constructor + * @throws NoSuchMethodException + */ + public Constructor getConstructor(String classname, Class... parameterTyped) throws NoSuchMethodException { + Constructor constructor = findClass(classname).getDeclaredConstructor(parameterTyped); + constructor.setAccessible(true); + return constructor; + } + +} diff --git a/src/test/java/Helper/Resources.java b/src/test/java/Helper/Resources.java new file mode 100644 index 0000000..4ab9584 --- /dev/null +++ b/src/test/java/Helper/Resources.java @@ -0,0 +1,42 @@ +package Helper; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; + +import common.Compiler; +import syntaxtree.structure.Program; + +public class Resources { + + /** + * @param fileName + * @return Program + */ + public static Program getProgram(String fileName) { + return Compiler.getFactory().getAstAdapter().getAst(getFileAsStream(fileName)); + } + + /** + * @param fileName + * @return InputStream + */ + public static InputStream getFileAsStream(String fileName) { + ClassLoader classLoader = Resources.class.getClassLoader(); + File file = new File(classLoader.getResource(fileName).getFile()); + assertNotNull(file); + try { + return new FileInputStream(file); + } catch (FileNotFoundException e) { + e.printStackTrace(); + fail(); + } + + throw new IllegalStateException(); + } + +} diff --git a/src/test/java/TAST/TestRunner.java b/src/test/java/TAST/TestRunner.java new file mode 100644 index 0000000..31deab6 --- /dev/null +++ b/src/test/java/TAST/TestRunner.java @@ -0,0 +1,324 @@ +package TAST; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.io.FileNotFoundException; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +import Helper.MockGenerator; +import Helper.Resources; +import common.AccessModifier; +import common.BaseType; +import common.Compiler; +import common.Primitives; +import common.PrintableVector; +import semantic.exceptions.SemanticError; +import syntaxtree.structure.ClassDecl; +import syntaxtree.structure.ConstructorDecl; +import syntaxtree.structure.FieldDecl; +import syntaxtree.structure.Program; + +@DisplayName("Typed Abstract Syntax Generation") +public class TestRunner { + + /** + * @throws FileNotFoundException + */ + @Test + @DisplayName("EmptyClass") + void emptyClass() throws FileNotFoundException { + + ClassDecl emptyClass = new ClassDecl("EmptyClass", new PrintableVector<>(), new PrintableVector<>(), + new PrintableVector<>()); + PrintableVector classDecls = new PrintableVector<>(); + classDecls.add(emptyClass); + var ast = new Program(classDecls); + var tast = ast; + + var generatedTast = Compiler.getFactory().getTastAdapter().getTast(ast); + + assertEquals(tast, generatedTast); + + } + + @Test + @DisplayName("ClassFields") + void classFields() { + + Program expectedAst = MockGenerator.getEmptyProgram("ClassFields"); + + FieldDecl autoAccess = new FieldDecl(AccessModifier.PACKAGE_PRIVATE, new BaseType(Primitives.INT), + "autoAccess"); + FieldDecl privateField = new FieldDecl(AccessModifier.PRIVATE, new BaseType(Primitives.INT), "private"); + FieldDecl publicField = new FieldDecl(AccessModifier.PUBLIC, new BaseType(Primitives.INT), "public"); + FieldDecl protectedField = new FieldDecl(AccessModifier.PROTECTED, new BaseType(Primitives.INT), "protected"); + + PrintableVector fields = expectedAst.getClasses().firstElement().getFieldDelcarations(); + fields.add(autoAccess); + fields.add(privateField); + fields.add(publicField); + fields.add(protectedField); + + var generatedAst = Compiler.getFactory().getTastAdapter().getTast(expectedAst); + + assertEquals(expectedAst, generatedAst); + } + + @Test + @DisplayName("ClassField without AccessModifier") + void classFieldWithoutAccessModifier() { + + Program expectedTast = MockGenerator.getAutoClassFieldTast(); + Program generatedTast = Compiler.getFactory().getTastAdapter().getTast(expectedTast); + + assertEquals(expectedTast, generatedTast); + } + + @Test + @DisplayName("EmptyClassWithConstructor") + void emptyClassWithConstructor() { + PrintableVector constructors = new PrintableVector<>(); + constructors.add(new ConstructorDecl()); + ClassDecl classDecl = new ClassDecl("EmptyClassWithConstructor", new PrintableVector<>(), constructors, + new PrintableVector<>()); + PrintableVector classDecls = new PrintableVector<>(); + classDecls.add(classDecl); + var ast = new Program(classDecls); + + var generatedTast = Compiler.getFactory().getTastAdapter().getTast(ast); + var tast = ast; + assertEquals(tast, generatedTast); + + } + + @Test + @DisplayName("Constructor With Parameters") + void constructorWithParameters() { + Program generatedTast = Compiler.getFactory().getTastAdapter() + .getTast(MockGenerator.getConstructorParameterAst()); + Program expectedTast = MockGenerator.getConstructorParameterTast(); + + assertEquals(expectedTast, generatedTast); + } + + @Test + @DisplayName("Constructor With this. assign body") + void constructorWithThisAssignBody() { + Program generatedTast = Compiler.getFactory().getTastAdapter() + .getTast(MockGenerator.getConstructorThisDotAst()); + Program expectedTast = MockGenerator.getConstructorThisDotTast(); + + assertEquals(expectedTast, generatedTast); + } + + @Test + @DisplayName("VoidMethod") + void voidMethod() { + Program generatedTast = Compiler.getFactory().getTastAdapter().getTast(MockGenerator.getVoidMethodAst()); + + Program expectedTast = MockGenerator.getVoidMethodTast(); + + assertEquals(expectedTast, generatedTast); + } + + @Test + @DisplayName("RealConstructor") + void realConstructor() { + Program generatedTast = Compiler.getFactory().getTastAdapter().getTast(MockGenerator.getRealConstructorAst()); + + Program expectedTast = MockGenerator.getRealConstructorTast(); + + assertEquals(expectedTast, generatedTast); + } + + @Test + @DisplayName("MethodCall") + void methodCall() { + Program generatedTast = Compiler.getFactory().getTastAdapter().getTast(MockGenerator.getMethodCallAst()); + + Program expectedTast = MockGenerator.getMethodCallTast(); + + assertEquals(expectedTast, generatedTast); + } + + @Test + @DisplayName("MultipleFields") + @Tag("expectfail") + void multipleFields() { + Program program = Resources.getProgram("FailTests/MultiFieldDecl.java"); + System.err.print(assertThrows( + SemanticError.class, + () -> Compiler.getFactory().getTastAdapter().getTast(program), + "Expected SemanticError to be thrown").getMessage()); + + } + + @Test + @DisplayName("MismatchingReturnType") + @Tag("expectfail") + void mismatchingReturnType() { + Program program = Resources.getProgram("FailTests/MismatchingReturnType.java"); + System.err.print(assertThrows( + SemanticError.class, + () -> Compiler.getFactory().getTastAdapter().getTast(program), + "Expected SemanticError to be thrown").getMessage()); + + } + + @Test + @DisplayName("WhileTest") + void whileTest() { + Program program = Resources.getProgram("SimpleTests/WhileTest.java"); + Compiler.getFactory().getTastAdapter().getTast(program); + + } + + @Test + @DisplayName("WhileFailTest") + void whileFailTest() { + Program program = Resources.getProgram("FailTests/WhileBool.java"); + System.err.print(assertThrows( + SemanticError.class, + () -> Compiler.getFactory().getTastAdapter().getTast(program), + "Expected SemanticError to be thrown").getMessage()); + + } + + @Test + @DisplayName("ScopeFailTest") + void scopeFailTest() { + Program program = Resources.getProgram("FailTests/ScopeTest.java"); + System.err.print(assertThrows( + SemanticError.class, + () -> Compiler.getFactory().getTastAdapter().getTast(program), + "Expected SemanticError to be thrown").getMessage()); + + } + + @Test + @DisplayName("AssignFailTest") + void assignFailTest() { + Program program = Resources.getProgram("FailTests/AssignWrongType.java"); + System.err.print(assertThrows( + SemanticError.class, + () -> Compiler.getFactory().getTastAdapter().getTast(program), + "Expected SemanticError to be thrown").getMessage()); + + } + + @Test + @DisplayName("LocalVarDeclaration with wrong init-Type") + void localVarDeclInitFail() { + Program program = Resources.getProgram("FailTests/LocalVarWrongInit.java"); + System.err.print(assertThrows( + SemanticError.class, + () -> Compiler.getFactory().getTastAdapter().getTast(program), + "Expected SemanticError to be thrown").getMessage()); + + } + + @Test + @DisplayName("ExplicitNullAssign") + void explicitNullAssign() { + Program program = Resources.getProgram("SimpleTests/ExplicitNullAssign.java"); + Compiler.getFactory().getTastAdapter().getTast(program); + } + + @Test + @DisplayName("SelfReference") + void selfReference() { + Program generatedTast = Compiler.getFactory().getTastAdapter().getTast(MockGenerator.getSelfReferenceAst()); + + Program expectedTast = MockGenerator.getSelfReferenceTast(); + + assertEquals(expectedTast, generatedTast); + } + + @Test + @DisplayName("SystemOutPrintln-Test") + void systemOutPrintlnTest() { + Program generatedTast = Compiler.getFactory().getTastAdapter().getTast(MockGenerator.getSystemOutPrintlnAst()); + Program expectedTast = MockGenerator.getSystemOutPrintlnTast(); + + assertEquals(expectedTast, generatedTast); + } + + @Test + @DisplayName("FieldAccessTests") + void fieldAccessTests() { + Program program = Resources.getProgram("FailTests/FieldAccessTests.java"); + System.err.print(assertThrows( + SemanticError.class, + () -> Compiler.getFactory().getTastAdapter().getTast(program), + "Expected SemanticError to be thrown").getMessage()); + + } + + @Test + @DisplayName("MethodAccessTests") + void methodAccessTests() { + Program program = Resources.getProgram("FailTests/MethodAccessTests.java"); + System.err.print(assertThrows( + SemanticError.class, + () -> Compiler.getFactory().getTastAdapter().getTast(program), + "Expected SemanticError to be thrown").getMessage()); + + } + + @Test + @DisplayName("DuplicateMethod") + void duplicateMethod() { + Program program = Resources.getProgram("FailTests/DuplicateMethod.java"); + System.err.print(assertThrows( + SemanticError.class, + () -> Compiler.getFactory().getTastAdapter().getTast(program), + "Expected SemanticError to be thrown").getMessage()); + + } + + @Test + @DisplayName("SystemOutPrintln-String-Test") + void systemOutPrintlnStringTest() { + Program generatedTast = Compiler.getFactory().getTastAdapter() + .getTast(MockGenerator.getSystemOutPrintStringAst()); + Program expectedTast = MockGenerator.getSystemOutPrintStringTast(); + assertEquals(expectedTast, generatedTast); + } + + @Test + @DisplayName("MainMethodTest") + void mainMethodTest() { + Program generatedTast = Compiler.getFactory().getTastAdapter().getTast(MockGenerator.getMainMethodTestAst()); + Program expectedTast = MockGenerator.getMainMethodTestTast(); + assertEquals(expectedTast, generatedTast); + } + + @Test + @DisplayName("ForLoopTest") + void forLoopTest() { + Program generatedTast = Compiler.getFactory().getTastAdapter().getTast(MockGenerator.getForTestAst()); + Program expectedTast = MockGenerator.getForTestTast(); + assertEquals(expectedTast, generatedTast); + } + + @Test + @DisplayName("IncTest") + void incTest() { + Program generatedTast = Compiler.getFactory().getTastAdapter().getTast(MockGenerator.getIncTestAst()); + Program expectedTast = MockGenerator.getIncTestTast(); + assertEquals(expectedTast, generatedTast); + } + + @Test + @DisplayName("DecTest") + void decTest() { + Program generatedTast = Compiler.getFactory().getTastAdapter().getTast(MockGenerator.getDecTestAst()); + Program expectedTast = MockGenerator.getDecTestTast(); + assertEquals(expectedTast, generatedTast); + } + +} diff --git a/src/test/java/TestSuite.java b/src/test/java/TestSuite.java new file mode 100644 index 0000000..82821d8 --- /dev/null +++ b/src/test/java/TestSuite.java @@ -0,0 +1,10 @@ +import org.junit.platform.suite.api.SelectClasses; +import org.junit.platform.suite.api.Suite; +import org.junit.platform.suite.api.SuiteDisplayName; + +@SelectClasses({AST.TestRunner.class, TAST.TestRunner.class, CodeGen.TestRunner.class, All.TestRunner.class}) + +@Suite +@SuiteDisplayName("House of Compiler") +public class TestSuite { +} diff --git a/src/test/java/initialTest/initialTest.java b/src/test/java/initialTest/initialTest.java new file mode 100644 index 0000000..8883cf2 --- /dev/null +++ b/src/test/java/initialTest/initialTest.java @@ -0,0 +1,12 @@ +package initialTest; +import org.junit.Test; +import static org.junit.Assert.assertEquals; + +public class initialTest { + + @Test + public void testSomething() { + //MyClass myClass = new MyClass(); + assertEquals(1, 1); + } +} diff --git a/src/test/resources/Comments.java b/src/test/resources/Comments.java new file mode 100644 index 0000000..18610ef --- /dev/null +++ b/src/test/resources/Comments.java @@ -0,0 +1,19 @@ +class Comments{ + + private int lorem; + + // One Line Comment!!!!! IGNORE THAT + + private boolean ipsum; + + /* + MULT-LINE COMMENT! IGNORE THIS + */ + + /** + * + * Should be ignored + * + */ + +} \ No newline at end of file diff --git a/src/test/resources/EmptyClassWithConstructor.java b/src/test/resources/EmptyClassWithConstructor.java new file mode 100644 index 0000000..257b084 --- /dev/null +++ b/src/test/resources/EmptyClassWithConstructor.java @@ -0,0 +1,7 @@ +class EmptyClassWithConstructor{ + + public EmptyClassWithConstructor(){ + + } + +} \ No newline at end of file diff --git a/src/test/resources/EmtpyClass.java b/src/test/resources/EmtpyClass.java new file mode 100644 index 0000000..d8a3350 --- /dev/null +++ b/src/test/resources/EmtpyClass.java @@ -0,0 +1 @@ +class EmptyClass{} \ No newline at end of file diff --git a/src/test/resources/FailTests/AssignWrongType.java b/src/test/resources/FailTests/AssignWrongType.java new file mode 100644 index 0000000..e9dfd23 --- /dev/null +++ b/src/test/resources/FailTests/AssignWrongType.java @@ -0,0 +1,11 @@ +package FailTests; + +class AssignWrongType { + + int test() { + int x = 1; + x = true; + return x; + } + +} diff --git a/src/test/resources/FailTests/BoolAssignedInt.java b/src/test/resources/FailTests/BoolAssignedInt.java new file mode 100644 index 0000000..6e022e4 --- /dev/null +++ b/src/test/resources/FailTests/BoolAssignedInt.java @@ -0,0 +1,9 @@ +package FailTests; + +class BoolAssignedInt { + + void foo() { + boolean bool = 10; + } + +} diff --git a/src/test/resources/FailTests/DivideByZero.java b/src/test/resources/FailTests/DivideByZero.java new file mode 100644 index 0000000..04cdeef --- /dev/null +++ b/src/test/resources/FailTests/DivideByZero.java @@ -0,0 +1,9 @@ +package FailTests; + +class DivideByZero { + + public static void main(String[] args) { + int a = 1 / 0; + } + +} diff --git a/src/test/resources/FailTests/DuplicateFieldDeclaration.java b/src/test/resources/FailTests/DuplicateFieldDeclaration.java new file mode 100644 index 0000000..20daca4 --- /dev/null +++ b/src/test/resources/FailTests/DuplicateFieldDeclaration.java @@ -0,0 +1,6 @@ +package FailTests; + +class DuplicateFieldDeclaration { + char i; + int i; +} diff --git a/src/test/resources/FailTests/DuplicateMethod.java b/src/test/resources/FailTests/DuplicateMethod.java new file mode 100644 index 0000000..5ca1f3e --- /dev/null +++ b/src/test/resources/FailTests/DuplicateMethod.java @@ -0,0 +1,9 @@ +package FailTests; + +class DuplicateMethod { + + public void test() { } + + public void test() { } + +} diff --git a/src/test/resources/FailTests/FaultyForLoop.java b/src/test/resources/FailTests/FaultyForLoop.java new file mode 100644 index 0000000..17d5486 --- /dev/null +++ b/src/test/resources/FailTests/FaultyForLoop.java @@ -0,0 +1,11 @@ +package FailTests; + +class FaultyForLoop { + int foo() { + int x; + for (x == true; ;) { + return 4324; + } + + } +} \ No newline at end of file diff --git a/src/test/resources/FailTests/MethodAccessTests.java b/src/test/resources/FailTests/MethodAccessTests.java new file mode 100644 index 0000000..6bba4fa --- /dev/null +++ b/src/test/resources/FailTests/MethodAccessTests.java @@ -0,0 +1,18 @@ +package FailTests; + +class MethodAccessTests { + + void MethodAccesTestMethod() { + DontTouchMe clazz = new DontTouchMe(); + DontTouchMeMethod(); + } + +} + +class DontTouchMe { + + public void DontTouchMeMethod() { + + } + +} diff --git a/src/test/resources/FailTests/MismatchingReturnType.java b/src/test/resources/FailTests/MismatchingReturnType.java new file mode 100644 index 0000000..25bbb80 --- /dev/null +++ b/src/test/resources/FailTests/MismatchingReturnType.java @@ -0,0 +1,9 @@ +package FailTests; + +class MismatchingReturnType { + + char foo(){ + return 69; + } + +} diff --git a/src/test/resources/FailTests/ScopeTest.java b/src/test/resources/FailTests/ScopeTest.java new file mode 100644 index 0000000..7f59de1 --- /dev/null +++ b/src/test/resources/FailTests/ScopeTest.java @@ -0,0 +1,23 @@ +package FailTests; + +class ScopeTest { + + int returnDoesntExist() { + int x = 1; + { + int y = 1; + } + return y; + } + + int varInMethodDoesntExist() { + int x = 1; + { + int y = 1; + int x = 2; + } + int y = 1; + return y; + } + +} diff --git a/src/test/resources/IntegerWrapper.java b/src/test/resources/IntegerWrapper.java new file mode 100644 index 0000000..b6c213f --- /dev/null +++ b/src/test/resources/IntegerWrapper.java @@ -0,0 +1,20 @@ +class IntegerWrapper{ + + public int i; + + public IntegerWrapper(){ + this.i = 0; + } + + public IntegerWrapper(int i) { + this.i = i; + } + + public IntegerWrapper add(IntegerWrapper j){ return new IntegerWrapper(j.i+this.i);} + + public IntegerWrapper sub(IntegerWrapper j){ return new IntegerWrapper(j.i-this.i);} + + public boolean equals(IntegerWrapper j){return j.i == this.i;} + + +} \ No newline at end of file diff --git a/src/test/resources/Integration/Dijkstra.java b/src/test/resources/Integration/Dijkstra.java new file mode 100644 index 0000000..2844c29 --- /dev/null +++ b/src/test/resources/Integration/Dijkstra.java @@ -0,0 +1,366 @@ +package Integration; + +class Dijkstra { + + void main() { + Vertex v1 = new Vertex(1); + Graph g = new Graph(v1); + Vertex v2 = new Vertex(2); + Vertex v3 = new Vertex(3); + Vertex v4 = new Vertex(4); + Vertex v5 = new Vertex(5); + Vertex v6 = new Vertex(6); + Vertex v7 = new Vertex(7); + Vertex v8 = new Vertex(8); + Vertex v9 = new Vertex(9); + Vertex v10 = new Vertex(10); + Vertex v11 = new Vertex(11); + Vertex v12 = new Vertex(12); + + g.addVertex(v2); + g.addVertex(v4); + g.addVertex(v3); + g.addVertex(v5); + g.addVertex(v6); + g.addVertex(v7); + g.addVertex(v8); + g.addVertex(v9); + g.addVertex(v10); + g.addVertex(v11); + g.addVertex(v12); + + g.addEdge(v1, v2); // A-B + g.addEdge(v1, v5); // A-E + g.addEdge(v1, v10); // A-J + + g.addEdge(v2, v3); // B + g.addEdge(v2, v7); + + g.addEdge(v3, v4); // C + g.addEdge(v3, v5); + + g.addEdge(v4, v8); // D + + g.addEdge(v5, v6); // E + g.addEdge(v5, v9); + + g.addEdge(v6, v7); // F + + g.addEdge(v7, v8); // G + + g.addEdge(v8, v12); // H + g.addEdge(v8, v10); + + g.addEdge(v9, v10); // I + + g.addEdge(v10, v11); // J + + g.addEdge(v11, v12); // K + + g.getShortestPath(v1, v8); + g.getShortestPath(v1, v12); + g.getShortestPath(v4, v12); + g.getShortestPath(v4, v9); + g.getShortestPath(v6, v9); + + } + +} + +class Graph { + + private VertexSet vertexList; + + public Graph(VertexSet vertexList) { + this.vertexList = vertexList; + } + + public Graph(Vertex v1) { + this.vertexList = new VertexSet(v1); + } + + public VertexSet getVertexSet() { + return vertexList; + } + + public void addVertex(Vertex vertex) { + vertexList.add(vertex); + } + + public void addEdge(Vertex vertex1, Vertex vertex2) { + vertex1.addAdjancey(vertex2); + vertex2.addAdjancey(vertex1); + } + + public void getShortestPath(Vertex source, Vertex destination) { + VertexSet calcList = vertexList.copy(); + calcList.get(source.id).setDistance(0); + calcList.get(source.id).setPrevious(null); + Vertex current = calcList.get(source.id); + + // Fill the list with the distances + while (current != null) { + current.setVisited(true); + // Search for every adjacent vertex + VertexSet currentAdjanceyList = current.getAdjanceyList(); + if (currentAdjanceyList != null) { + for (int i = 0; i < currentAdjanceyList.size(); i = i + 1) { + Vertex adjancey = currentAdjanceyList.getFromIndex(i); + adjancey = calcList.get(adjancey.id); + if ((adjancey != null) && !adjancey.isVisited()) { + int distance = current.getDistance() + 1; + if (distance < adjancey.getDistance()) { + adjancey.setDistance(distance); + adjancey.setPrevious(current); + } + } + + } + } else { + } + current = calcList.getNextSmallestUnvisited(); + } + Vertex previous = calcList.get(destination.id); + if (previous == null) { + + return; + } + IntStack path = new IntStack(previous.id); + previous = previous.getPrevious(); + while (previous != null) { + path.push(previous.id); + previous = previous.getPrevious(); + } + +} + +class Vertex { + + public int id; + public VertexSet adjanceyList; + public int distance; + public Vertex previous; + public boolean visited; + + public Vertex(int id) { + this.id = id; + } + + public void setDistance(int distance) { + this.distance = distance; + } + + public void setPrevious(Vertex previous) { + this.previous = previous; + } + + public void setVisited(boolean visited) { + this.visited = visited; + } + + public int getDistance() { + return distance; + } + + public VertexSet getAdjanceyList() { + return adjanceyList; + } + + public Vertex getPrevious() { + return previous; + } + + public boolean isVisited() { + return visited; + } + + public Vertex(Vertex vertex) { + this.id = vertex.id; + this.adjanceyList = vertex.adjanceyList; + this.distance = 10000; // No infinity so... + this.previous = null; + this.visited = false; + } + + public void addAdjancey(Vertex v) { + if (adjanceyList == null) { + adjanceyList = new VertexSet(v); + } else { + adjanceyList.add(v); + } + } + + public Vertex copy() { + return new Vertex(this); + } + + public boolean isDirect(Vertex v) { + return adjanceyList.contains(v); + } + +} + +class VertexSet { + + private Vertex vertex; + private VertexSet next; + + public VertexSet(Vertex vertex) { + this.vertex = vertex; + this.next = null; + } + + public int size() { + int size = 1; + VertexSet v = next; + while (v != null) { + size = size + 1; + v = v.next; + } + return size; + } + + public VertexSet(VertexSet vertexList) { + this.vertex = vertexList.vertex.copy(); + if (vertexList.next != null) { + this.next = vertexList.next.copy(); + } else { + this.next = null; + } + } + + public Vertex getNextSmallestUnvisited() { + VertexSet v = this.getUnvisited(); + if (v == null) { + return null; + } else { + return v.getSmallestDistance(); + } + } + + public Vertex getSmallestDistance() { + Vertex smallest = vertex; + VertexSet v = next; + while (v != null) { + if (v.vertex.getDistance() < smallest.getDistance()) { + smallest = v.vertex; + } + v = v.next; + } + return smallest; + } + + public VertexSet getUnvisited() { + VertexSet unvisited = null; + + VertexSet current = this; + while (current != null) { + if (!current.vertex.isVisited()) { + if (unvisited == null) { + unvisited = new VertexSet(current.vertex); + } else { + unvisited.add(current.vertex); + } + } + current = current.next; + } + + return unvisited; + } + + public Vertex getFromIndex(int i) { + if (i == 0) { + return vertex; + } else { + return next.getFromIndex(i - 1); + } + } + + public void remove(Vertex v) { + if (vertex.id == v.id) { + vertex = next.vertex; + next = next.next; + } else { + if (next != null) { + next.remove(v); + } + } + } + + public boolean hasUnvisited() { + if (next != null) { + return next.hasUnvisited(); + } else { + return vertex.isVisited(); + } + } + + public VertexSet copy() { + return new VertexSet(this); + } + + public boolean contains(Vertex v) { + if (vertex.id == v.id) { + return true; + } + if (next == null) { + return false; + } + return next.contains(v); + } + + public void add(Vertex vertex) { + if (this.next == null) { + this.next = new VertexSet(vertex); + } else { + this.next.add(vertex); + } + } + + public Vertex get(int index) { + if ((vertex == null)) { + return null; + } else if (vertex.id == index) { + return this.vertex; + } else if (next != null) { + return this.next.get(index); + } else { + return null; + } + } + +} + +class IntStack { + + public int c; + public IntStack next; + public int size; + + public IntStack(int c) { + this.size = 1; + this.c = c; + this.next = null; + } + + public void push(int c) { + size = size + 1; + if (this.next == null) { + this.next = new IntStack(c); + } else { + this.next.push(c); + } + } + + public int pop() { + size = size - 1; + if (this.next.next == null) { + int temp = this.next.c; + this.next = null; + return temp; + } else { + return this.next.pop(); + } + } + +} \ No newline at end of file diff --git a/src/test/resources/Integration/LOFOI.java b/src/test/resources/Integration/LOFOI.java new file mode 100644 index 0000000..fb77773 --- /dev/null +++ b/src/test/resources/Integration/LOFOI.java @@ -0,0 +1,23 @@ +package Integration; + +// Local or Field or Imported var Test +class LOFOI { + + // This test is to determine wheter the order of finding the vars is correct + + int System; + + public LOFOI() { + System = 10; + } + + public int foo() { + int System = 20; + return System; + } + + public int bar() { + return System; + } + +} diff --git a/src/test/resources/Integration/LinkedList.java b/src/test/resources/Integration/LinkedList.java new file mode 100644 index 0000000..7289e9b --- /dev/null +++ b/src/test/resources/Integration/LinkedList.java @@ -0,0 +1,80 @@ +package Integration; + +class LinkedList { + + public int value; + public LinkedList next; + public int size; + + public LinkedList(int value) { + this.value = value; + size = 1; + } + + public int get() { + return value; + } + + public void set(int value) { + this.value = value; + } + + public LinkedList getNode(int i) { + if (i == 0) { + return this; + } else { + return this.next.getNode(i - 1); + } + } + + public void swap(int i, int j) { + int temp = getNode(i).get(); + getNode(i).set(getNode(j).get()); + getNode(j).set(temp); + } + + public void add(int value) { + size = size + 1; + if (this.next == null) { + this.next = new LinkedList(value); + + } else { + this.next.add(value); + } + } + +} + +class Executer { + + void foo() { + LinkedList list = new LinkedList(3); + list.add(2); + list.add(7); + list.add(5); + list.add(1); + list.add(8); + list.add(6); + list.add(4); + } + + LinkedList sort(LinkedList list) { + + int i = 0; + int j = 0; + while (i < list.size - 1) { + j = 0; + while (j < list.size - 1) { + if (list.getNode(j).get() > list.getNode(j + 1).get()) { + list.swap(j, j + 1); + } + j = j + 1; + } + i = i + 1; + } + + return list; + + } + +} \ No newline at end of file diff --git a/src/test/resources/Integration/Stack.java b/src/test/resources/Integration/Stack.java new file mode 100644 index 0000000..cb3ba1c --- /dev/null +++ b/src/test/resources/Integration/Stack.java @@ -0,0 +1,55 @@ +package Integration; + +class Stack { + + private int value; + private Stack next; + public int size; + + public Stack(int value) { + this.value = value; + size = 1; + } + + public int peek(int i) { + if (i == 0) { + return this.value; + } else { + return this.next.peek(i - 1); + } + } + + public void push(int value) { + size = size + 1; + if (this.next == null) { + this.next = new Stack(value); + + } else { + this.next.push(value); + } + } + + public int pop() { + size = size - 1; + if (this.next == null) { + return this.value; + } else { + return this.next.pop(); + } + } + +} + +class Executer { + + void foo() { + Stack stack = new Stack(1); + stack.push(2); + stack.push(3); + stack.push(4); + stack.push(5); + stack.push(6); + + } + +} \ No newline at end of file diff --git a/src/test/resources/Integration/StringList.java b/src/test/resources/Integration/StringList.java new file mode 100644 index 0000000..2c08950 --- /dev/null +++ b/src/test/resources/Integration/StringList.java @@ -0,0 +1,48 @@ +package Integration; + +class StringList { + + private char value; + private StringList next; + + public StringList() { + } + + public StringList(char c) { + this.value = c; + } + + public char get(int i) { + if (i == 0) { + return this.value; + } else { + return next.get(i - 1); + } + } + + public void add(char value) { + if (next == null) { + next = new StringList(value); + } else { + next.add(value); + } + } + + public int length() { + if (this.next == null) { + return 1; + } else { + return 1 + next.length(); + } + } + + public void print() { + System.out.print(this.value); + if (this.next != null) { + next.print(); + } else { + System.out.println(); + } + } + +} diff --git a/src/test/resources/NotTested/BinaryTests.java b/src/test/resources/NotTested/BinaryTests.java new file mode 100644 index 0000000..57a30c5 --- /dev/null +++ b/src/test/resources/NotTested/BinaryTests.java @@ -0,0 +1,31 @@ +package NotTested; + +class BinaryTests{ + + private int a,b,c; + + public int pvs() { + return a+b*c; + } + + public int klammern() { + return a * (b+c); + } + + public int modulo(){ + return a%b; + } + + public boolean avo() { + return a || b && c; + } + + public boolean binary() { + return a == b && !c; + } + + public int endBoss() { + return (a%c) + b / (a * a) * a + a - (c-b/a) && b-c; + } + +} \ No newline at end of file diff --git a/src/test/resources/NotTested/CharWrapper.java b/src/test/resources/NotTested/CharWrapper.java new file mode 100644 index 0000000..a18da95 --- /dev/null +++ b/src/test/resources/NotTested/CharWrapper.java @@ -0,0 +1,19 @@ +package NotTested; + +class CharWrapper{ + + private char c; + + public CharWrapper(char c){ + this.c = c; + } + + public void setChar(char c){ + this.c = c; + } + + public char getChar(){ + return this.c; + } + +} \ No newline at end of file diff --git a/src/test/resources/NotTested/ClassStress.java b/src/test/resources/NotTested/ClassStress.java new file mode 100644 index 0000000..5d189b4 --- /dev/null +++ b/src/test/resources/NotTested/ClassStress.java @@ -0,0 +1,33 @@ +package NotTested; + +class ClassStress{ + + private int x = 100; + + public ClassStress(int x){ + this.x = x*2%2+x/10 % 100*x; + } + +} + +class ClassStress2{ + + private int x = 2; + private boolean b = true; + private ClassStress cd = new ClassStress(3); + + public ClassStress2(int x, ClassStress cs, boolean b){ + this.x = x; + this.b = b; + this.cs = cs + } + + public ClassStress2(int x){ + this.x = x; + } + + public foo(){ + return new ClassStress2(1, new ClassStress(this.cd.x), this.b); + } + +} \ No newline at end of file diff --git a/src/test/resources/NotTested/Fib.java b/src/test/resources/NotTested/Fib.java new file mode 100644 index 0000000..6b82c69 --- /dev/null +++ b/src/test/resources/NotTested/Fib.java @@ -0,0 +1,16 @@ +package NotTested; + +public class Fibonacci +{ + public int fibonacci(int n) + { + if (n <= 1) + { + return n; + } + else + { + return fibonacci(n-1) + fibonacci(n-2); + } + } +} \ No newline at end of file diff --git a/src/test/resources/NotTested/FibIntegerWrapper.java b/src/test/resources/NotTested/FibIntegerWrapper.java new file mode 100644 index 0000000..52c7ad8 --- /dev/null +++ b/src/test/resources/NotTested/FibIntegerWrapper.java @@ -0,0 +1,37 @@ +package NotTested; + +class IntegerWrapper{ + + public int i; + + public IntegerWrapper(int i){ + this.i = i; + } + + public IntegerWrapper(){ + this.i = 0; + } + + public IntegerWrapper Add(IntegerWrapper j){ return new IntegerWrapper(j.i+this.i)} + + public IntegerWrapper Sub(IntegerWrapper j){ return new IntegerWrapper(j.i-this.i)} + + public boolean equals(IntegerWrapper j){return j.i == this.i} + + +} + +class Fibonacci +{ + public IntegerWrapper fibonacci(IntegerWrapper n) + { + if (n.LessThan(new IntegerWrapper(2))) + { + return n; + } + else + { + return fibonacci(n.Sub(new IntegerWrapper(1))).Add(fibonacci(n.Sub(new IntegerWrapper(2)))); + } + } +} \ No newline at end of file diff --git a/src/test/resources/NotTested/IfTest.java b/src/test/resources/NotTested/IfTest.java new file mode 100644 index 0000000..053a1a8 --- /dev/null +++ b/src/test/resources/NotTested/IfTest.java @@ -0,0 +1,30 @@ +package NotTested; + +class IfTest{ + + public int ifTest(){ + if(true){ + return 1; + } + return 0; + } + + public int ifElseTest(){ + if(true){ + return 1; + }else{ + return 0; + } + } + + public int ifElseIfTest(){ + if(false){ + return 0; + }else if(true){ + return 1; + }else{ + return 0; + } + } + +} \ No newline at end of file diff --git a/src/test/resources/NotTested/TwoClasses.java b/src/test/resources/NotTested/TwoClasses.java new file mode 100644 index 0000000..a3c7b3e --- /dev/null +++ b/src/test/resources/NotTested/TwoClasses.java @@ -0,0 +1,9 @@ +package NotTested; + +class TwoClasses{ + +} + +class TwoClasses{ + +} \ No newline at end of file diff --git a/src/test/resources/NotTested/TwoClassesReferences.java b/src/test/resources/NotTested/TwoClassesReferences.java new file mode 100644 index 0000000..3055aba --- /dev/null +++ b/src/test/resources/NotTested/TwoClassesReferences.java @@ -0,0 +1,27 @@ +package NotTested; + +class TwoClassesFilled{ + + private int i; + public int a = 4; + + public TwoClassesFilled(int i){ + this.i = i; + } + +} + + +class TwoClassesFilled2{ + + private TwoClassesFilled a; + + public TwoClassesFilled2(int a){ + this.a = new TwoClassesFilled(a); + } + + public int get(){ + return this.a.a; + } + +} \ No newline at end of file diff --git a/src/test/resources/NotTested/VoidMethod.java b/src/test/resources/NotTested/VoidMethod.java new file mode 100644 index 0000000..884726a --- /dev/null +++ b/src/test/resources/NotTested/VoidMethod.java @@ -0,0 +1,10 @@ +package NotTested; + +class VoidMethod{ + + + public void test(){ + + } + +} \ No newline at end of file diff --git a/src/test/resources/NotTested/VoidMethodReturn.java b/src/test/resources/NotTested/VoidMethodReturn.java new file mode 100644 index 0000000..5c6f9d1 --- /dev/null +++ b/src/test/resources/NotTested/VoidMethodReturn.java @@ -0,0 +1,10 @@ +package NotTested; + +class VoidMethodReturn{ + + + public void test(){ + return; + } + +} \ No newline at end of file diff --git a/src/test/resources/NotTested/WhileTest.java b/src/test/resources/NotTested/WhileTest.java new file mode 100644 index 0000000..dbb8b94 --- /dev/null +++ b/src/test/resources/NotTested/WhileTest.java @@ -0,0 +1,19 @@ +package NotTested; + +class WhileTest{ + + public void infinite(){ + while(true){} + } + + public int ten(){ + int i = 0; + int counter = 10; + while(counter>0){ + i = i+1; + counter = counter - 1; + } + return i; + } + +} \ No newline at end of file diff --git a/src/test/resources/NotTested/ggt.java b/src/test/resources/NotTested/ggt.java new file mode 100644 index 0000000..30847d0 --- /dev/null +++ b/src/test/resources/NotTested/ggt.java @@ -0,0 +1,25 @@ +package NotTested; + +class ggt{ + + private int a; + private int b; + + public ggt(int a, int b){ + this.a = a; + this.b = b; + } + + public int calculate(){ + int c; + int a = this.a; + int b = this.b; + while ( b != 0) { + c = a % b; + a = b; + b = c; + } + return a; + } + +} \ No newline at end of file diff --git a/src/test/resources/SimpleTests/AndVorOr.java b/src/test/resources/SimpleTests/AndVorOr.java new file mode 100644 index 0000000..af4cb86 --- /dev/null +++ b/src/test/resources/SimpleTests/AndVorOr.java @@ -0,0 +1,13 @@ +package SimpleTests; + +class AndVorOr { + + boolean foo(boolean a, boolean b, boolean c) { + return a && b || c && b; + } + + boolean bar(boolean a, boolean b, boolean c) { + return a || b && c || b && c; + } + +} diff --git a/src/test/resources/SimpleTests/AutoAccessModifierField.java b/src/test/resources/SimpleTests/AutoAccessModifierField.java new file mode 100644 index 0000000..3acd3d3 --- /dev/null +++ b/src/test/resources/SimpleTests/AutoAccessModifierField.java @@ -0,0 +1,7 @@ +package SimpleTests; + +class AutoAccessModifierField { + + int autoAccess; + +} diff --git a/src/test/resources/SimpleTests/CharArgument.java b/src/test/resources/SimpleTests/CharArgument.java new file mode 100644 index 0000000..3cdaf65 --- /dev/null +++ b/src/test/resources/SimpleTests/CharArgument.java @@ -0,0 +1,15 @@ +package SimpleTests; + +class CharArgument { + + char c; + + public CharArgument() { + this.c = foo('a'); + } + + char foo(char c) { + return c; + } + +} diff --git a/src/test/resources/SimpleTests/ClassFields.java b/src/test/resources/SimpleTests/ClassFields.java new file mode 100644 index 0000000..85df092 --- /dev/null +++ b/src/test/resources/SimpleTests/ClassFields.java @@ -0,0 +1,9 @@ +package SimpleTests; + +class ClassFields { + + private int privateAccess; + public int publicAccess; + protected int protectedAccess; + +} diff --git a/src/test/resources/SimpleTests/Comments.java b/src/test/resources/SimpleTests/Comments.java new file mode 100644 index 0000000..af041b0 --- /dev/null +++ b/src/test/resources/SimpleTests/Comments.java @@ -0,0 +1,21 @@ +package SimpleTests; + +class Comments{ + + private int lorem; + + // One Line Comment!!!!! IGNORE THAT + + private boolean ipsum; + + /* + MULT-LINE COMMENT! IGNORE THIS + */ + + /** + * + * Should be ignored + * + */ + +} \ No newline at end of file diff --git a/src/test/resources/SimpleTests/ConditionalEvaluation.java b/src/test/resources/SimpleTests/ConditionalEvaluation.java new file mode 100644 index 0000000..2d38734 --- /dev/null +++ b/src/test/resources/SimpleTests/ConditionalEvaluation.java @@ -0,0 +1,16 @@ +package SimpleTests; + +class ConditionalEvaluation { + + boolean foo() { + System.out.println("foo"); + return true || bar(); + } + + boolean bar() { + System.out.println("bar"); + + return true && foo(); + } + +} diff --git a/src/test/resources/SimpleTests/ConstructorParams.java b/src/test/resources/SimpleTests/ConstructorParams.java new file mode 100644 index 0000000..519ab50 --- /dev/null +++ b/src/test/resources/SimpleTests/ConstructorParams.java @@ -0,0 +1,9 @@ +package SimpleTests; + +class ConstructorParams { + + public ConstructorParams(int i) { + + } + +} \ No newline at end of file diff --git a/src/test/resources/SimpleTests/ConstructorThisDot.java b/src/test/resources/SimpleTests/ConstructorThisDot.java new file mode 100644 index 0000000..f9a4b26 --- /dev/null +++ b/src/test/resources/SimpleTests/ConstructorThisDot.java @@ -0,0 +1,11 @@ +package SimpleTests; + +class ConstructorThisDot{ + + public int i; + + public ConstructorThisDot(){ + this.i = 5; + } + +} diff --git a/src/test/resources/SimpleTests/DecTest.java b/src/test/resources/SimpleTests/DecTest.java new file mode 100644 index 0000000..d589d41 --- /dev/null +++ b/src/test/resources/SimpleTests/DecTest.java @@ -0,0 +1,17 @@ +package SimpleTests; + +class DecTest { + + void foo() { + for (int i = 10; i > 0; i--) { + System.out.println(i); + } + } + + void bar() { + for (int i = 10; i > 0; --i) { + System.out.println(i); + } + } + +} diff --git a/src/test/resources/SimpleTests/DivMethod.java b/src/test/resources/SimpleTests/DivMethod.java new file mode 100644 index 0000000..80007ed --- /dev/null +++ b/src/test/resources/SimpleTests/DivMethod.java @@ -0,0 +1,9 @@ +package SimpleTests; + +class DivMethod { + + int foo(int i){ + return i/i; + } + +} diff --git a/src/test/resources/SimpleTests/EmptyClass.java b/src/test/resources/SimpleTests/EmptyClass.java new file mode 100644 index 0000000..4bae0fa --- /dev/null +++ b/src/test/resources/SimpleTests/EmptyClass.java @@ -0,0 +1,3 @@ +package SimpleTests; + +class EmptyClass{} \ No newline at end of file diff --git a/src/test/resources/SimpleTests/EmptyClassWithConstructor.java b/src/test/resources/SimpleTests/EmptyClassWithConstructor.java new file mode 100644 index 0000000..9d54fa8 --- /dev/null +++ b/src/test/resources/SimpleTests/EmptyClassWithConstructor.java @@ -0,0 +1,9 @@ +package SimpleTests; + +class EmptyClassWithConstructor{ + + public EmptyClassWithConstructor(){ + + } + +} \ No newline at end of file diff --git a/src/test/resources/SimpleTests/ExplicitNullAssign.java b/src/test/resources/SimpleTests/ExplicitNullAssign.java new file mode 100644 index 0000000..c56eca7 --- /dev/null +++ b/src/test/resources/SimpleTests/ExplicitNullAssign.java @@ -0,0 +1,10 @@ +package SimpleTests; + +class ExplicitNullAssign { + + ExplicitNullAssign e; + + void test() { + e = null; + } +} diff --git a/src/test/resources/SimpleTests/ExtendedNotTest.java b/src/test/resources/SimpleTests/ExtendedNotTest.java new file mode 100644 index 0000000..23fc8f2 --- /dev/null +++ b/src/test/resources/SimpleTests/ExtendedNotTest.java @@ -0,0 +1,18 @@ +package SimpleTests; + +class ExtendedNotTest { + + boolean notequal(int a, int b) { + return !(a == b); + } + + boolean multiple(boolean a, boolean b) { + return !(!a || b); + } + + boolean notWithAssigns(boolean a) { + boolean b = !a; + return !b; + } + +} diff --git a/src/test/resources/SimpleTests/FieldWithExpr.java b/src/test/resources/SimpleTests/FieldWithExpr.java new file mode 100644 index 0000000..e87be59 --- /dev/null +++ b/src/test/resources/SimpleTests/FieldWithExpr.java @@ -0,0 +1,7 @@ +package SimpleTests; + +class FieldWithExpr { + + public int x = 5; + +} diff --git a/src/test/resources/SimpleTests/ForTest.java b/src/test/resources/SimpleTests/ForTest.java new file mode 100644 index 0000000..87ba856 --- /dev/null +++ b/src/test/resources/SimpleTests/ForTest.java @@ -0,0 +1,11 @@ +package SimpleTests; + +class ForTest { + + void foo() { + for (int i = 0; i < 10; i = i + 1) { + System.out.println(i); + } + } + +} diff --git a/src/test/resources/SimpleTests/FourClasses.java b/src/test/resources/SimpleTests/FourClasses.java new file mode 100644 index 0000000..7cb84e0 --- /dev/null +++ b/src/test/resources/SimpleTests/FourClasses.java @@ -0,0 +1,63 @@ +package SimpleTests; + +class FourClasses { + + public int main(int i) { + Test t = new Test(i); + Test2 t2 = new Test2(t.y); + return t2.test.test3.getX(); + } + +} + +class Test { + private int x; + public int y; + public Test3 test3; + + public Test(int i) { + this.x = i; + this.y = 10; + this.test3 = new Test3(i * 2); + } + + public Test3 getTest3() { + return this.test3; + } + + public int getX() { + return this.x; + } +} + +class Test2 { + public Test test; + + public Test2(int i) { + this.test = new Test(i); + } + +} + +class Test3 { + public int x; + + private int y; + + public Test3(int i) { + this.x = i; + } + + public int getX() { + return this.x; + } + + public int getY() { + return this.y; + } + + public void setY(int y) { + this.y = y; + } + +} \ No newline at end of file diff --git a/src/test/resources/SimpleTests/FourClassesFieldAssign.java b/src/test/resources/SimpleTests/FourClassesFieldAssign.java new file mode 100644 index 0000000..e3b6e7f --- /dev/null +++ b/src/test/resources/SimpleTests/FourClassesFieldAssign.java @@ -0,0 +1,64 @@ +package SimpleTests; + +class FourClassesFieldAssign { + + public int fieldAssign(int i) { + Test t = new Test(i); + Test2 t2 = new Test2(t.y); + t2.test.test3.x = i; + return t2.test.test3.getX(); + } + +} + +class Test { + private int x; + public int y; + public Test3 test3; + + public Test(int i) { + this.x = i; + this.y = 10; + this.test3 = new Test3(i * 2); + } + + public Test3 getTest3() { + return this.test3; + } + + public int getX() { + return this.x; + } +} + +class Test2 { + public Test test; + + public Test2(int i) { + this.test = new Test(i); + } + +} + +class Test3 { + public int x; + + private int y; + + public Test3(int i) { + this.x = i; + } + + public int getX() { + return this.x; + } + + public int getY() { + return this.y; + } + + public void setY(int y) { + this.y = y; + } + +} \ No newline at end of file diff --git a/src/test/resources/SimpleTests/FourClassesSetter.java b/src/test/resources/SimpleTests/FourClassesSetter.java new file mode 100644 index 0000000..57909eb --- /dev/null +++ b/src/test/resources/SimpleTests/FourClassesSetter.java @@ -0,0 +1,65 @@ +package SimpleTests; + +class FourClassesSetter { + + public int setFieldTest(int i) { + Test t = new Test(i); + Test2 t2 = new Test2(t.y); + t2.test.test3.setY(i); + + return t2.test.test3.getY(); + } + +} + +class Test { + private int x; + public int y; + public Test3 test3; + + public Test(int i) { + this.x = i; + this.y = 10; + this.test3 = new Test3(i * 2); + } + + public Test3 getTest3() { + return this.test3; + } + + public int getX() { + return this.x; + } +} + +class Test2 { + public Test test; + + public Test2(int i) { + this.test = new Test(i); + } + +} + +class Test3 { + public int x; + + private int y; + + public Test3(int i) { + this.x = i; + } + + public int getX() { + return this.x; + } + + public int getY() { + return this.y; + } + + public void setY(int y) { + this.y = y; + } + +} \ No newline at end of file diff --git a/src/test/resources/SimpleTests/GetterFunction.java b/src/test/resources/SimpleTests/GetterFunction.java new file mode 100644 index 0000000..c501713 --- /dev/null +++ b/src/test/resources/SimpleTests/GetterFunction.java @@ -0,0 +1,15 @@ +package SimpleTests; + +class GetterFunction { + + private int i; + + public GetterFunction(int i) { + this.i = i; + } + + public int getI() { + return this.i; + } + +} diff --git a/src/test/resources/SimpleTests/IfConstructor.java b/src/test/resources/SimpleTests/IfConstructor.java new file mode 100644 index 0000000..dff598a --- /dev/null +++ b/src/test/resources/SimpleTests/IfConstructor.java @@ -0,0 +1,11 @@ +package SimpleTests; + +class IfConstructor { + + int i; + + public IfConstructor() { + i = 0; + } + +} diff --git a/src/test/resources/SimpleTests/IfElseIfStatement.java b/src/test/resources/SimpleTests/IfElseIfStatement.java new file mode 100644 index 0000000..66921a1 --- /dev/null +++ b/src/test/resources/SimpleTests/IfElseIfStatement.java @@ -0,0 +1,15 @@ +package SimpleTests; + +class IfElseIfStatement { + + int foo(int i) { + if (i == 1) { + return 10; + } else if (i == 2) { + return 40000; + } else { + return 42000; + } + } + +} diff --git a/src/test/resources/SimpleTests/IfElseIfStatementWithOneReturn.java b/src/test/resources/SimpleTests/IfElseIfStatementWithOneReturn.java new file mode 100644 index 0000000..a1ab5ce --- /dev/null +++ b/src/test/resources/SimpleTests/IfElseIfStatementWithOneReturn.java @@ -0,0 +1,17 @@ +package SimpleTests; + +class IfElseIfStatementWithOneReturn { + + int foo(int i) { + int result = 0; + if (i == 1) { + result = 10; + } else if (i == 2) { + return 20; + } else { + result = 30; + } + return result; + } + +} diff --git a/src/test/resources/SimpleTests/IfElseIfStatementWithoutReturn.java b/src/test/resources/SimpleTests/IfElseIfStatementWithoutReturn.java new file mode 100644 index 0000000..846da0c --- /dev/null +++ b/src/test/resources/SimpleTests/IfElseIfStatementWithoutReturn.java @@ -0,0 +1,17 @@ +package SimpleTests; + +class IfElseIfStatementWithoutReturn { + + int foo(int i) { + int result; + if (i == 1) { + result = 10; + } else if (i == 2) { + result = 20; + } else { + result = 30; + } + return result; + } + +} diff --git a/src/test/resources/SimpleTests/IfElseStatement.java b/src/test/resources/SimpleTests/IfElseStatement.java new file mode 100644 index 0000000..0678843 --- /dev/null +++ b/src/test/resources/SimpleTests/IfElseStatement.java @@ -0,0 +1,13 @@ +package SimpleTests; + +class IfElseStatement { + + int foo(int i) { + if (i == 1) { + return 10; + } else { + return 100; + } + } + +} diff --git a/src/test/resources/SimpleTests/IfStatement.java b/src/test/resources/SimpleTests/IfStatement.java new file mode 100644 index 0000000..a13b32d --- /dev/null +++ b/src/test/resources/SimpleTests/IfStatement.java @@ -0,0 +1,12 @@ +package SimpleTests; + +class IfStatement { + + int foo(int i) { + if (i == 1) { + return 10; + } + return 100; + } + +} diff --git a/src/test/resources/SimpleTests/IncDecStressTest.java b/src/test/resources/SimpleTests/IncDecStressTest.java new file mode 100644 index 0000000..39a4354 --- /dev/null +++ b/src/test/resources/SimpleTests/IncDecStressTest.java @@ -0,0 +1,26 @@ +package SimpleTests; + +class IncDecStressTest { + + int incrementThenReturn(int i) { + return ++i; + } + + int returnThenIncrement(int i) { + return i++; + } + + int decrementThenReturn(int i) { + return --i; + } + + int returnThenDecrement(int i) { + return i--; + } + + int callInline(int i) { + i++; + return i; + } + +} diff --git a/src/test/resources/SimpleTests/IncTest.java b/src/test/resources/SimpleTests/IncTest.java new file mode 100644 index 0000000..711b53f --- /dev/null +++ b/src/test/resources/SimpleTests/IncTest.java @@ -0,0 +1,17 @@ +package SimpleTests; + +class IncTest { + + void foo() { + for (int i = 0; i < 10; i++) { + System.out.println(i); + } + } + + void bar() { + for (int i = 0; i < 10; ++i) { + System.out.println(i); + } + } + +} diff --git a/src/test/resources/SimpleTests/IntCompare.java b/src/test/resources/SimpleTests/IntCompare.java new file mode 100644 index 0000000..7f2e1c1 --- /dev/null +++ b/src/test/resources/SimpleTests/IntCompare.java @@ -0,0 +1,9 @@ +package SimpleTests; + +class IntCompare { + + boolean eq(int a, int b) { + return a == b; + } + +} diff --git a/src/test/resources/SimpleTests/IntMethod.java b/src/test/resources/SimpleTests/IntMethod.java new file mode 100644 index 0000000..95a7ce7 --- /dev/null +++ b/src/test/resources/SimpleTests/IntMethod.java @@ -0,0 +1,9 @@ +package SimpleTests; + +class IntMethod { + + int foo(){ + return 1; + } + +} diff --git a/src/test/resources/SimpleTests/KlammerVorPunkt.java b/src/test/resources/SimpleTests/KlammerVorPunkt.java new file mode 100644 index 0000000..4165f26 --- /dev/null +++ b/src/test/resources/SimpleTests/KlammerVorPunkt.java @@ -0,0 +1,9 @@ +package SimpleTests; + +class KlammerVorPunkt { + + int foo(int a, int b, int c) { + return (b + c) * a; + } + +} diff --git a/src/test/resources/SimpleTests/MainMethodTest.java b/src/test/resources/SimpleTests/MainMethodTest.java new file mode 100644 index 0000000..892f7b9 --- /dev/null +++ b/src/test/resources/SimpleTests/MainMethodTest.java @@ -0,0 +1,9 @@ +package SimpleTests; + +class MainMethodTest { + + public static void main(String[] args) { + System.out.println("maintest"); + } + +} diff --git a/src/test/resources/SimpleTests/MethodCall.java b/src/test/resources/SimpleTests/MethodCall.java new file mode 100644 index 0000000..f70d253 --- /dev/null +++ b/src/test/resources/SimpleTests/MethodCall.java @@ -0,0 +1,15 @@ +package SimpleTests; + +class MethodCall { + + int i; + + public MethodCall() { + this.i = foo(); + } + + int foo() { + return 1; + } + +} diff --git a/src/test/resources/SimpleTests/MethodCallParams.java b/src/test/resources/SimpleTests/MethodCallParams.java new file mode 100644 index 0000000..6d63a35 --- /dev/null +++ b/src/test/resources/SimpleTests/MethodCallParams.java @@ -0,0 +1,15 @@ +package SimpleTests; + +class MethodCallParams { + + int i; + + public MethodCallParams(int i) { + this.i = foo(i); + } + + int foo(int i) { + return i; + } + +} diff --git a/src/test/resources/SimpleTests/MethodCallStressTest.java b/src/test/resources/SimpleTests/MethodCallStressTest.java new file mode 100644 index 0000000..c2cdbe8 --- /dev/null +++ b/src/test/resources/SimpleTests/MethodCallStressTest.java @@ -0,0 +1,34 @@ +package SimpleTests; + +class MethodCallStressTest { + + void foo() { + int i = baz(); + while (i < 10) { + baz(); + bar(); + i = i + baz(); + } + + i = baz() - baz(); + i = baz() + baz(); + + if (boo()) { + i = baz(); + } else { + i = baz(); + } + } + + void bar() { + } + + int baz() { + return 1; + } + + boolean boo() { + return true; + } + +} diff --git a/src/test/resources/SimpleTests/MethodCallsInWhile.java b/src/test/resources/SimpleTests/MethodCallsInWhile.java new file mode 100644 index 0000000..458b1c7 --- /dev/null +++ b/src/test/resources/SimpleTests/MethodCallsInWhile.java @@ -0,0 +1,23 @@ +package SimpleTests; + +class MethodCallsInWhile { + + void main() { + int i = 0; + Test t = new Test(); + t.foo(); + while (i < 10) { + i = i + t.foo(); + t.foo(); // <-- This is causing the error + } + + } + +} + +class Test { + + int foo() { + return 1; + } +} diff --git a/src/test/resources/SimpleTests/MiniLinkedList.java b/src/test/resources/SimpleTests/MiniLinkedList.java new file mode 100644 index 0000000..2c3e08e --- /dev/null +++ b/src/test/resources/SimpleTests/MiniLinkedList.java @@ -0,0 +1,25 @@ +package SimpleTests; + +class MiniLinkedList { + + int main() { + LinkedList list = new LinkedList(1); + return 1; + } + +} + +class LinkedList { + + int x; + private LinkedList next; + + public LinkedList(int x) { + this.x = x; + } + + void add(int x) { + next = new LinkedList(x); + } + +} diff --git a/src/test/resources/SimpleTests/MinusMethod.java b/src/test/resources/SimpleTests/MinusMethod.java new file mode 100644 index 0000000..5c99fe5 --- /dev/null +++ b/src/test/resources/SimpleTests/MinusMethod.java @@ -0,0 +1,9 @@ +package SimpleTests; + +class MinusMethod { + + int foo(int i){ + return i-i; + } + +} diff --git a/src/test/resources/SimpleTests/ModMethod.java b/src/test/resources/SimpleTests/ModMethod.java new file mode 100644 index 0000000..5c81d23 --- /dev/null +++ b/src/test/resources/SimpleTests/ModMethod.java @@ -0,0 +1,7 @@ +package SimpleTests; + +class ModMethod { + int foo(int i, int j) { + return i % j; + } +} \ No newline at end of file diff --git a/src/test/resources/SimpleTests/MulMethod.java b/src/test/resources/SimpleTests/MulMethod.java new file mode 100644 index 0000000..9d03138 --- /dev/null +++ b/src/test/resources/SimpleTests/MulMethod.java @@ -0,0 +1,9 @@ +package SimpleTests; + +class MulMethod { + + int foo(int i){ + return i*i; + } + +} diff --git a/src/test/resources/SimpleTests/MultClasses.java b/src/test/resources/SimpleTests/MultClasses.java new file mode 100644 index 0000000..8a35cf4 --- /dev/null +++ b/src/test/resources/SimpleTests/MultClasses.java @@ -0,0 +1,9 @@ +package SimpleTests; + +class MultClasses1 { + +} + +class MultClasses2 { + +} diff --git a/src/test/resources/SimpleTests/MultClassesReference.java b/src/test/resources/SimpleTests/MultClassesReference.java new file mode 100644 index 0000000..1b3d3ef --- /dev/null +++ b/src/test/resources/SimpleTests/MultClassesReference.java @@ -0,0 +1,26 @@ +package SimpleTests; + +class MultClassesReference1 { + + public int i; + + public MultClassesReference1(int i){ + this.i = i; + } + + +} + +class MultClassesReference2 { + + public MultClassesReference1 bar; + + public MultClassesReference2(int i){ + this.bar = new MultClassesReference1(i); + } + + int test(){ + return this.bar.i; + } + +} \ No newline at end of file diff --git a/src/test/resources/SimpleTests/MultipleClassesMethodCalls.java b/src/test/resources/SimpleTests/MultipleClassesMethodCalls.java new file mode 100644 index 0000000..609159e --- /dev/null +++ b/src/test/resources/SimpleTests/MultipleClassesMethodCalls.java @@ -0,0 +1,22 @@ +package SimpleTests; + +class MultipleClassesMethodCalls { + + public int main(int i) { + Test t = new Test(i); + return t.getX(); + } + +} + +class Test { + public int x; + + public Test(int i) { + this.x = i; + } + + public int getX() { + return this.x; + } +} \ No newline at end of file diff --git a/src/test/resources/SimpleTests/MultipleClassesStress.java b/src/test/resources/SimpleTests/MultipleClassesStress.java new file mode 100644 index 0000000..a742183 --- /dev/null +++ b/src/test/resources/SimpleTests/MultipleClassesStress.java @@ -0,0 +1,24 @@ +package SimpleTests; + +class MultipleClassesStress { + + public int main(int i) { + Test t = new Test(i); + return t.getX() + t.y; + } + +} + +class Test { + private int x; + public int y; + + public Test(int i) { + this.x = i; + this.y = 10; + } + + public int getX() { + return this.x; + } +} \ No newline at end of file diff --git a/src/test/resources/SimpleTests/NotMethod.java b/src/test/resources/SimpleTests/NotMethod.java new file mode 100644 index 0000000..da989bc --- /dev/null +++ b/src/test/resources/SimpleTests/NotMethod.java @@ -0,0 +1,7 @@ +package SimpleTests; + +class NotMethod { + boolean foo(boolean i) { + return !i; + } +} \ No newline at end of file diff --git a/src/test/resources/SimpleTests/OperatorStacking.java b/src/test/resources/SimpleTests/OperatorStacking.java new file mode 100644 index 0000000..43a0123 --- /dev/null +++ b/src/test/resources/SimpleTests/OperatorStacking.java @@ -0,0 +1,21 @@ +package SimpleTests; + +class OperatorStacking { + + boolean foo() { + return true && false || true && true; // Should return true + } + + int bar() { + return 1 + 2 * 3 - 4 % 6; // Should return 3 + } + // 1 + 6 - 4 % 6 + // 7 - 4 % 6 + // 3 % 6 = 3 + + // 1 + 6 - 4 % 6 + // 1 + 6 - 4 + // 7-4 + // 3 + +} diff --git a/src/test/resources/SimpleTests/OperatorTest.java b/src/test/resources/SimpleTests/OperatorTest.java new file mode 100644 index 0000000..4d9e6e5 --- /dev/null +++ b/src/test/resources/SimpleTests/OperatorTest.java @@ -0,0 +1,86 @@ +package SimpleTests; + +class OperatorTest { + + public OperatorTest() { + } + + public int assign(int i) { + int returnValue; + returnValue = i; + return returnValue; + } + + public int plus(int x, int y) { + return x + y; + } + + public int minus(int x, int y) { + return x - y; + } + + public int mult(int x, int y) { + return x * y; + } + + public int div(int x, int y) { + return x / y; + } + + public int mod(int x, int y) { + return x % y; + } + + public boolean gt(int x, int y) { + return x > y; + } + + public boolean lt(int x, int y) { + return x < y; + } + + public boolean lte(int x, int y) { + return x <= y; + } + + public boolean gte(int x, int y) { + return x >= y; + } + + public boolean eq(int x, int y) { + return x == y; + } + + public boolean neq(int x, int y) { + return x != y; + } + + public boolean beq(boolean x, boolean y) { + return x == y; + } + + public boolean bneq(boolean x, boolean y) { + return x != y; + } + + public boolean and(boolean x, boolean y) { + return x && y; + } + + public boolean or(boolean x, boolean y) { + return x || y; + } + + public boolean not(boolean x) { + return !x; + } + + public boolean icEq(int x, char y) { + return x == y; + } + + public boolean icLt(int x, char y) { + return x < y; + } + +} \ No newline at end of file diff --git a/src/test/resources/SimpleTests/OverridingTest.java b/src/test/resources/SimpleTests/OverridingTest.java new file mode 100644 index 0000000..658de52 --- /dev/null +++ b/src/test/resources/SimpleTests/OverridingTest.java @@ -0,0 +1,32 @@ +package SimpleTests; + +class OverridingTest { + + // Test is used to determine wheter the Right method with the right types is + // called + + public int foo(int i) { + if (i < 5) { + return test(); + } else if (i < 10) { + return test(i); + } else { + return test(this); + } + } + + public int test() { + System.out.println(0); + return 0; + } + + public int test(int i) { + System.out.println(i); + return i; + } + + public int test(OverridingTest o) { + return 1337; + } + +} diff --git a/src/test/resources/SimpleTests/OverridingTestNull.java b/src/test/resources/SimpleTests/OverridingTestNull.java new file mode 100644 index 0000000..39b0df1 --- /dev/null +++ b/src/test/resources/SimpleTests/OverridingTestNull.java @@ -0,0 +1,35 @@ +package SimpleTests; + +class OverridingTestNull { + + // Test is used to determine wheter the Right method with the right types is + // called + + public int foo(int i) { + if (i < 5) { + return test(); + } else if (i < 10) { + return test(i); + } else if (i < 20) { + return test(this); + } else { + return test(null); + } + } + + public int test() { + System.out.println(0); + return 0; + } + + public int test(int i) { + System.out.println(i); + return i; + } + + public int test(OverridingTestNull o) { + System.out.println(1337); + return 1337; + } + +} diff --git a/src/test/resources/SimpleTests/OverridingTestNullMultiple.java b/src/test/resources/SimpleTests/OverridingTestNullMultiple.java new file mode 100644 index 0000000..99dd3d1 --- /dev/null +++ b/src/test/resources/SimpleTests/OverridingTestNullMultiple.java @@ -0,0 +1,37 @@ +package SimpleTests; + +class OverridingTestNullMultiple { + + // Test is used to determine wheter the Right method with the right types is + // called + + public int foo(int i) { + if (i < 5) { + return test(); + } else if (i < 10) { + return test(i); + } else if (i < 20) { + return test(this, null); + } else if (i < 30) { + return test(null, null); + } else { + return test(this, this); + } + } + + public int test() { + System.out.println(0); + return 0; + } + + public int test(int i) { + System.out.println(i); + return i; + } + + public int test(OverridingTestNullMultiple o, OverridingTestNullMultiple b) { + System.out.println(1337); + return 1337; + } + +} diff --git a/src/test/resources/SimpleTests/ParamMethod.java b/src/test/resources/SimpleTests/ParamMethod.java new file mode 100644 index 0000000..fe19181 --- /dev/null +++ b/src/test/resources/SimpleTests/ParamMethod.java @@ -0,0 +1,7 @@ +package SimpleTests; + +class ParamMethod { + + void foo(int i){} + +} diff --git a/src/test/resources/SimpleTests/PlusMethod.java b/src/test/resources/SimpleTests/PlusMethod.java new file mode 100644 index 0000000..3dc849c --- /dev/null +++ b/src/test/resources/SimpleTests/PlusMethod.java @@ -0,0 +1,9 @@ +package SimpleTests; + +class PlusMethod { + + int foo(int i){ + return i+i; + } + +} diff --git a/src/test/resources/SimpleTests/PunktVorStrich.java b/src/test/resources/SimpleTests/PunktVorStrich.java new file mode 100644 index 0000000..42643d6 --- /dev/null +++ b/src/test/resources/SimpleTests/PunktVorStrich.java @@ -0,0 +1,13 @@ +package SimpleTests; + +class PunktVorStrich { + + int foo(int a, int b, int c) { + return a * b + c; + } + + int bar(int a, int b, int c) { + return a + b * c; + } + +} diff --git a/src/test/resources/SimpleTests/RealConstructor.java b/src/test/resources/SimpleTests/RealConstructor.java new file mode 100644 index 0000000..3bb9571 --- /dev/null +++ b/src/test/resources/SimpleTests/RealConstructor.java @@ -0,0 +1,11 @@ +package SimpleTests; + +class RealConstructor { + + private int i; + + public RealConstructor(int i){ + this.i = i; + } + +} diff --git a/src/test/resources/SimpleTests/RealMethod.java b/src/test/resources/SimpleTests/RealMethod.java new file mode 100644 index 0000000..1b39ece --- /dev/null +++ b/src/test/resources/SimpleTests/RealMethod.java @@ -0,0 +1,7 @@ +package SimpleTests; + +class RealMethod { + int foo(int i){ + return i; + } +} diff --git a/src/test/resources/SimpleTests/RealWhile.java b/src/test/resources/SimpleTests/RealWhile.java new file mode 100644 index 0000000..b81a5e2 --- /dev/null +++ b/src/test/resources/SimpleTests/RealWhile.java @@ -0,0 +1,14 @@ +package SimpleTests; + +class RealWhile { + + int foo(int i) { + int result = 0; + while (i > 0) { + result = result + 2; + i = i - 1; + } + return result; + } + +} diff --git a/src/test/resources/SimpleTests/SelfReference.java b/src/test/resources/SimpleTests/SelfReference.java new file mode 100644 index 0000000..4f2c922 --- /dev/null +++ b/src/test/resources/SimpleTests/SelfReference.java @@ -0,0 +1,20 @@ +package SimpleTests; + +class SelfReference { + + SelfReference selfRef; + + int foo() { + return this.baz(); + } + + int baz() { + return 10; + } + + int bar() { + SelfReference self = new SelfReference(); + return self.selfRef.foo(); + } + +} diff --git a/src/test/resources/SimpleTests/SystemOutPrintln.java b/src/test/resources/SimpleTests/SystemOutPrintln.java new file mode 100644 index 0000000..39273fd --- /dev/null +++ b/src/test/resources/SimpleTests/SystemOutPrintln.java @@ -0,0 +1,9 @@ +package SimpleTests; + +class SystemOutPrintln { + + void foo() { + System.out.println(1); + } + +} diff --git a/src/test/resources/SimpleTests/SystemOutPrintlnString.java b/src/test/resources/SimpleTests/SystemOutPrintlnString.java new file mode 100644 index 0000000..7fdb8d2 --- /dev/null +++ b/src/test/resources/SimpleTests/SystemOutPrintlnString.java @@ -0,0 +1,9 @@ +package SimpleTests; + +class SystemOutPrintlnString { + + void foo() { + System.out.println("Das ist ein String"); + } + +} diff --git a/src/test/resources/SimpleTests/ThisDotMethodCall.java b/src/test/resources/SimpleTests/ThisDotMethodCall.java new file mode 100644 index 0000000..1171ff2 --- /dev/null +++ b/src/test/resources/SimpleTests/ThisDotMethodCall.java @@ -0,0 +1,15 @@ +package SimpleTests; + +class ThisDotMethodCall { + + int i; + + public ThisDotMethodCall() { + this.i = this.foo(); + } + + int foo() { + return 1; + } + +} diff --git a/src/test/resources/SimpleTests/ValueAdapterTests.java b/src/test/resources/SimpleTests/ValueAdapterTests.java new file mode 100644 index 0000000..d0a67d1 --- /dev/null +++ b/src/test/resources/SimpleTests/ValueAdapterTests.java @@ -0,0 +1,29 @@ +package SimpleTests; + +class ValueAdapterTests { + + boolean readsTrue() { + return true; + } + + boolean readsFalse() { + return false; + } + + boolean readsTrueAndFalse() { + return true && false; + } + + int readsInt() { + return 1; + } + + int readsIntAndInt() { + return 1 + 1; + } + + char readsChar() { + return 'a'; + } + +} diff --git a/src/test/resources/SimpleTests/VoidMethod.java b/src/test/resources/SimpleTests/VoidMethod.java new file mode 100644 index 0000000..4635a60 --- /dev/null +++ b/src/test/resources/SimpleTests/VoidMethod.java @@ -0,0 +1,7 @@ +package SimpleTests; + +class VoidMethod { + + void foo(){} + +} diff --git a/src/test/resources/SimpleTests/VoidReturn.java b/src/test/resources/SimpleTests/VoidReturn.java new file mode 100644 index 0000000..2e53b08 --- /dev/null +++ b/src/test/resources/SimpleTests/VoidReturn.java @@ -0,0 +1,9 @@ +package SimpleTests; + +class VoidReturn { + + void foo() { + return; + } + +} diff --git a/src/test/resources/SimpleTests/WhileTest.java b/src/test/resources/SimpleTests/WhileTest.java new file mode 100644 index 0000000..0c366da --- /dev/null +++ b/src/test/resources/SimpleTests/WhileTest.java @@ -0,0 +1,13 @@ +package SimpleTests; + +class WhileTest { + + + int foo(){ + while(true){ + return 1; + } + } + + +} diff --git a/src/test/resources/basicClasses/emptyClass b/src/test/resources/basicClasses/emptyClass new file mode 100644 index 0000000..0a60526 --- /dev/null +++ b/src/test/resources/basicClasses/emptyClass @@ -0,0 +1 @@ +class emptyClass {} \ No newline at end of file diff --git a/src/test/resources/basicClasses/publicEmptyClass b/src/test/resources/basicClasses/publicEmptyClass new file mode 100644 index 0000000..e69de29 From c185b56065ce3c9415f32837a1803011721cd358 Mon Sep 17 00:00:00 2001 From: i22022 Date: Wed, 8 May 2024 08:59:02 +0000 Subject: [PATCH 03/10] Readme --- Readme.MD | 1 + 1 file changed, 1 insertion(+) create mode 100644 Readme.MD diff --git a/Readme.MD b/Readme.MD new file mode 100644 index 0000000..9d0061b --- /dev/null +++ b/Readme.MD @@ -0,0 +1 @@ +Please move your stuff from "Source" to "src". From 10a5d41aa80b12c3f10856a0292e9fc613bf1597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krau=C3=9F=2C=20Josefine?= Date: Wed, 8 May 2024 11:22:12 +0200 Subject: [PATCH 04/10] working on class fields --- Source/TypeCheck/TypeCheckHelper.java | 9 +++++++++ Source/abstractSyntaxTree/Class/FieldDecl.java | 15 ++++++++++++--- Source/abstractSyntaxTree/Class/MethodDecl.java | 12 ++++++++++++ Source/abstractSyntaxTree/Datatype/RefType.java | 16 +++++++++++++++- Source/abstractSyntaxTree/Program.java | 11 +++++++++++ .../Statement/BlockStatement.java | 6 +++++- .../abstractSyntaxTree/Statement/IStatement.java | 2 ++ 7 files changed, 66 insertions(+), 5 deletions(-) diff --git a/Source/TypeCheck/TypeCheckHelper.java b/Source/TypeCheck/TypeCheckHelper.java index e5a3a65..bd4aa58 100644 --- a/Source/TypeCheck/TypeCheckHelper.java +++ b/Source/TypeCheck/TypeCheckHelper.java @@ -1,5 +1,6 @@ package TypeCheck; +import java.util.List; import java.util.Objects; public class TypeCheckHelper { @@ -20,4 +21,12 @@ public class TypeCheckHelper { } return result; } + public static boolean typeExists(String type, List typeslist) { + + if(type.equals("int") || type.equals("bool") || type.equals("char")){ + return true; + } + return typeslist.contains(type); + } + } diff --git a/Source/abstractSyntaxTree/Class/FieldDecl.java b/Source/abstractSyntaxTree/Class/FieldDecl.java index 7524350..f22e2f6 100644 --- a/Source/abstractSyntaxTree/Class/FieldDecl.java +++ b/Source/abstractSyntaxTree/Class/FieldDecl.java @@ -1,14 +1,20 @@ package abstractSyntaxTree.Class; +import TypeCheck.AbstractType; +import TypeCheck.TypeCheckHelper; import TypeCheck.TypeCheckResult; +import abstractSyntaxTree.Program; import java.util.ArrayList; import java.util.List; -public class FieldDecl implements IClass { - private String type; +public class FieldDecl extends AbstractType implements IClass{ + private Program program; private String identifier; + public FieldDecl(Program program){ + this.program = program; + } public TypeCheckResult typeCheck(List classFieldsIdentifier) throws Exception { TypeCheckResult result = new TypeCheckResult(); if (classFieldsIdentifier.contains(this.identifier)){ @@ -16,8 +22,11 @@ public class FieldDecl implements IClass { } else { classFieldsIdentifier.add(this); } - result.type = this.type; + //TypeCheckHelper.typeExists(type, ) // need all types of classes + setTypeCheckResult(result); return result; + + //write field table } } diff --git a/Source/abstractSyntaxTree/Class/MethodDecl.java b/Source/abstractSyntaxTree/Class/MethodDecl.java index 3ae18c4..89f9fad 100644 --- a/Source/abstractSyntaxTree/Class/MethodDecl.java +++ b/Source/abstractSyntaxTree/Class/MethodDecl.java @@ -1,12 +1,24 @@ package abstractSyntaxTree.Class; import TypeCheck.TypeCheckResult; +import abstractSyntaxTree.Program; +import java.util.HashMap; import java.util.List; public class MethodDecl implements IClass { + + private Program program; + + private HashMap localVars; + + public MethodDecl(Program program){ + this.program = program; + } public TypeCheckResult typeCheck(List fieldsOrMethods) throws Exception { return null; +// write localvars + // write method table } } diff --git a/Source/abstractSyntaxTree/Datatype/RefType.java b/Source/abstractSyntaxTree/Datatype/RefType.java index 8c3d64e..59781a6 100644 --- a/Source/abstractSyntaxTree/Datatype/RefType.java +++ b/Source/abstractSyntaxTree/Datatype/RefType.java @@ -4,14 +4,28 @@ import TypeCheck.AbstractType; import TypeCheck.TypeCheckResult; import abstractSyntaxTree.Class.FieldDecl; import abstractSyntaxTree.Class.MethodDecl; +import abstractSyntaxTree.Program; import jdk.jshell.spi.ExecutionControl; -import org.objectweb.asm.MethodVisitor; +import java.util.HashMap; import java.util.List; public class RefType extends AbstractType implements IDatatype { + + String name; public List fieldDecls; + + private HashMap fieldsTable; // type, identifier public List methodDecls; + private HashMap methodsTable; // return type, method name without parameter + private Program program; + + private boolean hasMain; + + + public RefType(Program program){ + this.program = program; + } public RefType(List fieldDecls, List methodDecls){ this.fieldDecls = fieldDecls; this.methodDecls = methodDecls; diff --git a/Source/abstractSyntaxTree/Program.java b/Source/abstractSyntaxTree/Program.java index a590977..c7c8469 100644 --- a/Source/abstractSyntaxTree/Program.java +++ b/Source/abstractSyntaxTree/Program.java @@ -3,13 +3,24 @@ package abstractSyntaxTree; import TypeCheck.TypeCheckResult; import abstractSyntaxTree.Datatype.RefType; +import java.util.HashMap; import java.util.List; public class Program { public List classes; + public HashMap> classTypeIndentifierTable; // (class, (type, identifier)) + public TypeCheckResult typeCheck() throws Exception{ + for(RefType oneClass : classes){ + oneClass.typeCheck(); + } return null; } + public void codeGen() throws Exception{ + for(RefType oneClass : classes){ + oneClass.codeGen(); + } + } } diff --git a/Source/abstractSyntaxTree/Statement/BlockStatement.java b/Source/abstractSyntaxTree/Statement/BlockStatement.java index 3fb36e4..be04bbc 100644 --- a/Source/abstractSyntaxTree/Statement/BlockStatement.java +++ b/Source/abstractSyntaxTree/Statement/BlockStatement.java @@ -5,13 +5,17 @@ import TypeCheck.AbstractType; import abstractSyntaxTree.Expression.IExpression; import org.objectweb.asm.MethodVisitor; +import java.util.HashMap; import java.util.List; public class BlockStatement extends AbstractType implements IStatement{ //We will need a parameter which holds the symbol table + HashMap localVars; + HashMap typeIndentifierTable; // from program List statements; - public BlockStatement(List statements){ + public BlockStatement(List statements, HashMap localVars, HashMap typeIndentifierTable){ + this.statements = statements; } @Override diff --git a/Source/abstractSyntaxTree/Statement/IStatement.java b/Source/abstractSyntaxTree/Statement/IStatement.java index 65a2cb0..dd75e23 100644 --- a/Source/abstractSyntaxTree/Statement/IStatement.java +++ b/Source/abstractSyntaxTree/Statement/IStatement.java @@ -5,6 +5,8 @@ import org.objectweb.asm.MethodVisitor; public interface IStatement { + + TypeCheckResult typeCheck() throws Exception; void CodeGen(MethodVisitor mv) throws Exception; From a9101d2c1227aac63d25dc96e66c603b7f90198e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krau=C3=9F=2C=20Josefine?= Date: Wed, 8 May 2024 12:48:56 +0200 Subject: [PATCH 05/10] working on class/method tables --- Source/abstractSyntaxTree/Class/FieldDecl.java | 11 +++++++---- .../abstractSyntaxTree/Class/MethodDecl.java | 15 +++++++++------ .../abstractSyntaxTree/Datatype/RefType.java | 18 +++++++++--------- Source/abstractSyntaxTree/Program.java | 7 ++++++- .../Statement/BlockStatement.java | 4 ++-- 5 files changed, 33 insertions(+), 22 deletions(-) diff --git a/Source/abstractSyntaxTree/Class/FieldDecl.java b/Source/abstractSyntaxTree/Class/FieldDecl.java index f22e2f6..98e2225 100644 --- a/Source/abstractSyntaxTree/Class/FieldDecl.java +++ b/Source/abstractSyntaxTree/Class/FieldDecl.java @@ -6,14 +6,17 @@ import TypeCheck.TypeCheckResult; import abstractSyntaxTree.Program; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; public class FieldDecl extends AbstractType implements IClass{ - private Program program; - private String identifier; - public FieldDecl(Program program){ - this.program = program; + private HashMap> typeContext; // form class from program + public String type; // from parser + public String identifier; // from parser + + public FieldDecl(HashMap> typeContext){ + this.typeContext = typeContext; } public TypeCheckResult typeCheck(List classFieldsIdentifier) throws Exception { TypeCheckResult result = new TypeCheckResult(); diff --git a/Source/abstractSyntaxTree/Class/MethodDecl.java b/Source/abstractSyntaxTree/Class/MethodDecl.java index 89f9fad..fce967a 100644 --- a/Source/abstractSyntaxTree/Class/MethodDecl.java +++ b/Source/abstractSyntaxTree/Class/MethodDecl.java @@ -8,17 +8,20 @@ import java.util.List; public class MethodDecl implements IClass { - private Program program; + private HashMap>> methodContext; + private HashMap> typeContext; - private HashMap localVars; + private HashMap localVars; // (type, identifier) // add content here - public MethodDecl(Program program){ - this.program = program; + public MethodDecl(HashMap>> methodContext, HashMap> typeContext){ + this.methodContext = methodContext; + this.typeContext = typeContext; } public TypeCheckResult typeCheck(List fieldsOrMethods) throws Exception { + // write localvars + + // jede methode als block statement aufrufen return null; -// write localvars - // write method table } } diff --git a/Source/abstractSyntaxTree/Datatype/RefType.java b/Source/abstractSyntaxTree/Datatype/RefType.java index 59781a6..42f9876 100644 --- a/Source/abstractSyntaxTree/Datatype/RefType.java +++ b/Source/abstractSyntaxTree/Datatype/RefType.java @@ -14,22 +14,22 @@ public class RefType extends AbstractType implements IDatatype { String name; public List fieldDecls; - - private HashMap fieldsTable; // type, identifier public List methodDecls; - private HashMap methodsTable; // return type, method name without parameter - private Program program; + private HashMap> typeContext; // (class, (type, identifier)) + private HashMap>> methodContext; // (class, (returntype, (identifier, parameter) private boolean hasMain; - - public RefType(Program program){ - this.program = program; - } - public RefType(List fieldDecls, List methodDecls){ + public RefType(List fieldDecls, + List methodDecls, + HashMap> typeContext, + HashMap>> methodContext){ this.fieldDecls = fieldDecls; this.methodDecls = methodDecls; + this.typeContext = typeContext; + this.methodContext = methodContext; } + @Override public TypeCheckResult typeCheck() throws Exception { TypeCheckResult result = new TypeCheckResult(); diff --git a/Source/abstractSyntaxTree/Program.java b/Source/abstractSyntaxTree/Program.java index c7c8469..8d06220 100644 --- a/Source/abstractSyntaxTree/Program.java +++ b/Source/abstractSyntaxTree/Program.java @@ -1,6 +1,7 @@ package abstractSyntaxTree; import TypeCheck.TypeCheckResult; +import abstractSyntaxTree.Class.FieldDecl; import abstractSyntaxTree.Datatype.RefType; import java.util.HashMap; @@ -9,10 +10,14 @@ import java.util.List; public class Program { public List classes; - public HashMap> classTypeIndentifierTable; // (class, (type, identifier)) + public HashMap> typeContext; // (class, (type, identifier)) + public HashMap>> methodContext; // (class, (returntype, (identifier, parameter))) public TypeCheckResult typeCheck() throws Exception{ for(RefType oneClass : classes){ + HashMap classVars = new HashMap<>(); + for (FieldDecl fielsDecl: oneClass.fieldDecls) + classVars.put(fielsDecl.type, fielsDecl.identifier); oneClass.typeCheck(); } return null; diff --git a/Source/abstractSyntaxTree/Statement/BlockStatement.java b/Source/abstractSyntaxTree/Statement/BlockStatement.java index be04bbc..84cb0d7 100644 --- a/Source/abstractSyntaxTree/Statement/BlockStatement.java +++ b/Source/abstractSyntaxTree/Statement/BlockStatement.java @@ -2,8 +2,6 @@ package abstractSyntaxTree.Statement; import TypeCheck.TypeCheckResult; import TypeCheck.AbstractType; -import abstractSyntaxTree.Expression.IExpression; -import org.objectweb.asm.MethodVisitor; import java.util.HashMap; import java.util.List; @@ -14,6 +12,8 @@ public class BlockStatement extends AbstractType implements IStatement{ HashMap localVars; HashMap typeIndentifierTable; // from program List statements; + // do we need expression, statementexpression + public BlockStatement(List statements, HashMap localVars, HashMap typeIndentifierTable){ this.statements = statements; From ce399626dac29071d2b4c65a0bfd42ed229990b3 Mon Sep 17 00:00:00 2001 From: Jochen Seyfried Date: Wed, 8 May 2024 12:56:40 +0200 Subject: [PATCH 06/10] Fixed typo in codeGen method declaration --- .../Datatype/BoolDatatype.java | 2 +- .../Datatype/CharDatatype.java | 2 +- .../Datatype/IDatatype.java | 2 +- .../Datatype/IntDatatype.java | 2 +- .../abstractSyntaxTree/Datatype/RefType.java | 3 +- .../Expression/BinaryExpression.java | 50 +++++++++---------- .../Expression/IExpression.java | 2 +- .../Expression/InstVarExpression.java | 2 +- .../Expression/UnaryExpression.java | 4 +- .../Expression/VarRefExpression.java | 2 +- Source/abstractSyntaxTree/Program.java | 1 + .../Statement/BlockStatement.java | 5 +- .../Statement/EmptyStatement.java | 2 +- .../Statement/IStatement.java | 2 +- .../Statement/IfElseStatement.java | 6 +-- .../Statement/IfStatement.java | 4 +- .../Statement/ReturnStatement.java | 2 +- .../Statement/WhileStatement.java | 6 +-- 18 files changed, 51 insertions(+), 48 deletions(-) diff --git a/Source/abstractSyntaxTree/Datatype/BoolDatatype.java b/Source/abstractSyntaxTree/Datatype/BoolDatatype.java index 6f571fb..6b8ccf0 100644 --- a/Source/abstractSyntaxTree/Datatype/BoolDatatype.java +++ b/Source/abstractSyntaxTree/Datatype/BoolDatatype.java @@ -17,7 +17,7 @@ public class BoolDatatype extends AbstractType implements IDatatype{ } @Override - public void CodeGen(MethodVisitor mv) throws Exception { + public void codeGen(MethodVisitor mv) throws Exception { if(value) { mv.visitInsn(Opcodes.ICONST_1); // Pushes the int 1 on the stack (true) } else { diff --git a/Source/abstractSyntaxTree/Datatype/CharDatatype.java b/Source/abstractSyntaxTree/Datatype/CharDatatype.java index 12424fa..1346f0d 100644 --- a/Source/abstractSyntaxTree/Datatype/CharDatatype.java +++ b/Source/abstractSyntaxTree/Datatype/CharDatatype.java @@ -17,7 +17,7 @@ public class CharDatatype extends AbstractType implements IDatatype{ } @Override - public void CodeGen(MethodVisitor mv) throws Exception { + public void codeGen(MethodVisitor mv) throws Exception { // Possible use of BIPUSH and SIPUSH if the value is small enough //This saves space in the bytecode which is not very relevant at this point, but could be implemented anyway diff --git a/Source/abstractSyntaxTree/Datatype/IDatatype.java b/Source/abstractSyntaxTree/Datatype/IDatatype.java index 0947c89..d729f96 100644 --- a/Source/abstractSyntaxTree/Datatype/IDatatype.java +++ b/Source/abstractSyntaxTree/Datatype/IDatatype.java @@ -9,7 +9,7 @@ public interface IDatatype { // visit method for code generation - void CodeGen(MethodVisitor mv) throws Exception; + void codeGen(MethodVisitor mv) throws Exception; } //TODO: Check if we need to differentiate between primitive types and reference types --> for example in "==" \ No newline at end of file diff --git a/Source/abstractSyntaxTree/Datatype/IntDatatype.java b/Source/abstractSyntaxTree/Datatype/IntDatatype.java index a49c496..4733931 100644 --- a/Source/abstractSyntaxTree/Datatype/IntDatatype.java +++ b/Source/abstractSyntaxTree/Datatype/IntDatatype.java @@ -21,7 +21,7 @@ public class IntDatatype extends AbstractType implements IDatatype{ @Override - public void CodeGen(MethodVisitor mv) throws Exception { + public void codeGen(MethodVisitor mv) throws Exception { //Example of using BIPUSH and SIPUSH for optimizing bytecode size if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) diff --git a/Source/abstractSyntaxTree/Datatype/RefType.java b/Source/abstractSyntaxTree/Datatype/RefType.java index 42f9876..1c3d0ab 100644 --- a/Source/abstractSyntaxTree/Datatype/RefType.java +++ b/Source/abstractSyntaxTree/Datatype/RefType.java @@ -6,6 +6,7 @@ import abstractSyntaxTree.Class.FieldDecl; import abstractSyntaxTree.Class.MethodDecl; import abstractSyntaxTree.Program; import jdk.jshell.spi.ExecutionControl; +import org.objectweb.asm.MethodVisitor; import java.util.HashMap; import java.util.List; @@ -50,7 +51,7 @@ public class RefType extends AbstractType implements IDatatype { // Method for code generation which iterates over all the field declarations // and method declarations and calls their CodeGen methods @Override - public void CodeGen(MethodVisitor mv) throws Exception { + public void codeGen(MethodVisitor mv) throws Exception { throw new ExecutionControl.NotImplementedException("CodeGen not implemented for RefType"); } diff --git a/Source/abstractSyntaxTree/Expression/BinaryExpression.java b/Source/abstractSyntaxTree/Expression/BinaryExpression.java index 990ebde..72af1be 100644 --- a/Source/abstractSyntaxTree/Expression/BinaryExpression.java +++ b/Source/abstractSyntaxTree/Expression/BinaryExpression.java @@ -59,7 +59,7 @@ public class BinaryExpression extends AbstractType implements IExpression{ @Override - public void CodeGen(MethodVisitor mv) throws Exception { + public void codeGen(MethodVisitor mv) throws Exception { // Label for the jump instruction Label operationFalse = new Label(); //Operation is false Label operationTrue = new Label(); //Operation is true @@ -69,88 +69,88 @@ public class BinaryExpression extends AbstractType implements IExpression{ // Bytecode for the binary operation switch (operator) { case "&&": - left.CodeGen(mv); + left.codeGen(mv); mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // IFEQ --> "if equals to zero" (false) --> if left exp is false - right.CodeGen(mv); + right.codeGen(mv); mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // If right exp is false, jump to the end of the whole expression mv.visitJumpInsn(Opcodes.GOTO, operationTrue); // If it reaches this point, the right exp is true break; case "||": - left.CodeGen(mv); + left.codeGen(mv); mv.visitJumpInsn(Opcodes.IFNE, operationTrue); // IFNE --> "if not equals to zero" (true) --> if left exp is true - right.CodeGen(mv); + right.codeGen(mv); mv.visitJumpInsn(Opcodes.IFNE, operationTrue); break; case "==": // Keep in mind that only primitive types are allowed in this case (at this time) - left.CodeGen(mv); - right.CodeGen(mv); + left.codeGen(mv); + right.codeGen(mv); mv.visitJumpInsn(Opcodes.IF_ICMPEQ, operationTrue); // If the two values are equal, jump to the end of the expression break; case "<": - left.CodeGen(mv); - right.CodeGen(mv); + left.codeGen(mv); + right.codeGen(mv); mv.visitJumpInsn(Opcodes.IF_ICMPLT, operationTrue); // Checks only on less than, not equal break; case ">": - left.CodeGen(mv); - right.CodeGen(mv); + left.codeGen(mv); + right.codeGen(mv); mv.visitJumpInsn(Opcodes.IF_ICMPGT, operationTrue); // Checks only on greater than, not equal break; case "<=": - left.CodeGen(mv); - right.CodeGen(mv); + left.codeGen(mv); + right.codeGen(mv); mv.visitJumpInsn(Opcodes.IF_ICMPLE, operationTrue); // Checks on less than OR equal break; case ">=": - left.CodeGen(mv); - right.CodeGen(mv); + left.codeGen(mv); + right.codeGen(mv); mv.visitJumpInsn(Opcodes.IF_ICMPGE, operationTrue); // Checks on greater than OR equal break; case "!=": - left.CodeGen(mv); - right.CodeGen(mv); + left.codeGen(mv); + right.codeGen(mv); mv.visitJumpInsn(Opcodes.IF_ICMPNE, operationTrue); // Checks on not equal break; case "+": - left.CodeGen(mv); - right.CodeGen(mv); + left.codeGen(mv); + right.codeGen(mv); mv.visitInsn(Opcodes.IADD); break; case "-": - left.CodeGen(mv); - right.CodeGen(mv); + left.codeGen(mv); + right.codeGen(mv); mv.visitInsn(Opcodes.ISUB); break; case "*": - left.CodeGen(mv); - right.CodeGen(mv); + left.codeGen(mv); + right.codeGen(mv); mv.visitInsn(Opcodes.IMUL); break; case "/": - left.CodeGen(mv); - right.CodeGen(mv); + left.codeGen(mv); + right.codeGen(mv); mv.visitInsn(Opcodes.IDIV); break; diff --git a/Source/abstractSyntaxTree/Expression/IExpression.java b/Source/abstractSyntaxTree/Expression/IExpression.java index 6ef53bd..a679711 100644 --- a/Source/abstractSyntaxTree/Expression/IExpression.java +++ b/Source/abstractSyntaxTree/Expression/IExpression.java @@ -8,5 +8,5 @@ public interface IExpression { TypeCheckResult typeCheck() throws Exception; // visit method for code generation - void CodeGen(MethodVisitor mv) throws Exception; + void codeGen(MethodVisitor mv) throws Exception; } diff --git a/Source/abstractSyntaxTree/Expression/InstVarExpression.java b/Source/abstractSyntaxTree/Expression/InstVarExpression.java index 4cefa0c..7b45d3a 100644 --- a/Source/abstractSyntaxTree/Expression/InstVarExpression.java +++ b/Source/abstractSyntaxTree/Expression/InstVarExpression.java @@ -22,7 +22,7 @@ public class InstVarExpression implements IExpression{ } @Override - public void CodeGen(MethodVisitor mv) throws Exception { + public void codeGen(MethodVisitor mv) throws Exception { throw new ExecutionControl.NotImplementedException("CodeGen not implemented for InstVarExpression"); //ALOAD the index of the var diff --git a/Source/abstractSyntaxTree/Expression/UnaryExpression.java b/Source/abstractSyntaxTree/Expression/UnaryExpression.java index 890a43a..4acdc53 100644 --- a/Source/abstractSyntaxTree/Expression/UnaryExpression.java +++ b/Source/abstractSyntaxTree/Expression/UnaryExpression.java @@ -42,9 +42,9 @@ public class UnaryExpression extends AbstractType implements IExpression{ } @Override - public void CodeGen(MethodVisitor mv) throws Exception { + public void codeGen(MethodVisitor mv) throws Exception { - operand.CodeGen(mv); + operand.codeGen(mv); switch (operator) { case "!": diff --git a/Source/abstractSyntaxTree/Expression/VarRefExpression.java b/Source/abstractSyntaxTree/Expression/VarRefExpression.java index b94b166..9276930 100644 --- a/Source/abstractSyntaxTree/Expression/VarRefExpression.java +++ b/Source/abstractSyntaxTree/Expression/VarRefExpression.java @@ -17,7 +17,7 @@ public class VarRefExpression implements IExpression{ } @Override - public void CodeGen(MethodVisitor mv) throws Exception { + public void codeGen(MethodVisitor mv) throws Exception { throw new Exception("CodeGen not implemented for VarRefExpression"); } } diff --git a/Source/abstractSyntaxTree/Program.java b/Source/abstractSyntaxTree/Program.java index 8d06220..0c9aa5d 100644 --- a/Source/abstractSyntaxTree/Program.java +++ b/Source/abstractSyntaxTree/Program.java @@ -3,6 +3,7 @@ package abstractSyntaxTree; import TypeCheck.TypeCheckResult; import abstractSyntaxTree.Class.FieldDecl; import abstractSyntaxTree.Datatype.RefType; +import org.objectweb.asm.MethodVisitor; import java.util.HashMap; import java.util.List; diff --git a/Source/abstractSyntaxTree/Statement/BlockStatement.java b/Source/abstractSyntaxTree/Statement/BlockStatement.java index 84cb0d7..da8e26d 100644 --- a/Source/abstractSyntaxTree/Statement/BlockStatement.java +++ b/Source/abstractSyntaxTree/Statement/BlockStatement.java @@ -2,6 +2,7 @@ package abstractSyntaxTree.Statement; import TypeCheck.TypeCheckResult; import TypeCheck.AbstractType; +import org.objectweb.asm.*; import java.util.HashMap; import java.util.List; @@ -40,9 +41,9 @@ public class BlockStatement extends AbstractType implements IStatement{ } @Override - public void CodeGen(MethodVisitor mv) throws Exception { + public void codeGen(MethodVisitor mv) throws Exception { for (IStatement statement : statements) { - statement.CodeGen(mv); //TODO: I think we need to pass the symbol table here + statement.codeGen(mv); //TODO: I think we need to pass the symbol table here } } } diff --git a/Source/abstractSyntaxTree/Statement/EmptyStatement.java b/Source/abstractSyntaxTree/Statement/EmptyStatement.java index b6ce18e..01818d7 100644 --- a/Source/abstractSyntaxTree/Statement/EmptyStatement.java +++ b/Source/abstractSyntaxTree/Statement/EmptyStatement.java @@ -13,7 +13,7 @@ public class EmptyStatement extends AbstractType implements IStatement{ } @Override - public void CodeGen(MethodVisitor mv) throws Exception { + public void codeGen(MethodVisitor mv) throws Exception { //An empty statement does not generate any code } } diff --git a/Source/abstractSyntaxTree/Statement/IStatement.java b/Source/abstractSyntaxTree/Statement/IStatement.java index dd75e23..d15e56b 100644 --- a/Source/abstractSyntaxTree/Statement/IStatement.java +++ b/Source/abstractSyntaxTree/Statement/IStatement.java @@ -9,5 +9,5 @@ public interface IStatement { TypeCheckResult typeCheck() throws Exception; - void CodeGen(MethodVisitor mv) throws Exception; + void codeGen(MethodVisitor mv) throws Exception; } diff --git a/Source/abstractSyntaxTree/Statement/IfElseStatement.java b/Source/abstractSyntaxTree/Statement/IfElseStatement.java index 55f7619..cd0fe10 100644 --- a/Source/abstractSyntaxTree/Statement/IfElseStatement.java +++ b/Source/abstractSyntaxTree/Statement/IfElseStatement.java @@ -38,7 +38,7 @@ public class IfElseStatement extends AbstractType implements IStatement{ } @Override - public void CodeGen(MethodVisitor mv) throws Exception { + public void codeGen(MethodVisitor mv) throws Exception { Label conditionFalse = new Label(); Label statementEnd = new Label(); @@ -46,11 +46,11 @@ public class IfElseStatement extends AbstractType implements IStatement{ condition.CodeGen(mv); mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); //Checks if the condition is false (0) - ifStatement.CodeGen(mv); //If the condition is true, execute the ifBlock + ifStatement.codeGen(mv); //If the condition is true, execute the ifBlock mv.visitJumpInsn(Opcodes.GOTO, statementEnd); //Jump to the end of the if-else statement mv.visitLabel(conditionFalse); - elseStatement.CodeGen(mv); //If the condition is false, execute the elseBlock + elseStatement.codeGen(mv); //If the condition is false, execute the elseBlock mv.visitLabel(statementEnd); //End of the if-else statement diff --git a/Source/abstractSyntaxTree/Statement/IfStatement.java b/Source/abstractSyntaxTree/Statement/IfStatement.java index c1a915d..665f4f1 100644 --- a/Source/abstractSyntaxTree/Statement/IfStatement.java +++ b/Source/abstractSyntaxTree/Statement/IfStatement.java @@ -31,14 +31,14 @@ public class IfStatement extends AbstractType implements IStatement{ } @Override - public void CodeGen(MethodVisitor mv) throws Exception { + public void codeGen(MethodVisitor mv) throws Exception { Label conditionFalse = new Label(); condition.CodeGen(mv); mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); //Checks if the condition is false (0) - ifStatement.CodeGen(mv); + ifStatement.codeGen(mv); mv.visitLabel(conditionFalse); // If the condition is false, the Statements in the ifBlock will not be executed } diff --git a/Source/abstractSyntaxTree/Statement/ReturnStatement.java b/Source/abstractSyntaxTree/Statement/ReturnStatement.java index 2ee7536..0005827 100644 --- a/Source/abstractSyntaxTree/Statement/ReturnStatement.java +++ b/Source/abstractSyntaxTree/Statement/ReturnStatement.java @@ -31,7 +31,7 @@ public class ReturnStatement extends AbstractType implements IStatement{ // This is a problem at "BinaryExpression" and here because we need to know the type to return // At this point in time we can either return reference types or have an error message @Override - public void CodeGen(MethodVisitor mv) throws Exception { + public void codeGen(MethodVisitor mv) throws Exception { if (expression != null) { expression.CodeGen(mv); diff --git a/Source/abstractSyntaxTree/Statement/WhileStatement.java b/Source/abstractSyntaxTree/Statement/WhileStatement.java index 128660e..e923fa1 100644 --- a/Source/abstractSyntaxTree/Statement/WhileStatement.java +++ b/Source/abstractSyntaxTree/Statement/WhileStatement.java @@ -31,16 +31,16 @@ public class WhileStatement extends AbstractType implements IStatement { } @Override - public void CodeGen(MethodVisitor mv) throws Exception { + public void codeGen(MethodVisitor mv) throws Exception { Label conditionFalse = new Label(); Label LoopStart = new Label(); mv.visitLabel(LoopStart); - condition.CodeGen(mv); + condition.codeGen(mv); mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); // Checks if the condition is false (0) - statement.CodeGen(mv); + statement.codeGen(mv); //TODO: If the block ends with a return statement, we might have to pop it from the stack // So the next iteration starts with a clean stack mv.visitJumpInsn(Opcodes.GOTO, LoopStart); // Jump to the start of the while loop From 370b2dbb06671d013f696463682acc50d2d0d34e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krau=C3=9F=2C=20Josefine?= Date: Wed, 8 May 2024 13:51:00 +0200 Subject: [PATCH 07/10] delete modifier --- Source/abstractSyntaxTree/Class/MethodDecl.java | 2 ++ Source/abstractSyntaxTree/Program.java | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/abstractSyntaxTree/Class/MethodDecl.java b/Source/abstractSyntaxTree/Class/MethodDecl.java index fce967a..1d3dc98 100644 --- a/Source/abstractSyntaxTree/Class/MethodDecl.java +++ b/Source/abstractSyntaxTree/Class/MethodDecl.java @@ -8,6 +8,8 @@ import java.util.List; public class MethodDecl implements IClass { + // name + private HashMap>> methodContext; private HashMap> typeContext; diff --git a/Source/abstractSyntaxTree/Program.java b/Source/abstractSyntaxTree/Program.java index 8d06220..c07013f 100644 --- a/Source/abstractSyntaxTree/Program.java +++ b/Source/abstractSyntaxTree/Program.java @@ -10,8 +10,8 @@ import java.util.List; public class Program { public List classes; - public HashMap> typeContext; // (class, (type, identifier)) - public HashMap>> methodContext; // (class, (returntype, (identifier, parameter))) + public HashMap> attributContext; // (class, (type, identifier)) + public HashMap>>> methodContext; // (class, (returntype, (identifier, parameter))) public TypeCheckResult typeCheck() throws Exception{ for(RefType oneClass : classes){ From 93514e4f0802f14b50f4ca1aa5677be94dcefee0 Mon Sep 17 00:00:00 2001 From: Jochen Seyfried Date: Wed, 8 May 2024 13:51:20 +0200 Subject: [PATCH 08/10] Added TODOS for changes --- Source/abstractSyntaxTree/Class/MethodDecl.java | 1 + Source/abstractSyntaxTree/Program.java | 14 +++++++++++++- .../Statement/IfElseStatement.java | 2 +- .../abstractSyntaxTree/Statement/IfStatement.java | 2 +- .../Statement/ReturnStatement.java | 4 ++-- 5 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Source/abstractSyntaxTree/Class/MethodDecl.java b/Source/abstractSyntaxTree/Class/MethodDecl.java index fce967a..5005324 100644 --- a/Source/abstractSyntaxTree/Class/MethodDecl.java +++ b/Source/abstractSyntaxTree/Class/MethodDecl.java @@ -11,6 +11,7 @@ public class MethodDecl implements IClass { private HashMap>> methodContext; private HashMap> typeContext; + //TODO: Move this into the typeCheck private HashMap localVars; // (type, identifier) // add content here public MethodDecl(HashMap>> methodContext, HashMap> typeContext){ diff --git a/Source/abstractSyntaxTree/Program.java b/Source/abstractSyntaxTree/Program.java index 0c9aa5d..6df43b2 100644 --- a/Source/abstractSyntaxTree/Program.java +++ b/Source/abstractSyntaxTree/Program.java @@ -3,7 +3,9 @@ package abstractSyntaxTree; import TypeCheck.TypeCheckResult; import abstractSyntaxTree.Class.FieldDecl; import abstractSyntaxTree.Datatype.RefType; +import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; import java.util.HashMap; import java.util.List; @@ -11,7 +13,10 @@ import java.util.List; public class Program { public List classes; + //TODO: Rename typeContext to attributeContext or something public HashMap> typeContext; // (class, (type, identifier)) + + //TODO: Change Data structure and make parameter a list public HashMap>> methodContext; // (class, (returntype, (identifier, parameter))) public TypeCheckResult typeCheck() throws Exception{ @@ -26,7 +31,14 @@ public class Program { public void codeGen() throws Exception{ for(RefType oneClass : classes){ - oneClass.codeGen(); + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); + cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, "oneClass.className", + null, "java/lang/Object", null); + oneClass.codeGen(cw); + cw.visitEnd(); + byte[] bytecode = cw.toByteArray(); + + //Write the bytecode to a .class file } } } diff --git a/Source/abstractSyntaxTree/Statement/IfElseStatement.java b/Source/abstractSyntaxTree/Statement/IfElseStatement.java index cd0fe10..d8ac01e 100644 --- a/Source/abstractSyntaxTree/Statement/IfElseStatement.java +++ b/Source/abstractSyntaxTree/Statement/IfElseStatement.java @@ -43,7 +43,7 @@ public class IfElseStatement extends AbstractType implements IStatement{ Label conditionFalse = new Label(); Label statementEnd = new Label(); - condition.CodeGen(mv); + condition.codeGen(mv); mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); //Checks if the condition is false (0) ifStatement.codeGen(mv); //If the condition is true, execute the ifBlock diff --git a/Source/abstractSyntaxTree/Statement/IfStatement.java b/Source/abstractSyntaxTree/Statement/IfStatement.java index 665f4f1..1c8461c 100644 --- a/Source/abstractSyntaxTree/Statement/IfStatement.java +++ b/Source/abstractSyntaxTree/Statement/IfStatement.java @@ -35,7 +35,7 @@ public class IfStatement extends AbstractType implements IStatement{ Label conditionFalse = new Label(); - condition.CodeGen(mv); + condition.codeGen(mv); mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); //Checks if the condition is false (0) ifStatement.codeGen(mv); diff --git a/Source/abstractSyntaxTree/Statement/ReturnStatement.java b/Source/abstractSyntaxTree/Statement/ReturnStatement.java index 0005827..976de6e 100644 --- a/Source/abstractSyntaxTree/Statement/ReturnStatement.java +++ b/Source/abstractSyntaxTree/Statement/ReturnStatement.java @@ -34,11 +34,11 @@ public class ReturnStatement extends AbstractType implements IStatement{ public void codeGen(MethodVisitor mv) throws Exception { if (expression != null) { - expression.CodeGen(mv); + expression.codeGen(mv); //Get the Type of the expression String type = expression.typeCheck().type; - if (type.equals("int") || type.equals("bool")) { + if (type.equals("int") || type.equals("bool") || type.equals("char")) { mv.visitInsn(Opcodes.IRETURN); } else { mv.visitInsn(Opcodes.ARETURN); From 3cff3982286f538feaff9ed4859cf8b09050648b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krau=C3=9F=2C=20Josefine?= Date: Wed, 8 May 2024 13:51:36 +0200 Subject: [PATCH 09/10] delete modifier --- Source/abstractSyntaxTree/Modifier/IModifier.java | 11 ----------- .../abstractSyntaxTree/Modifier/PrivateModifier.java | 4 ---- .../abstractSyntaxTree/Modifier/PublicModifier.java | 4 ---- 3 files changed, 19 deletions(-) delete mode 100644 Source/abstractSyntaxTree/Modifier/IModifier.java delete mode 100644 Source/abstractSyntaxTree/Modifier/PrivateModifier.java delete mode 100644 Source/abstractSyntaxTree/Modifier/PublicModifier.java diff --git a/Source/abstractSyntaxTree/Modifier/IModifier.java b/Source/abstractSyntaxTree/Modifier/IModifier.java deleted file mode 100644 index e8c98ab..0000000 --- a/Source/abstractSyntaxTree/Modifier/IModifier.java +++ /dev/null @@ -1,11 +0,0 @@ -package abstractSyntaxTree.Modifier; - -public interface IModifier { - - //TODO: Maybe we can just use an enum for the Modifier - // if there is no typeCheck and no CodeGen - - // not type or type check - - // visit method for code generation -} diff --git a/Source/abstractSyntaxTree/Modifier/PrivateModifier.java b/Source/abstractSyntaxTree/Modifier/PrivateModifier.java deleted file mode 100644 index 3a51ce6..0000000 --- a/Source/abstractSyntaxTree/Modifier/PrivateModifier.java +++ /dev/null @@ -1,4 +0,0 @@ -package abstractSyntaxTree.Modifier; - -public class PrivateModifier implements IModifier{ -} diff --git a/Source/abstractSyntaxTree/Modifier/PublicModifier.java b/Source/abstractSyntaxTree/Modifier/PublicModifier.java deleted file mode 100644 index ebc0bab..0000000 --- a/Source/abstractSyntaxTree/Modifier/PublicModifier.java +++ /dev/null @@ -1,4 +0,0 @@ -package abstractSyntaxTree.Modifier; - -public class PublicModifier implements IModifier{ -} From 56ee3602b500f6588dabb26d484c23c95ac6f62d Mon Sep 17 00:00:00 2001 From: Jochen Seyfried Date: Wed, 8 May 2024 13:53:43 +0200 Subject: [PATCH 10/10] Added ASM lib --- Lib/asm-9.7.jar | Bin 0 -> 125428 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Lib/asm-9.7.jar diff --git a/Lib/asm-9.7.jar b/Lib/asm-9.7.jar new file mode 100644 index 0000000000000000000000000000000000000000..fee9b028a3364169c659f6072ed53f9f09cb524d GIT binary patch literal 125428 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 XdO}IU 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 literal 0 HcmV?d00001