From ebeedf1e338038646664b68408269f869315c622 Mon Sep 17 00:00:00 2001 From: MontysCoconut Date: Wed, 24 Sep 2014 12:40:08 +0200 Subject: [PATCH] Initial commit --- .gitignore | 48 + COPYING | 674 +++++++ COPYING_EXCEPTION | 18 + COPYING_HEADER | 38 + README.md | 70 + pom.xml | 281 +++ .../de/uni/bremen/monty/moco/antlr/Monty.g4 | 228 +++ src/main/antlr4/imports/lex.g4 | 247 +++ .../java/de/uni/bremen/monty/moco/Main.java | 152 ++ .../uni/bremen/monty/moco/ast/ASTBuilder.java | 644 +++++++ .../de/uni/bremen/monty/moco/ast/ASTNode.java | 77 + .../bremen/monty/moco/ast/AccessModifier.java | 62 + .../bremen/monty/moco/ast/AntlrAdapter.java | 78 + .../bremen/monty/moco/ast/BasicASTNode.java | 109 ++ .../de/uni/bremen/monty/moco/ast/Block.java | 119 ++ .../uni/bremen/monty/moco/ast/ClassScope.java | 159 ++ .../bremen/monty/moco/ast/CoreClasses.java | 102 ++ .../uni/bremen/monty/moco/ast/Identifier.java | 93 + .../de/uni/bremen/monty/moco/ast/Import.java | 70 + .../de/uni/bremen/monty/moco/ast/Package.java | 109 ++ .../bremen/monty/moco/ast/PackageBuilder.java | 157 ++ .../uni/bremen/monty/moco/ast/Position.java | 96 + .../monty/moco/ast/ResolvableIdentifier.java | 57 + .../de/uni/bremen/monty/moco/ast/Scope.java | 202 +++ .../ast/declaration/ClassDeclaration.java | 188 ++ .../moco/ast/declaration/Declaration.java | 99 + .../ast/declaration/FunctionDeclaration.java | 148 ++ .../ast/declaration/ModuleDeclaration.java | 101 ++ .../ast/declaration/ProcedureDeclaration.java | 184 ++ .../moco/ast/declaration/TypeDeclaration.java | 67 + .../ast/declaration/VariableDeclaration.java | 151 ++ .../moco/ast/expression/CastExpression.java | 73 + .../ast/expression/ConditionalExpression.java | 92 + .../monty/moco/ast/expression/Expression.java | 74 + .../moco/ast/expression/FunctionCall.java | 106 ++ .../moco/ast/expression/IsExpression.java | 82 + .../moco/ast/expression/MemberAccess.java | 82 + .../moco/ast/expression/ParentExpression.java | 75 + .../moco/ast/expression/SelfExpression.java | 58 + .../moco/ast/expression/VariableAccess.java | 107 ++ .../ast/expression/literal/ArrayLiteral.java | 78 + .../expression/literal/BooleanLiteral.java | 56 + .../expression/literal/CharacterLiteral.java | 56 + .../ast/expression/literal/FloatLiteral.java | 56 + .../expression/literal/IntegerLiteral.java | 56 + .../expression/literal/LiteralExpression.java | 60 + .../ast/expression/literal/StringLiteral.java | 56 + .../monty/moco/ast/statement/Assignment.java | 94 + .../moco/ast/statement/BreakStatement.java | 75 + .../ast/statement/ConditionalStatement.java | 103 ++ .../moco/ast/statement/ContinueStatement.java | 66 + .../moco/ast/statement/RaiseStatement.java | 63 + .../moco/ast/statement/ReturnStatement.java | 80 + .../moco/ast/statement/SkipStatement.java | 71 + .../monty/moco/ast/statement/Statement.java | 46 + .../moco/ast/statement/TryStatement.java | 80 + .../monty/moco/ast/statement/WhileLoop.java | 91 + .../moco/codegeneration/CodeGenerator.java | 584 ++++++ .../monty/moco/codegeneration/CodeWriter.java | 84 + .../monty/moco/codegeneration/Native.java | 51 + .../codegeneration/context/CodeContext.java | 452 +++++ .../context/CommentAppender.java | 78 + .../moco/codegeneration/context/Context.java | 104 ++ .../codegeneration/context/ContextData.java | 43 + .../codegeneration/context/ContextUtils.java | 123 ++ .../codegeneration/context/Operations.java | 334 ++++ .../codegeneration/context/StringData.java | 52 + .../identifier/ArrayConstant.java | 64 + .../identifier/FunctionSignature.java | 59 + .../identifier/LLVMIdentifier.java | 96 + .../identifier/LLVMIdentifierFactory.java | 165 ++ .../identifier/StructConstant.java | 64 + .../codegeneration/types/LLVMArrayType.java | 84 + .../types/LLVMFunctionType.java | 83 + .../codegeneration/types/LLVMPointer.java | 74 + .../codegeneration/types/LLVMSimpleType.java | 72 + .../codegeneration/types/LLVMStructType.java | 72 + .../moco/codegeneration/types/LLVMType.java | 61 + .../codegeneration/types/LLVMTypeFactory.java | 154 ++ .../codegeneration/types/TypeConverter.java | 217 +++ .../codegeneration/voodoo/BlackMagic.java | 93 + .../InvalidControlFlowException.java | 47 + .../exception/InvalidExpressionException.java | 47 + .../InvalidPlaceToDeclareException.java | 47 + .../moco/exception/MontyBaseException.java | 59 + .../exception/NotYetImplementedException.java | 49 + .../exception/RedeclarationException.java | 47 + .../moco/exception/TypeMismatchException.java | 47 + .../exception/UnknownIdentifierException.java | 48 + .../moco/exception/UnknownTypeException.java | 48 + .../uni/bremen/monty/moco/util/MontyFile.java | 87 + .../uni/bremen/monty/moco/util/MontyJar.java | 126 ++ .../bremen/monty/moco/util/MontyResource.java | 54 + .../de/uni/bremen/monty/moco/util/Params.java | 146 ++ .../monty/moco/util/ParseTreePrinter.java | 127 ++ .../monty/moco/visitor/BaseVisitor.java | 449 +++++ .../moco/visitor/CodeGenerationVisitor.java | 643 +++++++ .../moco/visitor/ControlFlowVisitor.java | 168 ++ .../moco/visitor/DeclarationVisitor.java | 204 +++ .../moco/visitor/NameManglingVisitor.java | 308 ++++ .../monty/moco/visitor/PrintVisitor.java | 136 ++ .../monty/moco/visitor/ResolveVisitor.java | 356 ++++ .../monty/moco/visitor/SetParentVisitor.java | 59 + .../monty/moco/visitor/TypeCheckVisitor.java | 278 +++ .../monty/moco/visitor/VisitOnceVisitor.java | 321 ++++ src/main/resources/ast.png | Bin 0 -> 135714 bytes src/main/resources/checkstyle.xml | 183 ++ src/main/resources/corelib/Array.monty | 2 + src/main/resources/corelib/Bool.monty | 21 + src/main/resources/corelib/Char.monty | 3 + src/main/resources/corelib/Float.monty | 36 + src/main/resources/corelib/Int.monty | 39 + src/main/resources/corelib/Object.monty | 2 + src/main/resources/corelib/Print.monty | 14 + src/main/resources/find-missing-license.sh | 16 + src/main/resources/java-code-conv.xml | 291 +++ src/main/resources/log4j.properies | 1 + src/main/resources/moco-code-conv.xml | 295 +++ src/main/resources/rm_trailing_whitespace.sh | 17 + src/main/resources/std_llvm_include.ll | 57 + src/site/site.xml | 18 + .../monty/moco/CompileFilesBaseTest.java | 96 + .../moco/CompileLatestTestProgramsTest.java | 94 + .../monty/moco/CompileTestProgramsTest.java | 91 + .../monty/moco/IntegrationTestUtils.java | 106 ++ .../bremen/monty/moco/ModuleProgramsTest.java | 77 + .../bremen/monty/moco/ast/ASTBuilderTest.java | 270 +++ .../monty/moco/ast/ControlFlowTest.java | 894 +++++++++ .../monty/moco/ast/DeclarationTest.java | 971 ++++++++++ .../bremen/monty/moco/ast/TypeCheckTest.java | 1611 +++++++++++++++++ .../moco/codegeneration/ContextTest.java | 113 ++ .../monty/moco/util/MultiOutputStream.java | 57 + .../testAstBuilder/declarationType.monty | 19 + .../resources/testAstBuilder/ifElse.monty | 30 + .../resources/testAstBuilder/varDecl.monty | 1 + .../de/dafuq/monty/HelloSayer.monty | 11 + .../de/dafuq/monty/Main.monty | 13 + .../de/dafuq/monty/Main.output | 1 + .../resources/testPrograms/CorePackage.monty | 5 + .../resources/testPrograms/CorePackage.output | 1 + .../array/ArrayEmptyInit.monty.ignore | 7 + .../testPrograms/array/ArrayEmptyInit.output | 0 .../testPrograms/array/ArrayEmptyRead.error | 0 .../array/ArrayEmptyRead.monty.ignore | 8 + .../testPrograms/array/ArrayEmptyWrite.error | 0 .../array/ArrayEmptyWrite.monty.ignore | 8 + .../testPrograms/array/ArrayMany.monty.ignore | 25 + .../testPrograms/array/ArrayMany.output | 1 + .../testPrograms/array/ArrayOne.monty.ignore | 10 + .../testPrograms/array/ArrayOne.output | 1 + .../array/ArrayOutOfBounds1.error | 0 .../array/ArrayOutOfBounds1.monty.ignore | 8 + .../array/ArrayOutOfBounds2.error | 0 .../array/ArrayOutOfBounds2.monty.ignore | 8 + .../array/ArrayOutOfBounds3.error | 0 .../array/ArrayOutOfBounds3.monty.ignore | 8 + .../array/ArrayOutOfBounds4.error | 0 .../array/ArrayOutOfBounds4.monty.ignore | 8 + .../testPrograms/array/ArrayTwo.monty.ignore | 13 + .../testPrograms/array/ArrayTwo.output | 1 + .../testPrograms/callable/Function.monty | 11 + .../testPrograms/callable/Function.output | 1 + .../testPrograms/callable/Function1.monty | 11 + .../testPrograms/callable/Function1.output | 1 + .../testPrograms/callable/Function2.monty | 21 + .../testPrograms/callable/Function2.output | 1 + .../testPrograms/callable/Function3.monty | 20 + .../testPrograms/callable/Function3.output | 1 + .../testPrograms/callable/Function4.monty | 19 + .../testPrograms/callable/Function4.output | 1 + .../callable/FunctionGlobalLocalBoolean.monty | 12 + .../FunctionGlobalLocalBoolean.output | 1 + .../callable/FunctionGlobalLocalFloat.monty | 12 + .../callable/FunctionGlobalLocalFloat.output | 1 + .../callable/FunctionGlobalLocalInt.monty | 12 + .../callable/FunctionGlobalLocalInt.output | 1 + .../callable/FunctionGlobalLocalString.monty | 12 + .../callable/FunctionGlobalLocalString.output | 1 + .../testPrograms/callable/Procedure.monty | 17 + .../testPrograms/callable/Procedure.output | 1 + .../defaultParameter/DefaultFunction1.monty | 11 + .../defaultParameter/DefaultFunction1.output | 1 + .../defaultParameter/DefaultFunction2.monty | 11 + .../defaultParameter/DefaultFunction2.output | 1 + .../defaultParameter/DefaultFunction3.monty | 13 + .../defaultParameter/DefaultFunction3.output | 1 + .../defaultParameter/DefaultFunction4.monty | 21 + .../defaultParameter/DefaultFunction4.output | 1 + .../defaultParameter/DefaultFunction5.monty | 32 + .../defaultParameter/DefaultFunction5.output | 1 + .../defaultParameter/DefaultFunction6.monty | 33 + .../defaultParameter/DefaultFunction6.output | 1 + .../classes/ClassMemberBool1.monty | 15 + .../classes/ClassMemberBool1.output | 1 + .../classes/ClassMemberBool2.monty | 15 + .../classes/ClassMemberBool2.output | 1 + .../classes/ClassMemberBool3.monty | 17 + .../classes/ClassMemberBool3.output | 1 + .../classes/ClassMemberBool4.monty | 16 + .../classes/ClassMemberBool4.output | 1 + .../classes/ClassMemberChar1.monty | 15 + .../classes/ClassMemberChar1.output | 1 + .../classes/ClassMemberChar2.monty | 15 + .../classes/ClassMemberChar2.output | 1 + .../classes/ClassMemberChar3.monty | 17 + .../classes/ClassMemberChar3.output | 1 + .../classes/ClassMemberChar4.monty | 16 + .../classes/ClassMemberChar4.output | 1 + .../classes/ClassMemberComplex1.monty | 33 + .../classes/ClassMemberComplex1.output | 1 + .../classes/ClassMemberComplex2.monty | 20 + .../classes/ClassMemberComplex2.output | 1 + .../classes/ClassMemberComplex3.monty | 22 + .../classes/ClassMemberComplex3.output | 1 + .../classes/ClassMemberFloat1.monty | 15 + .../classes/ClassMemberFloat1.output | 1 + .../classes/ClassMemberFloat2.monty | 15 + .../classes/ClassMemberFloat2.output | 1 + .../classes/ClassMemberFloat3.monty | 17 + .../classes/ClassMemberFloat3.output | 1 + .../classes/ClassMemberFloat4.monty | 16 + .../classes/ClassMemberFloat4.output | 1 + .../classes/ClassMemberInt1.monty | 15 + .../classes/ClassMemberInt1.output | 1 + .../classes/ClassMemberInt2.monty | 15 + .../classes/ClassMemberInt2.output | 1 + .../classes/ClassMemberInt3.monty | 17 + .../classes/ClassMemberInt3.output | 1 + .../classes/ClassMemberInt4.monty | 16 + .../classes/ClassMemberInt4.output | 1 + .../classes/ClassMemberString1.monty | 15 + .../classes/ClassMemberString1.output | 1 + .../classes/ClassMemberString2.monty | 15 + .../classes/ClassMemberString2.output | 1 + .../classes/ClassMemberString3.monty | 17 + .../classes/ClassMemberString3.output | 1 + .../classes/ClassMemberString4.monty | 16 + .../classes/ClassMemberString4.output | 1 + .../testPrograms/classes/ClassPointer1.monty | 31 + .../testPrograms/classes/ClassPointer1.output | 1 + .../testPrograms/classes/ClassPointer2.monty | 26 + .../testPrograms/classes/ClassPointer2.output | 1 + .../classes/constructor/Constructor1.monty | 13 + .../classes/constructor/Constructor1.output | 1 + .../classes/constructor/Constructor2.monty | 11 + .../classes/constructor/Constructor2.output | 1 + .../classes/constructor/Constructor3.monty | 12 + .../classes/constructor/Constructor3.output | 1 + .../classes/constructor/Constructor4.monty | 15 + .../classes/constructor/Constructor4.output | 1 + .../classes/constructor/Constructor5.monty | 15 + .../classes/constructor/Constructor5.output | 1 + .../classes/constructor/Constructor6.monty | 16 + .../classes/constructor/Constructor6.output | 1 + .../classes/constructor/Constructor7.monty | 24 + .../classes/constructor/Constructor7.output | 1 + .../classes/methods/Methods1.monty | 29 + .../classes/methods/Methods1.output | 1 + .../classes/methods/Methods2.monty | 20 + .../classes/methods/Methods2.output | 1 + .../classes/methods/Methods3.monty | 23 + .../classes/methods/Methods3.output | 1 + .../classes/methods/Methods4.monty | 22 + .../classes/methods/Methods4.output | 1 + .../classes/methods/Methods5.monty | 36 + .../classes/methods/Methods5.output | 1 + .../compoundAssignments/Div.monty | 9 + .../compoundAssignments/Div.output | 1 + .../compoundAssignments/Div1.monty | 10 + .../compoundAssignments/Div1.output | 1 + .../compoundAssignments/Minus.monty | 9 + .../compoundAssignments/Minus.output | 1 + .../compoundAssignments/Minus1.monty | 9 + .../compoundAssignments/Minus1.output | 1 + .../compoundAssignments/Mod.monty | 9 + .../compoundAssignments/Mod.output | 1 + .../compoundAssignments/Mod1.monty | 10 + .../compoundAssignments/Mod1.output | 1 + .../compoundAssignments/Mult.monty | 9 + .../compoundAssignments/Mult.output | 1 + .../compoundAssignments/Mult1.monty | 10 + .../compoundAssignments/Mult1.output | 1 + .../compoundAssignments/Plus.monty | 9 + .../compoundAssignments/Plus.output | 1 + .../compoundAssignments/Plus1.monty | 10 + .../compoundAssignments/Plus1.output | 1 + .../compoundAssignments/Power.monty.ignore | 9 + .../compoundAssignments/Power.output | 1 + .../compoundAssignments/Power1.monty.ignore | 10 + .../compoundAssignments/Power1.output | 1 + .../ConditionalStatementComplex.monty | 13 + .../ConditionalStatementComplex.output | 1 + .../ConditionalStatementFalse.monty | 10 + .../ConditionalStatementFalse.output | 0 .../ConditionalStatementTrue.monty | 10 + .../ConditionalStatementTrue.output | 1 + .../testPrograms/controlflow/Ifelse1.monty | 19 + .../testPrograms/controlflow/Ifelse1.output | 1 + .../testPrograms/controlflow/Ifelse2.monty | 33 + .../testPrograms/controlflow/Ifelse2.output | 1 + .../controlflow/WhileLoopBreak1.monty | 12 + .../controlflow/WhileLoopBreak1.output | 1 + .../controlflow/WhileLoopFalse.monty | 11 + .../controlflow/WhileLoopFalse.output | 1 + .../controlflow/WhileLoopSimple.monty | 13 + .../controlflow/WhileLoopSimple.output | 1 + .../controlflow/WhileLoopSkip1.monty | 17 + .../controlflow/WhileLoopSkip1.output | 1 + .../expressions/BinaryOperatorAdd1.monty | 11 + .../expressions/BinaryOperatorAdd1.output | 1 + .../expressions/BinaryOperatorAdd2.monty | 10 + .../expressions/BinaryOperatorAdd2.output | 1 + .../expressions/BinaryOperatorAnd1.monty | 11 + .../expressions/BinaryOperatorAnd1.output | 1 + .../expressions/BinaryOperatorDiv1.monty | 10 + .../expressions/BinaryOperatorDiv1.output | 1 + .../expressions/BinaryOperatorDiv2.monty | 10 + .../expressions/BinaryOperatorDiv2.output | 1 + .../expressions/BinaryOperatorEquals1.monty | 11 + .../expressions/BinaryOperatorEquals1.output | 1 + .../expressions/BinaryOperatorEquals2.monty | 12 + .../expressions/BinaryOperatorEquals2.output | 1 + .../expressions/BinaryOperatorEquals3.monty | 13 + .../expressions/BinaryOperatorEquals3.output | 1 + .../BinaryOperatorEqualsNot1.monty | 11 + .../BinaryOperatorEqualsNot1.output | 1 + .../BinaryOperatorEqualsNot2.monty | 11 + .../BinaryOperatorEqualsNot2.output | 1 + .../BinaryOperatorEqualsNot3.monty | 13 + .../BinaryOperatorEqualsNot3.output | 1 + .../expressions/BinaryOperatorGreater1.monty | 9 + .../expressions/BinaryOperatorGreater1.output | 1 + .../expressions/BinaryOperatorGreater2.monty | 10 + .../expressions/BinaryOperatorGreater2.output | 1 + .../BinaryOperatorGreaterEqual1.monty | 9 + .../BinaryOperatorGreaterEqual1.output | 1 + .../BinaryOperatorGreaterEqual2.monty | 9 + .../BinaryOperatorGreaterEqual2.output | 1 + .../expressions/BinaryOperatorLess1.monty | 9 + .../expressions/BinaryOperatorLess1.output | 1 + .../expressions/BinaryOperatorLess2.monty | 10 + .../expressions/BinaryOperatorLess2.output | 1 + .../BinaryOperatorLessEqual1.monty | 9 + .../BinaryOperatorLessEqual1.output | 1 + .../BinaryOperatorLessEqual2.monty | 9 + .../BinaryOperatorLessEqual2.output | 1 + .../expressions/BinaryOperatorModulo1.monty | 11 + .../expressions/BinaryOperatorModulo1.output | 1 + .../expressions/BinaryOperatorMul1.monty | 11 + .../expressions/BinaryOperatorMul1.output | 1 + .../expressions/BinaryOperatorMul2.monty | 11 + .../expressions/BinaryOperatorMul2.output | 1 + .../expressions/BinaryOperatorOr1.monty | 11 + .../expressions/BinaryOperatorOr1.output | 1 + .../expressions/BinaryOperatorSub1.monty | 10 + .../expressions/BinaryOperatorSub1.output | 1 + .../expressions/BinaryOperatorSub2.monty | 10 + .../expressions/BinaryOperatorSub2.output | 1 + .../expressions/BinaryOperatorXor1.monty | 11 + .../expressions/BinaryOperatorXor1.output | 1 + .../ConditionalExpressionComplex.monty | 27 + .../ConditionalExpressionComplex.output | 1 + .../ConditionalExpressionFalse1.monty | 7 + .../ConditionalExpressionFalse1.output | 1 + .../ConditionalExpressionFalse2.monty | 9 + .../ConditionalExpressionFalse2.output | 1 + .../ConditionalExpressionFalse3.monty | 9 + .../ConditionalExpressionFalse3.output | 1 + .../ConditionalExpressionTrue1.monty | 7 + .../ConditionalExpressionTrue1.output | 1 + .../ConditionalExpressionTrue2.monty | 9 + .../ConditionalExpressionTrue2.output | 1 + .../ConditionalExpressionTrue3.monty | 9 + .../ConditionalExpressionTrue3.output | 1 + .../expressions/SelfDefinedOperators.monty | 93 + .../expressions/SelfDefinedOperators.output | 1 + .../expressions/UnaryOperatorMinus1.monty | 11 + .../expressions/UnaryOperatorMinus1.output | 1 + .../expressions/UnaryOperatorMinus2.monty | 11 + .../expressions/UnaryOperatorMinus2.output | 1 + .../expressions/UnaryOperatorNot1.monty | 8 + .../expressions/UnaryOperatorNot1.output | 1 + .../casting/ClassInheritedCast1.monty | 20 + .../casting/ClassInheritedCast1.output | 1 + .../casting/ClassInheritedCast2.error | 0 .../casting/ClassInheritedCast2.monty | 21 + .../casting/ClassInheritedUpcast1.monty | 21 + .../casting/ClassInheritedUpcast1.output | 1 + .../casting/ClassInheritedUpcast2.monty | 24 + .../casting/ClassInheritedUpcast2.output | 1 + .../casting/ClassInheritedUpcast3.monty | 25 + .../casting/ClassInheritedUpcast3.output | 1 + .../constructor/ConstructorInheritance1.monty | 17 + .../ConstructorInheritance1.output | 1 + .../constructor/ConstructorInheritance2.monty | 16 + .../ConstructorInheritance2.output | 1 + .../constructor/ConstructorInheritance3.monty | 17 + .../ConstructorInheritance3.output | 1 + .../constructor/ConstructorInheritance4.monty | 19 + .../ConstructorInheritance4.output | 1 + .../inheritance/is/ClassInheritedIs1.monty | 15 + .../inheritance/is/ClassInheritedIs1.output | 1 + .../inheritance/is/ClassInheritedIs2.monty | 18 + .../inheritance/is/ClassInheritedIs2.output | 1 + .../inheritance/is/ClassInheritedIs3.monty | 18 + .../inheritance/is/ClassInheritedIs3.output | 1 + .../member/ClassInheritedMemberBool1.monty | 19 + .../member/ClassInheritedMemberBool1.output | 1 + .../member/ClassInheritedMemberBool2.monty | 19 + .../member/ClassInheritedMemberBool2.output | 1 + .../member/ClassInheritedMemberBool3.monty | 21 + .../member/ClassInheritedMemberBool3.output | 1 + .../member/ClassInheritedMemberBool4.monty | 20 + .../member/ClassInheritedMemberBool4.output | 1 + .../member/ClassInheritedMemberChar1.monty | 19 + .../member/ClassInheritedMemberChar1.output | 1 + .../member/ClassInheritedMemberChar2.monty | 19 + .../member/ClassInheritedMemberChar2.output | 1 + .../member/ClassInheritedMemberChar3.monty | 21 + .../member/ClassInheritedMemberChar3.output | 1 + .../member/ClassInheritedMemberChar4.monty | 20 + .../member/ClassInheritedMemberChar4.output | 1 + .../member/ClassInheritedMemberComplex1.monty | 25 + .../ClassInheritedMemberComplex1.output | 1 + .../member/ClassInheritedMemberComplex2.monty | 26 + .../ClassInheritedMemberComplex2.output | 1 + .../member/ClassInheritedMemberFloat1.monty | 19 + .../member/ClassInheritedMemberFloat1.output | 1 + .../member/ClassInheritedMemberFloat2.monty | 19 + .../member/ClassInheritedMemberFloat2.output | 1 + .../member/ClassInheritedMemberFloat3.monty | 21 + .../member/ClassInheritedMemberFloat3.output | 1 + .../member/ClassInheritedMemberFloat4.monty | 20 + .../member/ClassInheritedMemberFloat4.output | 1 + .../member/ClassInheritedMemberInt1.monty | 19 + .../member/ClassInheritedMemberInt1.output | 1 + .../member/ClassInheritedMemberInt2.monty | 19 + .../member/ClassInheritedMemberInt2.output | 1 + .../member/ClassInheritedMemberInt3.monty | 21 + .../member/ClassInheritedMemberInt3.output | 1 + .../member/ClassInheritedMemberInt4.monty | 20 + .../member/ClassInheritedMemberInt4.output | 1 + .../member/ClassInheritedMemberString1.monty | 19 + .../member/ClassInheritedMemberString1.output | 1 + .../member/ClassInheritedMemberString2.monty | 19 + .../member/ClassInheritedMemberString2.output | 1 + .../member/ClassInheritedMemberString3.monty | 21 + .../member/ClassInheritedMemberString3.output | 1 + .../member/ClassInheritedMemberString4.monty | 20 + .../member/ClassInheritedMemberString4.output | 1 + .../methods/InheritanceMethods1.monty | 26 + .../methods/InheritanceMethods1.output | 1 + .../methods/InheritanceMethods2.monty | 24 + .../methods/InheritanceMethods2.output | 1 + .../testPrograms/literals/BoolAsObject.monty | 11 + .../testPrograms/literals/BoolAsObject.output | 1 + .../literals/BoolConstructor.monty | 11 + .../literals/BoolConstructor.output | 1 + .../testPrograms/literals/BoolIsObject.monty | 17 + .../testPrograms/literals/BoolIsObject.output | 1 + .../testPrograms/literals/CharAsObject.monty | 10 + .../testPrograms/literals/CharAsObject.output | 1 + .../literals/CharConstructor.monty | 9 + .../literals/CharConstructor.output | 1 + .../testPrograms/literals/CharIsObject.monty | 17 + .../testPrograms/literals/CharIsObject.output | 1 + .../testPrograms/literals/FloatAsObject.monty | 12 + .../literals/FloatAsObject.output | 1 + .../literals/FloatConstructor.monty | 11 + .../literals/FloatConstructor.output | 1 + .../testPrograms/literals/FloatIsObject.monty | 17 + .../literals/FloatIsObject.output | 1 + .../testPrograms/literals/IntAsObject.monty | 12 + .../testPrograms/literals/IntAsObject.output | 1 + .../literals/IntConstructor.monty | 11 + .../literals/IntConstructor.output | 1 + .../testPrograms/literals/IntIsObject.monty | 17 + .../testPrograms/literals/IntIsObject.output | 1 + .../negativ/IdentifierNotDefined.error | 1 + .../negativ/IdentifierNotDefined.monty | 7 + .../negativ/callable/neg_Function1.error | 1 + .../negativ/callable/neg_Function1.monty | 10 + .../negativ/callable/neg_Function2.error | 1 + .../negativ/callable/neg_Function2.monty | 8 + .../negativ/callable/neg_Function3.error | 1 + .../negativ/callable/neg_Function3.monty | 9 + .../negativ/callable/neg_Function4.error | 1 + .../callable/neg_Function4.monty.ignore | 17 + .../negativ/callable/neg_Procedure1.error | 1 + .../negativ/callable/neg_Procedure1.monty | 9 + .../negativ/callable/neg_Procedure2.error | 1 + .../negativ/callable/neg_Procedure2.monty | 13 + .../scoping/RedeclarationOtherType.error | 1 + .../scoping/RedeclarationOtherType.monty | 9 + .../scoping/RedeclarationSameType.error | 1 + .../scoping/RedeclarationSameType.monty | 8 + .../negativ/scoping/VariableAccess.error | 1 + .../negativ/scoping/VariableAccess.monty | 9 + .../negativ/scoping/VariableAccess2.error | 1 + .../negativ/scoping/VariableAccess2.monty | 13 + .../negativ/scoping/VariableAccess3.error | 1 + .../negativ/scoping/VariableAccess3.monty | 8 + .../negativ/scoping/VariableAccess4.error | 1 + .../negativ/scoping/VariableAccess4.monty | 8 + .../negativ/scoping/VariableAccess5.error | 1 + .../scoping/VariableAccess5.monty.ignore | 12 + .../negativ/scoping/VariableAccess6.error | 1 + .../negativ/scoping/VariableAccess6.monty | 15 + .../testPrograms/object/Object1.monty | 7 + .../testPrograms/object/Object1.output | 0 .../testPrograms/object/Object2.monty | 10 + .../testPrograms/object/Object2.output | 0 .../testPrograms/object/Object3.monty | 10 + .../testPrograms/object/Object3.output | 0 .../testPrograms/object/Object4.monty | 12 + .../testPrograms/object/Object4.output | 1 + .../overloading/OverloadingConstructor1.monty | 50 + .../OverloadingConstructor1.output | 1 + .../overloading/OverloadingFunction1.monty | 47 + .../overloading/OverloadingFunction1.output | 1 + .../overloading/OverloadingFunction2.monty | 37 + .../overloading/OverloadingFunction2.output | 1 + .../overloading/OverloadingFunction3.monty | 28 + .../overloading/OverloadingFunction3.output | 1 + .../overloading/OverloadingProcedure1.monty | 38 + .../overloading/OverloadingProcedure1.output | 1 + .../overloading/OverloadingProcedure2.monty | 31 + .../overloading/OverloadingProcedure2.output | 1 + .../overloading/OverloadingProcedure3.monty | 26 + .../overloading/OverloadingProcedure3.output | 1 + .../testPrograms/print/PrintBoolean.monty | 6 + .../testPrograms/print/PrintBoolean.output | 1 + .../testPrograms/print/PrintChar.monty | 8 + .../testPrograms/print/PrintChar.output | 1 + .../testPrograms/print/PrintFloat.monty | 6 + .../testPrograms/print/PrintFloat.output | 1 + .../testPrograms/print/PrintInt.monty | 6 + .../testPrograms/print/PrintInt.output | 1 + .../testPrograms/print/PrintString.monty | 6 + .../testPrograms/print/PrintString.output | 1 + .../print/PrintVariableBoolean.monty | 6 + .../print/PrintVariableBoolean.output | 1 + .../print/PrintVariableChar.monty | 6 + .../print/PrintVariableChar.output | 1 + .../print/PrintVariableFloat.monty | 6 + .../print/PrintVariableFloat.output | 1 + .../testPrograms/print/PrintVariableInt.monty | 6 + .../print/PrintVariableInt.output | 1 + .../print/PrintVariableString.monty | 6 + .../print/PrintVariableString.output | 1 + .../testPrograms/print/PrintWhitespaces.monty | 11 + .../print/PrintWhitespaces.output | 1 + .../print/PrintWhitespaces2.monty.ignore | 15 + .../print/PrintWhitespaces2.output | 3 + .../testPrograms/scoping/Redeclaration.monty | 17 + .../testPrograms/scoping/Redeclaration.output | 1 + .../SimultaneouslyVisibleFunctions.monty | 14 + .../SimultaneouslyVisibleFunctions.output | 1 + .../SimultaneouslyVisibleObjects.monty | 15 + .../SimultaneouslyVisibleObjects.output | 1 + .../testPrograms/scoping/VariableAccess.monty | 13 + .../scoping/VariableAccess.output | 1 + .../variables/GlobalVariableBoolean1.monty | 13 + .../variables/GlobalVariableBoolean1.output | 1 + .../variables/GlobalVariableBoolean2.monty | 14 + .../variables/GlobalVariableBoolean2.output | 1 + .../variables/GlobalVariableChar1.monty | 13 + .../variables/GlobalVariableChar1.output | 1 + .../variables/GlobalVariableChar2.monty | 14 + .../variables/GlobalVariableChar2.output | 1 + .../variables/GlobalVariableFloat1.monty | 13 + .../variables/GlobalVariableFloat1.output | 1 + .../variables/GlobalVariableFloat2.monty | 14 + .../variables/GlobalVariableFloat2.output | 1 + .../variables/GlobalVariableInt1.monty | 13 + .../variables/GlobalVariableInt1.output | 1 + .../variables/GlobalVariableInt2.monty | 14 + .../variables/GlobalVariableInt2.output | 1 + .../variables/GlobalVariableString1.monty | 13 + .../variables/GlobalVariableString1.output | 1 + .../variables/GlobalVariableString2.monty | 14 + .../variables/GlobalVariableString2.output | 1 + 582 files changed, 22987 insertions(+) create mode 100644 .gitignore create mode 100644 COPYING create mode 100644 COPYING_EXCEPTION create mode 100644 COPYING_HEADER create mode 100644 README.md create mode 100644 pom.xml create mode 100644 src/main/antlr4/de/uni/bremen/monty/moco/antlr/Monty.g4 create mode 100644 src/main/antlr4/imports/lex.g4 create mode 100644 src/main/java/de/uni/bremen/monty/moco/Main.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/ASTBuilder.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/ASTNode.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/AccessModifier.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/AntlrAdapter.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/BasicASTNode.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/Block.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/ClassScope.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/CoreClasses.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/Identifier.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/Import.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/Package.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/PackageBuilder.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/Position.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/ResolvableIdentifier.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/Scope.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/declaration/ClassDeclaration.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/declaration/Declaration.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/declaration/FunctionDeclaration.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/declaration/ModuleDeclaration.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/declaration/ProcedureDeclaration.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/declaration/TypeDeclaration.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/declaration/VariableDeclaration.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/expression/CastExpression.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/expression/ConditionalExpression.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/expression/Expression.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/expression/FunctionCall.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/expression/IsExpression.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/expression/MemberAccess.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/expression/ParentExpression.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/expression/SelfExpression.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/expression/VariableAccess.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/ArrayLiteral.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/BooleanLiteral.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/CharacterLiteral.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/FloatLiteral.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/IntegerLiteral.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/LiteralExpression.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/StringLiteral.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/statement/Assignment.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/statement/BreakStatement.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/statement/ConditionalStatement.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/statement/ContinueStatement.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/statement/RaiseStatement.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/statement/ReturnStatement.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/statement/SkipStatement.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/statement/Statement.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/statement/TryStatement.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/ast/statement/WhileLoop.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/codegeneration/CodeGenerator.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/codegeneration/CodeWriter.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/codegeneration/Native.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/codegeneration/context/CodeContext.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/codegeneration/context/CommentAppender.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/codegeneration/context/Context.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/codegeneration/context/ContextData.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/codegeneration/context/ContextUtils.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/codegeneration/context/Operations.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/codegeneration/context/StringData.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/codegeneration/identifier/ArrayConstant.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/codegeneration/identifier/FunctionSignature.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/codegeneration/identifier/LLVMIdentifier.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/codegeneration/identifier/LLVMIdentifierFactory.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/codegeneration/identifier/StructConstant.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/codegeneration/types/LLVMArrayType.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/codegeneration/types/LLVMFunctionType.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/codegeneration/types/LLVMPointer.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/codegeneration/types/LLVMSimpleType.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/codegeneration/types/LLVMStructType.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/codegeneration/types/LLVMType.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/codegeneration/types/LLVMTypeFactory.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/codegeneration/types/TypeConverter.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/codegeneration/voodoo/BlackMagic.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/exception/InvalidControlFlowException.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/exception/InvalidExpressionException.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/exception/InvalidPlaceToDeclareException.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/exception/MontyBaseException.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/exception/NotYetImplementedException.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/exception/RedeclarationException.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/exception/TypeMismatchException.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/exception/UnknownIdentifierException.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/exception/UnknownTypeException.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/util/MontyFile.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/util/MontyJar.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/util/MontyResource.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/util/Params.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/util/ParseTreePrinter.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/visitor/BaseVisitor.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/visitor/CodeGenerationVisitor.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/visitor/ControlFlowVisitor.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/visitor/DeclarationVisitor.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/visitor/NameManglingVisitor.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/visitor/PrintVisitor.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/visitor/ResolveVisitor.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/visitor/SetParentVisitor.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/visitor/TypeCheckVisitor.java create mode 100644 src/main/java/de/uni/bremen/monty/moco/visitor/VisitOnceVisitor.java create mode 100644 src/main/resources/ast.png create mode 100644 src/main/resources/checkstyle.xml create mode 100644 src/main/resources/corelib/Array.monty create mode 100644 src/main/resources/corelib/Bool.monty create mode 100644 src/main/resources/corelib/Char.monty create mode 100644 src/main/resources/corelib/Float.monty create mode 100644 src/main/resources/corelib/Int.monty create mode 100644 src/main/resources/corelib/Object.monty create mode 100644 src/main/resources/corelib/Print.monty create mode 100755 src/main/resources/find-missing-license.sh create mode 100644 src/main/resources/java-code-conv.xml create mode 100644 src/main/resources/log4j.properies create mode 100644 src/main/resources/moco-code-conv.xml create mode 100755 src/main/resources/rm_trailing_whitespace.sh create mode 100644 src/main/resources/std_llvm_include.ll create mode 100644 src/site/site.xml create mode 100644 src/test/java/de/uni/bremen/monty/moco/CompileFilesBaseTest.java create mode 100644 src/test/java/de/uni/bremen/monty/moco/CompileLatestTestProgramsTest.java create mode 100644 src/test/java/de/uni/bremen/monty/moco/CompileTestProgramsTest.java create mode 100644 src/test/java/de/uni/bremen/monty/moco/IntegrationTestUtils.java create mode 100644 src/test/java/de/uni/bremen/monty/moco/ModuleProgramsTest.java create mode 100644 src/test/java/de/uni/bremen/monty/moco/ast/ASTBuilderTest.java create mode 100644 src/test/java/de/uni/bremen/monty/moco/ast/ControlFlowTest.java create mode 100644 src/test/java/de/uni/bremen/monty/moco/ast/DeclarationTest.java create mode 100644 src/test/java/de/uni/bremen/monty/moco/ast/TypeCheckTest.java create mode 100644 src/test/java/de/uni/bremen/monty/moco/codegeneration/ContextTest.java create mode 100644 src/test/java/de/uni/bremen/monty/moco/util/MultiOutputStream.java create mode 100644 src/test/resources/testAstBuilder/declarationType.monty create mode 100644 src/test/resources/testAstBuilder/ifElse.monty create mode 100644 src/test/resources/testAstBuilder/varDecl.monty create mode 100644 src/test/resources/testModuleProgramms/de/dafuq/monty/HelloSayer.monty create mode 100644 src/test/resources/testModuleProgramms/de/dafuq/monty/Main.monty create mode 100644 src/test/resources/testModuleProgramms/de/dafuq/monty/Main.output create mode 100644 src/test/resources/testPrograms/CorePackage.monty create mode 100644 src/test/resources/testPrograms/CorePackage.output create mode 100644 src/test/resources/testPrograms/array/ArrayEmptyInit.monty.ignore create mode 100644 src/test/resources/testPrograms/array/ArrayEmptyInit.output create mode 100644 src/test/resources/testPrograms/array/ArrayEmptyRead.error create mode 100644 src/test/resources/testPrograms/array/ArrayEmptyRead.monty.ignore create mode 100644 src/test/resources/testPrograms/array/ArrayEmptyWrite.error create mode 100644 src/test/resources/testPrograms/array/ArrayEmptyWrite.monty.ignore create mode 100644 src/test/resources/testPrograms/array/ArrayMany.monty.ignore create mode 100644 src/test/resources/testPrograms/array/ArrayMany.output create mode 100644 src/test/resources/testPrograms/array/ArrayOne.monty.ignore create mode 100644 src/test/resources/testPrograms/array/ArrayOne.output create mode 100644 src/test/resources/testPrograms/array/ArrayOutOfBounds1.error create mode 100644 src/test/resources/testPrograms/array/ArrayOutOfBounds1.monty.ignore create mode 100644 src/test/resources/testPrograms/array/ArrayOutOfBounds2.error create mode 100644 src/test/resources/testPrograms/array/ArrayOutOfBounds2.monty.ignore create mode 100644 src/test/resources/testPrograms/array/ArrayOutOfBounds3.error create mode 100644 src/test/resources/testPrograms/array/ArrayOutOfBounds3.monty.ignore create mode 100644 src/test/resources/testPrograms/array/ArrayOutOfBounds4.error create mode 100644 src/test/resources/testPrograms/array/ArrayOutOfBounds4.monty.ignore create mode 100644 src/test/resources/testPrograms/array/ArrayTwo.monty.ignore create mode 100644 src/test/resources/testPrograms/array/ArrayTwo.output create mode 100644 src/test/resources/testPrograms/callable/Function.monty create mode 100644 src/test/resources/testPrograms/callable/Function.output create mode 100644 src/test/resources/testPrograms/callable/Function1.monty create mode 100644 src/test/resources/testPrograms/callable/Function1.output create mode 100644 src/test/resources/testPrograms/callable/Function2.monty create mode 100644 src/test/resources/testPrograms/callable/Function2.output create mode 100644 src/test/resources/testPrograms/callable/Function3.monty create mode 100644 src/test/resources/testPrograms/callable/Function3.output create mode 100644 src/test/resources/testPrograms/callable/Function4.monty create mode 100644 src/test/resources/testPrograms/callable/Function4.output create mode 100644 src/test/resources/testPrograms/callable/FunctionGlobalLocalBoolean.monty create mode 100644 src/test/resources/testPrograms/callable/FunctionGlobalLocalBoolean.output create mode 100644 src/test/resources/testPrograms/callable/FunctionGlobalLocalFloat.monty create mode 100644 src/test/resources/testPrograms/callable/FunctionGlobalLocalFloat.output create mode 100644 src/test/resources/testPrograms/callable/FunctionGlobalLocalInt.monty create mode 100644 src/test/resources/testPrograms/callable/FunctionGlobalLocalInt.output create mode 100644 src/test/resources/testPrograms/callable/FunctionGlobalLocalString.monty create mode 100644 src/test/resources/testPrograms/callable/FunctionGlobalLocalString.output create mode 100644 src/test/resources/testPrograms/callable/Procedure.monty create mode 100644 src/test/resources/testPrograms/callable/Procedure.output create mode 100644 src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction1.monty create mode 100644 src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction1.output create mode 100644 src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction2.monty create mode 100644 src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction2.output create mode 100644 src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction3.monty create mode 100644 src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction3.output create mode 100644 src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction4.monty create mode 100644 src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction4.output create mode 100644 src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction5.monty create mode 100644 src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction5.output create mode 100644 src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction6.monty create mode 100644 src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction6.output create mode 100644 src/test/resources/testPrograms/classes/ClassMemberBool1.monty create mode 100644 src/test/resources/testPrograms/classes/ClassMemberBool1.output create mode 100644 src/test/resources/testPrograms/classes/ClassMemberBool2.monty create mode 100644 src/test/resources/testPrograms/classes/ClassMemberBool2.output create mode 100644 src/test/resources/testPrograms/classes/ClassMemberBool3.monty create mode 100644 src/test/resources/testPrograms/classes/ClassMemberBool3.output create mode 100644 src/test/resources/testPrograms/classes/ClassMemberBool4.monty create mode 100644 src/test/resources/testPrograms/classes/ClassMemberBool4.output create mode 100644 src/test/resources/testPrograms/classes/ClassMemberChar1.monty create mode 100644 src/test/resources/testPrograms/classes/ClassMemberChar1.output create mode 100644 src/test/resources/testPrograms/classes/ClassMemberChar2.monty create mode 100644 src/test/resources/testPrograms/classes/ClassMemberChar2.output create mode 100644 src/test/resources/testPrograms/classes/ClassMemberChar3.monty create mode 100644 src/test/resources/testPrograms/classes/ClassMemberChar3.output create mode 100644 src/test/resources/testPrograms/classes/ClassMemberChar4.monty create mode 100644 src/test/resources/testPrograms/classes/ClassMemberChar4.output create mode 100644 src/test/resources/testPrograms/classes/ClassMemberComplex1.monty create mode 100644 src/test/resources/testPrograms/classes/ClassMemberComplex1.output create mode 100644 src/test/resources/testPrograms/classes/ClassMemberComplex2.monty create mode 100644 src/test/resources/testPrograms/classes/ClassMemberComplex2.output create mode 100644 src/test/resources/testPrograms/classes/ClassMemberComplex3.monty create mode 100644 src/test/resources/testPrograms/classes/ClassMemberComplex3.output create mode 100644 src/test/resources/testPrograms/classes/ClassMemberFloat1.monty create mode 100644 src/test/resources/testPrograms/classes/ClassMemberFloat1.output create mode 100644 src/test/resources/testPrograms/classes/ClassMemberFloat2.monty create mode 100644 src/test/resources/testPrograms/classes/ClassMemberFloat2.output create mode 100644 src/test/resources/testPrograms/classes/ClassMemberFloat3.monty create mode 100644 src/test/resources/testPrograms/classes/ClassMemberFloat3.output create mode 100644 src/test/resources/testPrograms/classes/ClassMemberFloat4.monty create mode 100644 src/test/resources/testPrograms/classes/ClassMemberFloat4.output create mode 100644 src/test/resources/testPrograms/classes/ClassMemberInt1.monty create mode 100644 src/test/resources/testPrograms/classes/ClassMemberInt1.output create mode 100644 src/test/resources/testPrograms/classes/ClassMemberInt2.monty create mode 100644 src/test/resources/testPrograms/classes/ClassMemberInt2.output create mode 100644 src/test/resources/testPrograms/classes/ClassMemberInt3.monty create mode 100644 src/test/resources/testPrograms/classes/ClassMemberInt3.output create mode 100644 src/test/resources/testPrograms/classes/ClassMemberInt4.monty create mode 100644 src/test/resources/testPrograms/classes/ClassMemberInt4.output create mode 100644 src/test/resources/testPrograms/classes/ClassMemberString1.monty create mode 100644 src/test/resources/testPrograms/classes/ClassMemberString1.output create mode 100644 src/test/resources/testPrograms/classes/ClassMemberString2.monty create mode 100644 src/test/resources/testPrograms/classes/ClassMemberString2.output create mode 100644 src/test/resources/testPrograms/classes/ClassMemberString3.monty create mode 100644 src/test/resources/testPrograms/classes/ClassMemberString3.output create mode 100644 src/test/resources/testPrograms/classes/ClassMemberString4.monty create mode 100644 src/test/resources/testPrograms/classes/ClassMemberString4.output create mode 100644 src/test/resources/testPrograms/classes/ClassPointer1.monty create mode 100644 src/test/resources/testPrograms/classes/ClassPointer1.output create mode 100644 src/test/resources/testPrograms/classes/ClassPointer2.monty create mode 100644 src/test/resources/testPrograms/classes/ClassPointer2.output create mode 100644 src/test/resources/testPrograms/classes/constructor/Constructor1.monty create mode 100644 src/test/resources/testPrograms/classes/constructor/Constructor1.output create mode 100644 src/test/resources/testPrograms/classes/constructor/Constructor2.monty create mode 100644 src/test/resources/testPrograms/classes/constructor/Constructor2.output create mode 100644 src/test/resources/testPrograms/classes/constructor/Constructor3.monty create mode 100644 src/test/resources/testPrograms/classes/constructor/Constructor3.output create mode 100644 src/test/resources/testPrograms/classes/constructor/Constructor4.monty create mode 100644 src/test/resources/testPrograms/classes/constructor/Constructor4.output create mode 100644 src/test/resources/testPrograms/classes/constructor/Constructor5.monty create mode 100644 src/test/resources/testPrograms/classes/constructor/Constructor5.output create mode 100644 src/test/resources/testPrograms/classes/constructor/Constructor6.monty create mode 100644 src/test/resources/testPrograms/classes/constructor/Constructor6.output create mode 100644 src/test/resources/testPrograms/classes/constructor/Constructor7.monty create mode 100644 src/test/resources/testPrograms/classes/constructor/Constructor7.output create mode 100644 src/test/resources/testPrograms/classes/methods/Methods1.monty create mode 100644 src/test/resources/testPrograms/classes/methods/Methods1.output create mode 100644 src/test/resources/testPrograms/classes/methods/Methods2.monty create mode 100644 src/test/resources/testPrograms/classes/methods/Methods2.output create mode 100644 src/test/resources/testPrograms/classes/methods/Methods3.monty create mode 100644 src/test/resources/testPrograms/classes/methods/Methods3.output create mode 100644 src/test/resources/testPrograms/classes/methods/Methods4.monty create mode 100644 src/test/resources/testPrograms/classes/methods/Methods4.output create mode 100644 src/test/resources/testPrograms/classes/methods/Methods5.monty create mode 100644 src/test/resources/testPrograms/classes/methods/Methods5.output create mode 100644 src/test/resources/testPrograms/compoundAssignments/Div.monty create mode 100644 src/test/resources/testPrograms/compoundAssignments/Div.output create mode 100644 src/test/resources/testPrograms/compoundAssignments/Div1.monty create mode 100644 src/test/resources/testPrograms/compoundAssignments/Div1.output create mode 100644 src/test/resources/testPrograms/compoundAssignments/Minus.monty create mode 100644 src/test/resources/testPrograms/compoundAssignments/Minus.output create mode 100644 src/test/resources/testPrograms/compoundAssignments/Minus1.monty create mode 100644 src/test/resources/testPrograms/compoundAssignments/Minus1.output create mode 100644 src/test/resources/testPrograms/compoundAssignments/Mod.monty create mode 100644 src/test/resources/testPrograms/compoundAssignments/Mod.output create mode 100644 src/test/resources/testPrograms/compoundAssignments/Mod1.monty create mode 100644 src/test/resources/testPrograms/compoundAssignments/Mod1.output create mode 100644 src/test/resources/testPrograms/compoundAssignments/Mult.monty create mode 100644 src/test/resources/testPrograms/compoundAssignments/Mult.output create mode 100644 src/test/resources/testPrograms/compoundAssignments/Mult1.monty create mode 100644 src/test/resources/testPrograms/compoundAssignments/Mult1.output create mode 100644 src/test/resources/testPrograms/compoundAssignments/Plus.monty create mode 100644 src/test/resources/testPrograms/compoundAssignments/Plus.output create mode 100644 src/test/resources/testPrograms/compoundAssignments/Plus1.monty create mode 100644 src/test/resources/testPrograms/compoundAssignments/Plus1.output create mode 100644 src/test/resources/testPrograms/compoundAssignments/Power.monty.ignore create mode 100644 src/test/resources/testPrograms/compoundAssignments/Power.output create mode 100644 src/test/resources/testPrograms/compoundAssignments/Power1.monty.ignore create mode 100644 src/test/resources/testPrograms/compoundAssignments/Power1.output create mode 100644 src/test/resources/testPrograms/controlflow/ConditionalStatementComplex.monty create mode 100644 src/test/resources/testPrograms/controlflow/ConditionalStatementComplex.output create mode 100644 src/test/resources/testPrograms/controlflow/ConditionalStatementFalse.monty create mode 100644 src/test/resources/testPrograms/controlflow/ConditionalStatementFalse.output create mode 100644 src/test/resources/testPrograms/controlflow/ConditionalStatementTrue.monty create mode 100644 src/test/resources/testPrograms/controlflow/ConditionalStatementTrue.output create mode 100644 src/test/resources/testPrograms/controlflow/Ifelse1.monty create mode 100644 src/test/resources/testPrograms/controlflow/Ifelse1.output create mode 100644 src/test/resources/testPrograms/controlflow/Ifelse2.monty create mode 100644 src/test/resources/testPrograms/controlflow/Ifelse2.output create mode 100644 src/test/resources/testPrograms/controlflow/WhileLoopBreak1.monty create mode 100644 src/test/resources/testPrograms/controlflow/WhileLoopBreak1.output create mode 100644 src/test/resources/testPrograms/controlflow/WhileLoopFalse.monty create mode 100644 src/test/resources/testPrograms/controlflow/WhileLoopFalse.output create mode 100644 src/test/resources/testPrograms/controlflow/WhileLoopSimple.monty create mode 100644 src/test/resources/testPrograms/controlflow/WhileLoopSimple.output create mode 100644 src/test/resources/testPrograms/controlflow/WhileLoopSkip1.monty create mode 100644 src/test/resources/testPrograms/controlflow/WhileLoopSkip1.output create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorAdd1.monty create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorAdd1.output create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorAdd2.monty create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorAdd2.output create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorAnd1.monty create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorAnd1.output create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorDiv1.monty create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorDiv1.output create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorDiv2.monty create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorDiv2.output create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorEquals1.monty create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorEquals1.output create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorEquals2.monty create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorEquals2.output create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorEquals3.monty create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorEquals3.output create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorEqualsNot1.monty create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorEqualsNot1.output create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorEqualsNot2.monty create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorEqualsNot2.output create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorEqualsNot3.monty create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorEqualsNot3.output create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorGreater1.monty create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorGreater1.output create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorGreater2.monty create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorGreater2.output create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorGreaterEqual1.monty create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorGreaterEqual1.output create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorGreaterEqual2.monty create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorGreaterEqual2.output create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorLess1.monty create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorLess1.output create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorLess2.monty create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorLess2.output create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorLessEqual1.monty create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorLessEqual1.output create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorLessEqual2.monty create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorLessEqual2.output create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorModulo1.monty create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorModulo1.output create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorMul1.monty create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorMul1.output create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorMul2.monty create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorMul2.output create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorOr1.monty create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorOr1.output create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorSub1.monty create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorSub1.output create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorSub2.monty create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorSub2.output create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorXor1.monty create mode 100644 src/test/resources/testPrograms/expressions/BinaryOperatorXor1.output create mode 100644 src/test/resources/testPrograms/expressions/ConditionalExpressionComplex.monty create mode 100644 src/test/resources/testPrograms/expressions/ConditionalExpressionComplex.output create mode 100644 src/test/resources/testPrograms/expressions/ConditionalExpressionFalse1.monty create mode 100644 src/test/resources/testPrograms/expressions/ConditionalExpressionFalse1.output create mode 100644 src/test/resources/testPrograms/expressions/ConditionalExpressionFalse2.monty create mode 100644 src/test/resources/testPrograms/expressions/ConditionalExpressionFalse2.output create mode 100644 src/test/resources/testPrograms/expressions/ConditionalExpressionFalse3.monty create mode 100644 src/test/resources/testPrograms/expressions/ConditionalExpressionFalse3.output create mode 100644 src/test/resources/testPrograms/expressions/ConditionalExpressionTrue1.monty create mode 100644 src/test/resources/testPrograms/expressions/ConditionalExpressionTrue1.output create mode 100644 src/test/resources/testPrograms/expressions/ConditionalExpressionTrue2.monty create mode 100644 src/test/resources/testPrograms/expressions/ConditionalExpressionTrue2.output create mode 100644 src/test/resources/testPrograms/expressions/ConditionalExpressionTrue3.monty create mode 100644 src/test/resources/testPrograms/expressions/ConditionalExpressionTrue3.output create mode 100644 src/test/resources/testPrograms/expressions/SelfDefinedOperators.monty create mode 100644 src/test/resources/testPrograms/expressions/SelfDefinedOperators.output create mode 100644 src/test/resources/testPrograms/expressions/UnaryOperatorMinus1.monty create mode 100644 src/test/resources/testPrograms/expressions/UnaryOperatorMinus1.output create mode 100644 src/test/resources/testPrograms/expressions/UnaryOperatorMinus2.monty create mode 100644 src/test/resources/testPrograms/expressions/UnaryOperatorMinus2.output create mode 100644 src/test/resources/testPrograms/expressions/UnaryOperatorNot1.monty create mode 100644 src/test/resources/testPrograms/expressions/UnaryOperatorNot1.output create mode 100644 src/test/resources/testPrograms/inheritance/casting/ClassInheritedCast1.monty create mode 100644 src/test/resources/testPrograms/inheritance/casting/ClassInheritedCast1.output create mode 100644 src/test/resources/testPrograms/inheritance/casting/ClassInheritedCast2.error create mode 100644 src/test/resources/testPrograms/inheritance/casting/ClassInheritedCast2.monty create mode 100644 src/test/resources/testPrograms/inheritance/casting/ClassInheritedUpcast1.monty create mode 100644 src/test/resources/testPrograms/inheritance/casting/ClassInheritedUpcast1.output create mode 100644 src/test/resources/testPrograms/inheritance/casting/ClassInheritedUpcast2.monty create mode 100644 src/test/resources/testPrograms/inheritance/casting/ClassInheritedUpcast2.output create mode 100644 src/test/resources/testPrograms/inheritance/casting/ClassInheritedUpcast3.monty create mode 100644 src/test/resources/testPrograms/inheritance/casting/ClassInheritedUpcast3.output create mode 100644 src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance1.monty create mode 100644 src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance1.output create mode 100644 src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance2.monty create mode 100644 src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance2.output create mode 100644 src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance3.monty create mode 100644 src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance3.output create mode 100644 src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance4.monty create mode 100644 src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance4.output create mode 100644 src/test/resources/testPrograms/inheritance/is/ClassInheritedIs1.monty create mode 100644 src/test/resources/testPrograms/inheritance/is/ClassInheritedIs1.output create mode 100644 src/test/resources/testPrograms/inheritance/is/ClassInheritedIs2.monty create mode 100644 src/test/resources/testPrograms/inheritance/is/ClassInheritedIs2.output create mode 100644 src/test/resources/testPrograms/inheritance/is/ClassInheritedIs3.monty create mode 100644 src/test/resources/testPrograms/inheritance/is/ClassInheritedIs3.output create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool1.monty create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool1.output create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool2.monty create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool2.output create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool3.monty create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool3.output create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool4.monty create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool4.output create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar1.monty create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar1.output create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar2.monty create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar2.output create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar3.monty create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar3.output create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar4.monty create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar4.output create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberComplex1.monty create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberComplex1.output create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberComplex2.monty create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberComplex2.output create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat1.monty create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat1.output create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat2.monty create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat2.output create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat3.monty create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat3.output create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat4.monty create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat4.output create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt1.monty create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt1.output create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt2.monty create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt2.output create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt3.monty create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt3.output create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt4.monty create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt4.output create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString1.monty create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString1.output create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString2.monty create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString2.output create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString3.monty create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString3.output create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString4.monty create mode 100644 src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString4.output create mode 100644 src/test/resources/testPrograms/inheritance/methods/InheritanceMethods1.monty create mode 100644 src/test/resources/testPrograms/inheritance/methods/InheritanceMethods1.output create mode 100644 src/test/resources/testPrograms/inheritance/methods/InheritanceMethods2.monty create mode 100644 src/test/resources/testPrograms/inheritance/methods/InheritanceMethods2.output create mode 100644 src/test/resources/testPrograms/literals/BoolAsObject.monty create mode 100644 src/test/resources/testPrograms/literals/BoolAsObject.output create mode 100644 src/test/resources/testPrograms/literals/BoolConstructor.monty create mode 100644 src/test/resources/testPrograms/literals/BoolConstructor.output create mode 100644 src/test/resources/testPrograms/literals/BoolIsObject.monty create mode 100644 src/test/resources/testPrograms/literals/BoolIsObject.output create mode 100644 src/test/resources/testPrograms/literals/CharAsObject.monty create mode 100644 src/test/resources/testPrograms/literals/CharAsObject.output create mode 100644 src/test/resources/testPrograms/literals/CharConstructor.monty create mode 100644 src/test/resources/testPrograms/literals/CharConstructor.output create mode 100644 src/test/resources/testPrograms/literals/CharIsObject.monty create mode 100644 src/test/resources/testPrograms/literals/CharIsObject.output create mode 100644 src/test/resources/testPrograms/literals/FloatAsObject.monty create mode 100644 src/test/resources/testPrograms/literals/FloatAsObject.output create mode 100644 src/test/resources/testPrograms/literals/FloatConstructor.monty create mode 100644 src/test/resources/testPrograms/literals/FloatConstructor.output create mode 100644 src/test/resources/testPrograms/literals/FloatIsObject.monty create mode 100644 src/test/resources/testPrograms/literals/FloatIsObject.output create mode 100644 src/test/resources/testPrograms/literals/IntAsObject.monty create mode 100644 src/test/resources/testPrograms/literals/IntAsObject.output create mode 100644 src/test/resources/testPrograms/literals/IntConstructor.monty create mode 100644 src/test/resources/testPrograms/literals/IntConstructor.output create mode 100644 src/test/resources/testPrograms/literals/IntIsObject.monty create mode 100644 src/test/resources/testPrograms/literals/IntIsObject.output create mode 100644 src/test/resources/testPrograms/negativ/IdentifierNotDefined.error create mode 100644 src/test/resources/testPrograms/negativ/IdentifierNotDefined.monty create mode 100644 src/test/resources/testPrograms/negativ/callable/neg_Function1.error create mode 100644 src/test/resources/testPrograms/negativ/callable/neg_Function1.monty create mode 100644 src/test/resources/testPrograms/negativ/callable/neg_Function2.error create mode 100644 src/test/resources/testPrograms/negativ/callable/neg_Function2.monty create mode 100644 src/test/resources/testPrograms/negativ/callable/neg_Function3.error create mode 100644 src/test/resources/testPrograms/negativ/callable/neg_Function3.monty create mode 100644 src/test/resources/testPrograms/negativ/callable/neg_Function4.error create mode 100644 src/test/resources/testPrograms/negativ/callable/neg_Function4.monty.ignore create mode 100644 src/test/resources/testPrograms/negativ/callable/neg_Procedure1.error create mode 100644 src/test/resources/testPrograms/negativ/callable/neg_Procedure1.monty create mode 100644 src/test/resources/testPrograms/negativ/callable/neg_Procedure2.error create mode 100644 src/test/resources/testPrograms/negativ/callable/neg_Procedure2.monty create mode 100644 src/test/resources/testPrograms/negativ/scoping/RedeclarationOtherType.error create mode 100644 src/test/resources/testPrograms/negativ/scoping/RedeclarationOtherType.monty create mode 100644 src/test/resources/testPrograms/negativ/scoping/RedeclarationSameType.error create mode 100644 src/test/resources/testPrograms/negativ/scoping/RedeclarationSameType.monty create mode 100644 src/test/resources/testPrograms/negativ/scoping/VariableAccess.error create mode 100644 src/test/resources/testPrograms/negativ/scoping/VariableAccess.monty create mode 100644 src/test/resources/testPrograms/negativ/scoping/VariableAccess2.error create mode 100644 src/test/resources/testPrograms/negativ/scoping/VariableAccess2.monty create mode 100644 src/test/resources/testPrograms/negativ/scoping/VariableAccess3.error create mode 100644 src/test/resources/testPrograms/negativ/scoping/VariableAccess3.monty create mode 100644 src/test/resources/testPrograms/negativ/scoping/VariableAccess4.error create mode 100644 src/test/resources/testPrograms/negativ/scoping/VariableAccess4.monty create mode 100644 src/test/resources/testPrograms/negativ/scoping/VariableAccess5.error create mode 100644 src/test/resources/testPrograms/negativ/scoping/VariableAccess5.monty.ignore create mode 100644 src/test/resources/testPrograms/negativ/scoping/VariableAccess6.error create mode 100644 src/test/resources/testPrograms/negativ/scoping/VariableAccess6.monty create mode 100644 src/test/resources/testPrograms/object/Object1.monty create mode 100644 src/test/resources/testPrograms/object/Object1.output create mode 100644 src/test/resources/testPrograms/object/Object2.monty create mode 100644 src/test/resources/testPrograms/object/Object2.output create mode 100644 src/test/resources/testPrograms/object/Object3.monty create mode 100644 src/test/resources/testPrograms/object/Object3.output create mode 100644 src/test/resources/testPrograms/object/Object4.monty create mode 100644 src/test/resources/testPrograms/object/Object4.output create mode 100644 src/test/resources/testPrograms/overloading/OverloadingConstructor1.monty create mode 100644 src/test/resources/testPrograms/overloading/OverloadingConstructor1.output create mode 100644 src/test/resources/testPrograms/overloading/OverloadingFunction1.monty create mode 100644 src/test/resources/testPrograms/overloading/OverloadingFunction1.output create mode 100644 src/test/resources/testPrograms/overloading/OverloadingFunction2.monty create mode 100644 src/test/resources/testPrograms/overloading/OverloadingFunction2.output create mode 100644 src/test/resources/testPrograms/overloading/OverloadingFunction3.monty create mode 100644 src/test/resources/testPrograms/overloading/OverloadingFunction3.output create mode 100644 src/test/resources/testPrograms/overloading/OverloadingProcedure1.monty create mode 100644 src/test/resources/testPrograms/overloading/OverloadingProcedure1.output create mode 100644 src/test/resources/testPrograms/overloading/OverloadingProcedure2.monty create mode 100644 src/test/resources/testPrograms/overloading/OverloadingProcedure2.output create mode 100644 src/test/resources/testPrograms/overloading/OverloadingProcedure3.monty create mode 100644 src/test/resources/testPrograms/overloading/OverloadingProcedure3.output create mode 100644 src/test/resources/testPrograms/print/PrintBoolean.monty create mode 100644 src/test/resources/testPrograms/print/PrintBoolean.output create mode 100644 src/test/resources/testPrograms/print/PrintChar.monty create mode 100644 src/test/resources/testPrograms/print/PrintChar.output create mode 100644 src/test/resources/testPrograms/print/PrintFloat.monty create mode 100644 src/test/resources/testPrograms/print/PrintFloat.output create mode 100644 src/test/resources/testPrograms/print/PrintInt.monty create mode 100644 src/test/resources/testPrograms/print/PrintInt.output create mode 100644 src/test/resources/testPrograms/print/PrintString.monty create mode 100644 src/test/resources/testPrograms/print/PrintString.output create mode 100644 src/test/resources/testPrograms/print/PrintVariableBoolean.monty create mode 100644 src/test/resources/testPrograms/print/PrintVariableBoolean.output create mode 100644 src/test/resources/testPrograms/print/PrintVariableChar.monty create mode 100644 src/test/resources/testPrograms/print/PrintVariableChar.output create mode 100644 src/test/resources/testPrograms/print/PrintVariableFloat.monty create mode 100644 src/test/resources/testPrograms/print/PrintVariableFloat.output create mode 100644 src/test/resources/testPrograms/print/PrintVariableInt.monty create mode 100644 src/test/resources/testPrograms/print/PrintVariableInt.output create mode 100644 src/test/resources/testPrograms/print/PrintVariableString.monty create mode 100644 src/test/resources/testPrograms/print/PrintVariableString.output create mode 100644 src/test/resources/testPrograms/print/PrintWhitespaces.monty create mode 100644 src/test/resources/testPrograms/print/PrintWhitespaces.output create mode 100644 src/test/resources/testPrograms/print/PrintWhitespaces2.monty.ignore create mode 100644 src/test/resources/testPrograms/print/PrintWhitespaces2.output create mode 100644 src/test/resources/testPrograms/scoping/Redeclaration.monty create mode 100644 src/test/resources/testPrograms/scoping/Redeclaration.output create mode 100644 src/test/resources/testPrograms/scoping/SimultaneouslyVisibleFunctions.monty create mode 100644 src/test/resources/testPrograms/scoping/SimultaneouslyVisibleFunctions.output create mode 100644 src/test/resources/testPrograms/scoping/SimultaneouslyVisibleObjects.monty create mode 100644 src/test/resources/testPrograms/scoping/SimultaneouslyVisibleObjects.output create mode 100644 src/test/resources/testPrograms/scoping/VariableAccess.monty create mode 100644 src/test/resources/testPrograms/scoping/VariableAccess.output create mode 100644 src/test/resources/testPrograms/variables/GlobalVariableBoolean1.monty create mode 100644 src/test/resources/testPrograms/variables/GlobalVariableBoolean1.output create mode 100644 src/test/resources/testPrograms/variables/GlobalVariableBoolean2.monty create mode 100644 src/test/resources/testPrograms/variables/GlobalVariableBoolean2.output create mode 100644 src/test/resources/testPrograms/variables/GlobalVariableChar1.monty create mode 100644 src/test/resources/testPrograms/variables/GlobalVariableChar1.output create mode 100644 src/test/resources/testPrograms/variables/GlobalVariableChar2.monty create mode 100644 src/test/resources/testPrograms/variables/GlobalVariableChar2.output create mode 100644 src/test/resources/testPrograms/variables/GlobalVariableFloat1.monty create mode 100644 src/test/resources/testPrograms/variables/GlobalVariableFloat1.output create mode 100644 src/test/resources/testPrograms/variables/GlobalVariableFloat2.monty create mode 100644 src/test/resources/testPrograms/variables/GlobalVariableFloat2.output create mode 100644 src/test/resources/testPrograms/variables/GlobalVariableInt1.monty create mode 100644 src/test/resources/testPrograms/variables/GlobalVariableInt1.output create mode 100644 src/test/resources/testPrograms/variables/GlobalVariableInt2.monty create mode 100644 src/test/resources/testPrograms/variables/GlobalVariableInt2.output create mode 100644 src/test/resources/testPrograms/variables/GlobalVariableString1.monty create mode 100644 src/test/resources/testPrograms/variables/GlobalVariableString1.output create mode 100644 src/test/resources/testPrograms/variables/GlobalVariableString2.monty create mode 100644 src/test/resources/testPrograms/variables/GlobalVariableString2.output diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7316f21 --- /dev/null +++ b/.gitignore @@ -0,0 +1,48 @@ +################### +# LATEX +################### +*.aux +*.glo +*.idx +*.log +*.toc +*.ist +*.acn +*.acr +*.alg +*.bbl +*.blg +*.dvi +*.glg +*.gls +*.ilg +*.ind +*.lof +*.lot +*.maf +*.mtc +*.mtc1 +*.out +*.synctex.gz +*.brf +*.nav +*.snm +*.vrb + +################### +# Java +################### +src/site/markdown/index.md +target/* +.classpath +.project +.settings/ +moco.iml +.idea/* + +################### +# Editor +################### +*.swp + +dependency-reduced-pom.xml diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/COPYING_EXCEPTION b/COPYING_EXCEPTION new file mode 100644 index 0000000..40424cf --- /dev/null +++ b/COPYING_EXCEPTION @@ -0,0 +1,18 @@ +Linking this program and/or its accompanying libraries statically or +dynamically with other modules is making a combined work based on this +program. Thus, the terms and conditions of the GNU General Public License +cover the whole combination. + +As a special exception, the copyright holders of moco give +you permission to link this programm and/or its accompanying libraries +with independent modules to produce an executable, regardless of the +license terms of these independent modules, and to copy and distribute the +resulting executable under terms of your choice, provided that you also meet, +for each linked independent module, the terms and conditions of the +license of that module. + +An independent module is a module which is not +derived from or based on this program and/or its accompanying libraries. +If you modify this library, you may extend this exception to your version of +the program or library, but you are not obliged to do so. If you do not wish +to do so, delete this exception statement from your version. \ No newline at end of file diff --git a/COPYING_HEADER b/COPYING_HEADER new file mode 100644 index 0000000..27cf923 --- /dev/null +++ b/COPYING_HEADER @@ -0,0 +1,38 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..ddb07c5 --- /dev/null +++ b/README.md @@ -0,0 +1,70 @@ +Allgemeines +----------- + +Dieses Projekt setzt Java in der Version 7 ein. Stellt sicher, dass ihr keine +Features von Java 8 verwendet. Die Referenz ob das Projekt baut und die Tests +laufen sind die Maven-Runs. + +Es wird durch Maven automatisch ein Code-Formatter ausgeführt. Bitte +kompiliert also vor dem commiten einmal mit Maven oder konfiguriert eure IDE, +sodass diese den Code entsprechend formatiert. + +Zu installierende Software: + +- Java 7 +- Maven 3 http://maven.apache.org/ +- LLVM 3.4 http://llvm.org/ +- Graphviz http://www.graphviz.org/ + +Bei Windows benötigt ihr extra noch: + +- ein 32bit JDK +- Visual C++ Redistributable Packages für Visual Studio 2013 + http://www.microsoft.com/de-de/download/details.aspx?id=40784 + +Kompilation und Ausführen +------------------------- + +- `mvn package` + Generiert die nötigen ANTLR4 Dateien, kompiliert alle wichtigen Dateien, + führt die Tests aus und baut ein ausführbares JAR + (`target/moco-0.6.jar`). +- `mvn package -Dmaven.test.skip=true` + Führt die Tests nicht aus. +Habt ihr das JAR erstellt, könnt ihr die Main Klasse mit `java -jar +target/moco-0.6.jar` starten. + +Maven Reporting +--------------- + +Maven wurde eingerichtet Reports zu generieren. + +`mvn site` erstellt die Dokumentation und generiert Reports unter +[target/site/](project-reports.html). Besonders interessant: + + - [JavaDoc](apidocs/index.html) + - [Code Coverage Analysis](cobertura/index.html) + +Außerdem gibt es Analysen auf dem Code. Bitte beachtet, dass euer Code nicht +zu viele Einträge in folgenden Reports erzeugt: + +- [Checkstyle](checkstyle.html) +- [Findbugs](findbugs.html) + +Entwicklungsumgebungen +---------------------- + +###Eclipse: + +- Maven kann mit `mvn eclipse:eclipse` Eclipse Konfiguration generieren. + Ist dies erledigt kann man das Projekt einfach als existierendes Projekt + importieren. +- Es wird ein Code Formatter verwendet. Unter + `src/main/resources/java-code-conv.xml` findet sich ein in Eclipse + importierbares Profil. +- Alternativ: + - m2e in Eclipse installieren: http://download.eclipse.org/technology/m2e/releases + - File -> Import -> Maven -> Existing Maven Projects -> Browse... -> Auf Projekt Zeigen -> Next -> Finish -> OK + - Rechtsklick auf Projekt moco -> Maven -> Update Project Config... + - Ordner "target" -> generated-sources -> Rechtsklick auf "antlr4" -> Build Path -> Use as source Folder + - Run diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..fa20d65 --- /dev/null +++ b/pom.xml @@ -0,0 +1,281 @@ + + + 4.0.0 + + moco + moco + 0.6 + + + UTF-8 + ${project.basedir}/src/main/resources/checkstyle.xml + + + + + unix + + + !windows + + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.3.2 + + + rm-trailing-ws + compile + + exec + + + ${basedir}/src/main/resources/rm_trailing_whitespace.sh + + ${basedir}/src + + + + + + + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.5 + + + + de.uni.bremen.monty.moco.Main + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 2.3 + + + package + + shade + + + + + + + com.googlecode.maven-java-formatter-plugin + maven-java-formatter-plugin + 0.4 + + ${project.basedir}/src/main/resources/moco-code-conv.xml + true + 1.7 + 1.7 + 1.7 + LF + UTF-8 + + + + + format + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 1.7 + 1.7 + + + + + org.antlr + antlr4-maven-plugin + 4.2.2 + + + + antlr4 + + + false + true + + + + + true + + + + + org.apache.maven.plugins + maven-antrun-plugin + 1.7 + + + pre-site + + run + + + + + + + + + + + + + org.apache.maven.plugins + maven-site-plugin + 3.3 + + + org.apache.maven.doxia + doxia-module-markdown + 1.3 + + + + + + + + + + + + org.apache.maven.plugins + maven-project-info-reports-plugin + 2.6 + + + + index + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + + + javadoc + + + + + org.umlgraph.doclet.UmlGraphDoc + + org.umlgraph + umlgraph + 5.6 + + -views -all -horizontal + true + *antlr4* + + + + + org.apache.maven.plugins + maven-jxr-plugin + 2.3 + + + + org.apache.maven.plugins + maven-surefire-report-plugin + 2.17 + + + + org.codehaus.mojo + cobertura-maven-plugin + 2.6 + + + html + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 2.12.1 + + + + + + + + org.antlr + antlr4-runtime + 4.2.2 + + + + junit + junit + 4.11 + test + + + + commons-io + commons-io + 2.4 + + + + org.apache.commons + commons-lang3 + 3.3.1 + + + + org.mockito + mockito-all + 1.9.5 + test + + + + org.hamcrest + hamcrest-all + 1.3 + test + + + diff --git a/src/main/antlr4/de/uni/bremen/monty/moco/antlr/Monty.g4 b/src/main/antlr4/de/uni/bremen/monty/moco/antlr/Monty.g4 new file mode 100644 index 0000000..39c6668 --- /dev/null +++ b/src/main/antlr4/de/uni/bremen/monty/moco/antlr/Monty.g4 @@ -0,0 +1,228 @@ +grammar Monty; + +import lex; + +compilationUnit + : EndOfLine* moduleDeclaration EOF + ; + +moduleDeclaration + : importLine* ((classDeclaration | statement) EndOfLine*)* + ; + +importLine + : 'import' Identifier EndOfLine+ + ; + +independentDeclaration + : variableDeclaration (':=' expression)? EndOfLine + | constantDeclaration (':=' expression)? EndOfLine + | functionDeclaration + | procedureDeclaration + ; + +classDeclaration + : 'abstract'? 'class' ClassIdentifier ('inherits' typeList)? + ':' EndOfLine + Indent + (memberDeclaration+ | 'pass' EndOfLine) + Dedent + ; + +memberDeclaration + : accessModifier independentDeclaration + ; + +accessModifier + : modifier='#' + | modifier='+' + | modifier='-' + | modifier='~' + ; + +variableDeclaration + : type Identifier + ; + +constantDeclaration + : type ConstantIdentifier + ; + +type + : ClassIdentifier ('<' typeList '>')? + ; + +typeList + : type (',' type)* + ; + +functionDeclaration + : type + (Identifier | 'operator' binaryOperation) + Lparenthesis parameterList? Rparenthesis ':' EndOfLine + statementBlock + ; + +procedureDeclaration + : Identifier Lparenthesis parameterList? Rparenthesis ':' EndOfLine + statementBlock + ; + +defaultParameter + : variableDeclaration ':=' expression + ; + +parameterList + : defaultParameter (',' defaultParameter)* + | variableDeclaration (',' variableDeclaration)* (',' defaultParameter)* + ; + +statementBlock + : Indent + (statement+ | 'pass' EndOfLine) + Dedent + ; + +statement + : whileStatement #whileStm + | ifStatement #ifStm + | tryStatement #tryStm + | assignment #assignStm + | compoundAssignment #compoundAssign + | independentDeclaration #independentDeclStm + | command='return' expression? EndOfLine #returnStm + | command='raise' expression? EndOfLine #raiseStm + | command='skip' EndOfLine #skipStm + | command='break' EndOfLine #breakStm + | functionCall EndOfLine #funcCallStm + | left=expression operator='.' right=functionCall EndOfLine #MemberAccessStmt + ; + +/* while loop: The expression must be a condition (i.e. Boolean expression). */ +whileStatement + : 'while' expression ':' EndOfLine statementBlock + ; + +ifStatement + : 'if' ifCondition=expression ':' EndOfLine thenBlock=statementBlock + elif* + ('else' ':' EndOfLine elseBlock=statementBlock)? + ; + +elif + : 'elif' elifCondition=expression ':' EndOfLine elifBlock=statementBlock + ; + +tryStatement + : 'try:' EndOfLine tryBlock=statementBlock + ('handle' variableDeclaration? ':' EndOfLine handleBlock=statementBlock)+ + ; + +assignment + : left=expression ':=' right=expression EndOfLine + ; + +compoundAssignment + : left=expression compoundSymbol right=expression EndOfLine + ; + +compoundSymbol + : operator=('+=' | '-=' | '*=' | '/=' | '%=' | '^=') + ; + +functionCall + : (ClassIdentifier | Identifier) '(' expressionList? ')' + ; + +expressionList + : expression (',' expression)* + ; + +expression + : primary + | ifExprThen=expression 'if' ifExpCondition=expression 'else' ifExprElse=expression + | functionCall + | array=expression Lbracket index=expression Rbracket + | left=expression accessOperator right=expression + | (plusMinusOperator | notOperator) singleExpression=expression + | left=expression powerOperator right=expression + | left=expression dotOperator right=expression + | left=expression plusMinusOperator right=expression + | left=expression compareOperator right=expression + | left=expression eqOperator right=expression + | left=expression inOperator right=expression + | left=expression andOperator right=expression + | left=expression orOperator right=expression + | expr=expression asOperator ClassIdentifier + | expr=expression isOperator ClassIdentifier + ; + +primary + : Lparenthesis singleExpression=expression Rparenthesis + | literal + | Identifier + | ConstantIdentifier + | 'self' + | 'parent(' parent=ClassIdentifier ')' + ; + +inOperator + : operator='in' + ; + +andOperator + : operator='and' + ; + +orOperator + : operator=('or' | 'xor') + ; + +asOperator + : operator='as' + ; + +isOperator + : operator='is' + ; + +eqOperator + : operator=('=' | '!=') + ; + +compareOperator + : operator=('<' | '>' | '>=' | '<=') + ; + +powerOperator + : operator='^' + ; + +plusMinusOperator + : operator=('+' | '-') + ; + +notOperator + : operator='not' + ; + +accessOperator + : operator=('.' | '->') + ; + +dotOperator + : operator=('*' | '/' | '%') + ; + +literal + : IntegerLiteral + | RealLiteral + | CharacterLiteral + | StringLiteral + | BooleanLiteral + | arrayLiteral + ; + +arrayLiteral + : Lbracket (expression (',' expression)*)? Rbracket + ; diff --git a/src/main/antlr4/imports/lex.g4 b/src/main/antlr4/imports/lex.g4 new file mode 100644 index 0000000..75de360 --- /dev/null +++ b/src/main/antlr4/imports/lex.g4 @@ -0,0 +1,247 @@ +lexer grammar lex; + +@lexer::header { + import java.util.Stack; + import java.util.LinkedList; + import java.util.Queue; +} + +@lexer::members { +// we need a stack to store the indentation levels +Stack indentationStack = new Stack(); +// the queue provides us the possibility to add more than one token per lexer rule +Queue tokenQueue = new LinkedList(); +// we have to count opening an closing brackets for implicit line skips +int nesting = 0; + +// we have to store the 'imaginary tokens' because they only appear in the parser class +public static final int Indent = MontyParser.Indent; +public static final int Dedent = MontyParser.Dedent; + +// initialize the indentation stack with level 0 indent +{ + indentationStack.push(0); +} + +// add every token to the queue +@Override +public void emit(Token token) { + _token = token; + tokenQueue.offer(token); +} + +// return tokens from the queue until it is empty, then return EOF +@Override +public Token nextToken() { + super.nextToken(); + if(tokenQueue.peek() == null) + return new CommonToken(Token.EOF); + return tokenQueue.poll(); +} +} + +// forward declarations of 'imaginary tokens' +tokens { Indent, Dedent } + +// line skip with \ +ExplicitLineSkip : '\\' ('\u000C')? '\r'? '\n' -> skip; +// line skip within brackets +// ImplicitLineSkip : ('\u000C')? '\r'? '\n' {nesting>0}? -> skip; + +// check indentation, treat multiple newlines as one +EndOfLine : + //_________line breaks____ _whitespaces__ __comments__ ___last line break______ ___indent__ + ((('\u000C')?('\r')? '\n' ) | '\t' | ' ' | ('//' (~'\n')*))* (('\u000C')?('\r')? '\n' ) (' ' | '\t' )* + + { + if(nesting>0) + { + skip(); + return; + } + + String tokenText = getText(); + int indentLength = tokenText.length()-(tokenText.lastIndexOf("\n")+1); + // generate a newline token + tokenQueue.offer(new CommonToken(EndOfLine, "\n")); + + // if the indentation is deeper than the last one, add an Indent token + if(indentLength > indentationStack.peek()) + { + indentationStack.push(indentLength); + tokenQueue.offer(new CommonToken(Indent, "Indent")); + } + // if the indentation is less deep than the last line, + // add as many Dedent tokens as required + else if(indentLength < indentationStack.peek()) + { + while(indentationStack.peek() > indentLength) + { + indentationStack.pop(); + tokenQueue.offer(new CommonToken(Dedent, "Dedent")); + } + // if the new indentation does not match any outer level, + // we have a problem: + if(indentationStack.peek() != indentLength) + { + throw new RuntimeException("Monty says: Your indentation sucks!"); + } + } + + skip(); // do not automatically emit an EndOfLine token, + // since we already did it manually to ensure + // that it appears before the Indent or Dedent tokens + }; + +Lparenthesis + : '(' {nesting++;} ; +Rparenthesis + : ')' {nesting--;} ; +Lbracket + : '[' {nesting++;} ; +Rbracket + : ']' {nesting--;} ; +Lcurly + : '{' {nesting++;} ; +Rcurly + : '}' {nesting--;} ; + + +/* See http://www.antlr.org/wiki/display/ANTLR4/Grammar+Lexicon */ +fragment IdentifierStart + : Letter + | '\u00C0' .. '\u00D6' + | '\u00D8' .. '\u00F6' + | '\u00F8' .. '\u02FF' + | '\u0370' .. '\u037D' + | '\u037F' .. '\u1FFF' + | '\u200C' .. '\u200D' + | '\u2070' .. '\u218F' + | '\u2C00' .. '\u2FEF' + | '\u3001' .. '\uD7FF' + | '\uF900' .. '\uFDCF' + | '\uFDF0' .. '\uFFFD' + ; + +fragment IdentifierCharacter + : IdentifierStart + | Digit + | '_' + | '\u00B7' + | '\u0300' .. '\u036F' + | '\u203F' .. '\u2040' + ; + +BooleanLiteral + : ('true' | 'false') + ; + +/* Unicode identifiers. */ +Identifier + : '_'* LowercaseLetter (LowercaseLetter | UppercaseLetter | Digit | '_')* + ; + +ClassIdentifier + : UppercaseLetter (LowercaseLetter | UppercaseLetter | Digit)* LowercaseLetter (LowercaseLetter | UppercaseLetter | Digit)* + ; + +ConstantIdentifier + : '_'* UppercaseLetter (UppercaseLetter | Digit | '_')* + ; + +UppercaseLetter + : [A-Z] + ; + +LowercaseLetter + : [a-z] + ; + +IntegerLiteral + : (Digit | Letter)+ Exponent? Base? + ; + +RealLiteral + : Digit+ '.' Digit+ Exponent? + ; + +Digit + : [0-9] + ; + +Letter + : [a-zA-Z] + ; + +operation + : unaryOperation + | binaryOperation + ; + +unaryOperation + : 'not' + | '-' + ; + +binaryOperation + : '+' + | '-' + | '*' + | '/' + | '%' + | '^' + + | '=' + | '!=' + | '<' + | '>' + | '<=' + | '>=' + + | 'and' + | 'or' + | 'xor' + + | Lbracket Rbracket + + | 'in' + ; + +fragment Base + : '_' Digit+ + ; + +fragment Exponent + : 'e' ('+' | '-')? Digit+ + ; + +CharacterLiteral + : '\'' (CharacterEscapeSequence | ~('\'' | '\\')) '\'' + ; + +StringLiteral + : 'raw'? '"' (StringEscapeSequence | ~('\\' | '"'))* '"' + ; + +fragment CharacterEscapeSequence + : '\\' ('b' | 't' | 'n' | 'f' | 'r' | '\'' | '\\') + ; + +// hier müsste man noch das \n aus dem String rauskriegen +fragment StringEscapeSequence + : '\\' ('b' | 't' | 'n' | 'f' | 'r' | '\"' | '\\' | '$' | (('\u000C')?('\r')? '\n' )) + ; + +/* Toss out whitespaces. */ +Whitespaces + : ' '+ -> skip + ; + +/* Treat one or more tabs as a token representing a sequence of indentation + * characters. + */ +SpaceChars + : '\t'+ -> skip + ; + +Semicolon : ';' ; diff --git a/src/main/java/de/uni/bremen/monty/moco/Main.java b/src/main/java/de/uni/bremen/monty/moco/Main.java new file mode 100644 index 0000000..ed44a80 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/Main.java @@ -0,0 +1,152 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco; + +import de.uni.bremen.monty.moco.antlr.MontyParser; +import de.uni.bremen.monty.moco.ast.AntlrAdapter; +import de.uni.bremen.monty.moco.ast.Package; +import de.uni.bremen.monty.moco.ast.PackageBuilder; +import de.uni.bremen.monty.moco.util.Params; +import de.uni.bremen.monty.moco.util.ParseTreePrinter; +import de.uni.bremen.monty.moco.visitor.*; +import org.antlr.v4.runtime.misc.TestRig; +import org.apache.commons.io.IOUtils; + +import java.io.*; + +public class Main { + + public static void main(String[] args) throws IOException { + Params params = new Params(args); + new Main().start(params); + } + + private void start(Params params) throws IOException { + + String inputFile = params.getInputFile(); + + if (params.isDebugParseTree()) { + debugParseTree(params, inputFile); + return; + } + + PackageBuilder packageBuilder = new PackageBuilder(params); + Package mainPackage = packageBuilder.buildPackage(); + + visitVisitors(params, mainPackage); + } + + private void visitVisitors(Params params, Package ast) throws IOException { + + BaseVisitor[] visitors = + new BaseVisitor[] { new SetParentVisitor(), new DeclarationVisitor(), new ResolveVisitor(), + new TypeCheckVisitor(), new ControlFlowVisitor(), new NameManglingVisitor() }; + + boolean everyThingIsAwesome = true; + + for (BaseVisitor visitor : visitors) { + visitor.setStopOnFirstError(params.isStopOnFirstError()); + visitor.setStopOnFirstError(params.isStopOnFirstError()); + + try { + visitor.visitDoubleDispatched(ast); + } catch (RuntimeException exception) { + visitor.logError(exception); + everyThingIsAwesome = false; + break; + } + + if (visitor.foundError()) { + everyThingIsAwesome = false; + break; + } + } + + if (params.usePrintVisitor()) { + (new PrintVisitor()).visitDoubleDispatched(ast); + } else if (everyThingIsAwesome) { + (new CodeGenerationVisitor(params)).visitDoubleDispatched(ast); + generateCode(params); + } + } + + private void debugParseTree(Params params, String inputFile) throws IOException { + AntlrAdapter antlrAdapter = new AntlrAdapter(); + + File file = new File(inputFile); + MontyParser parser = antlrAdapter.createParser(new FileInputStream(file)); + ParseTreePrinter parseTreePrinter = new ParseTreePrinter(parser); + parser.addParseListener(parseTreePrinter); + parser.compilationUnit(); + System.out.print(parseTreePrinter.toString()); + try { + new TestRig(new String[] { "de.uni.bremen.monty.moco.antlr.Monty", "compilationUnit", "-gui", + params.getInputFile() }).process(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void generateCode(Params params) throws IOException { + PrintStream resultStream; + if (params.getOutputFile() == null) { + resultStream = System.out; + } else { + resultStream = new PrintStream(new FileOutputStream(params.getOutputFile())); + } + + if (!params.isGenerateOnlyLLVM()) { + String llFile = params.getLlFile(); + ProcessBuilder processBuilder = new ProcessBuilder("lli", llFile); + Process start = processBuilder.start(); + + String in = IOUtils.toString(start.getInputStream()); + String err = IOUtils.toString(start.getErrorStream()); + + System.err.print(err); + resultStream.print(in); + + if (!params.isKeepLLVMCode()) { + if (!new File(llFile).delete()) { + System.err.println("Warning: failed to delete file " + llFile); + } + } + } + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/ASTBuilder.java b/src/main/java/de/uni/bremen/monty/moco/ast/ASTBuilder.java new file mode 100644 index 0000000..ff6a19e --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/ASTBuilder.java @@ -0,0 +1,644 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast; + +import de.uni.bremen.monty.moco.antlr.MontyBaseVisitor; +import de.uni.bremen.monty.moco.antlr.MontyParser; +import de.uni.bremen.monty.moco.antlr.MontyParser.DefaultParameterContext; +import de.uni.bremen.monty.moco.antlr.MontyParser.TypeContext; +import de.uni.bremen.monty.moco.antlr.MontyParser.*; +import de.uni.bremen.monty.moco.ast.declaration.*; +import de.uni.bremen.monty.moco.ast.declaration.ProcedureDeclaration.DeclarationType; +import de.uni.bremen.monty.moco.ast.expression.*; +import de.uni.bremen.monty.moco.ast.expression.literal.*; +import de.uni.bremen.monty.moco.ast.statement.*; + +import org.antlr.v4.runtime.Token; +import org.antlr.v4.runtime.misc.NotNull; +import org.antlr.v4.runtime.tree.TerminalNode; +import org.apache.commons.io.FilenameUtils; + +import java.util.*; + +public class ASTBuilder extends MontyBaseVisitor { + private final String fileName; + private Stack currentBlocks; + private VariableDeclaration.DeclarationType currentVariableContext; + private ProcedureDeclaration.DeclarationType currentProcedureContext; + + public ASTBuilder(String fileName) { + this.fileName = fileName; + currentBlocks = new Stack<>(); + } + + private Position position(Token idSymbol) { + return new Position(fileName, idSymbol.getLine(), idSymbol.getCharPositionInLine()); + } + + private String getText(TerminalNode identifier) { + return identifier.getSymbol().getText(); + } + + @Override + public ASTNode visitModuleDeclaration(@NotNull MontyParser.ModuleDeclarationContext ctx) { + Block block = new Block(position(ctx.getStart())); + ModuleDeclaration module = + new ModuleDeclaration(position(ctx.getStart()), new Identifier(FilenameUtils.getBaseName(fileName)), + block, new ArrayList()); + currentBlocks.push(block); + + for (MontyParser.ImportLineContext imp : ctx.importLine()) { + + module.getImports().add( + new Import(position(imp.getStart()), new ResolvableIdentifier(getText(imp.Identifier())))); + } + + for (ClassDeclarationContext classDeclarationContext : ctx.classDeclaration()) { + ClassDeclaration classDecl = (ClassDeclaration) visit(classDeclarationContext); + block.addDeclaration(classDecl); + } + addStatementsToBlock(block, ctx.statement()); + currentBlocks.pop(); + return module; + } + + @Override + public ASTNode visitAssignment(@NotNull AssignmentContext ctx) { + Assignment assignment = + new Assignment(position(ctx.getStart()), (Expression) visit(ctx.left), (Expression) visit(ctx.right)); + return assignment; + } + + @Override + public ASTNode visitCompoundAssignment(CompoundAssignmentContext ctx) { + Expression expr = + binaryExpression( + position(ctx.getStart()), + ctx.compoundSymbol().operator.getText().substring(0, 1), + ctx.left, + ctx.right); + + return new Assignment(position(ctx.getStart()), (Expression) visit(ctx.left), expr); + } + + @Override + public ASTNode visitVariableDeclaration(@NotNull VariableDeclarationContext ctx) { + String typeName = ctx.type().ClassIdentifier().toString(); + ResolvableIdentifier type = new ResolvableIdentifier(typeName); + return new VariableDeclaration(position(ctx.getStart()), new Identifier(getText(ctx.Identifier())), type, + currentVariableContext); + } + + @Override + public ASTNode visitFunctionCall(FunctionCallContext ctx) { + ArrayList arguments = new ArrayList<>(); + String identifier; + if (ctx.Identifier() == null) { + identifier = ctx.ClassIdentifier().getText(); + } else { + identifier = ctx.Identifier().getText(); + } + FunctionCall func = new FunctionCall(position(ctx.getStart()), new ResolvableIdentifier(identifier), arguments); + if (ctx.expressionList() != null) { + for (ExpressionContext exprC : ctx.expressionList().expression()) { + + ASTNode expr = visit(exprC); + if (expr instanceof Expression) { + + arguments.add((Expression) expr); + } + } + } + return func; + } + + private void buildDefaultProcedures(boolean functionDeclaration, List defaultParameter, + List allVariableDeclarations, List params, + List defaultExpression, List defaultVariableDeclaration, + Identifier identifier, Token token, TypeContext typeContext, DeclarationType declarationTypeCopy) { + + for (int defaultParameterIdx = 0; defaultParameterIdx < defaultParameter.size(); defaultParameterIdx++) { + Block block = new Block(position(token)); + List l = new ArrayList<>(); + for (int variableDeclarationIdy = 0; variableDeclarationIdy < allVariableDeclarations.size(); variableDeclarationIdy++) { + if (variableDeclarationIdy >= params.size() + defaultParameterIdx) { + l.add(defaultExpression.get(variableDeclarationIdy - params.size())); + } else if (variableDeclarationIdy < params.size()) { + l.add(new VariableAccess(position(token), new ResolvableIdentifier(params.get( + variableDeclarationIdy).getIdentifier().getSymbol()))); + } else { + VariableDeclaration variableDeclaration = + defaultVariableDeclaration.get(variableDeclarationIdy - params.size()); + l.add(new VariableAccess(position(token), new ResolvableIdentifier( + variableDeclaration.getIdentifier().getSymbol()))); + } + } + + List subParams = + allVariableDeclarations.subList(0, params.size() + defaultParameterIdx); + + Expression expression = + new FunctionCall(position(token), new ResolvableIdentifier(identifier.getSymbol()), l); + + if (declarationTypeCopy == ProcedureDeclaration.DeclarationType.METHOD) { + expression = new MemberAccess(position(token), new SelfExpression(position(token)), expression); + } + + ProcedureDeclaration procDecl1; + if (functionDeclaration) { + block.addStatement(new ReturnStatement(new Position(), expression)); + procDecl1 = + new FunctionDeclaration(position(token), identifier, block, subParams, declarationTypeCopy, + new ResolvableIdentifier(typeContext.ClassIdentifier().getText())); + } else { + block.addStatement((Statement) expression); + block.addStatement(new ReturnStatement(new Position(), null)); + procDecl1 = + new ProcedureDeclaration(position(token), identifier, block, subParams, declarationTypeCopy); + } + currentBlocks.peek().addDeclaration(procDecl1); + } + } + + private ProcedureDeclaration buildProcedures(boolean functionDeclaration, + ParameterListContext parameterListContext, Token token, TypeContext typeContext, + StatementBlockContext statementBlockContext, Identifier identifier) { + + ProcedureDeclaration.DeclarationType declarationTypeCopy = currentProcedureContext; + List params = parameterListToVarDeclList(parameterListContext); + List defaultParameter = defaultParameterListToVarDeclList(parameterListContext); + + List defaultVariableDeclaration = new ArrayList<>(); + List defaultExpression = new ArrayList<>(); + for (DefaultParameterContext context : defaultParameter) { + defaultVariableDeclaration.add((VariableDeclaration) visit(context.variableDeclaration())); + defaultExpression.add((Expression) visit(context.expression())); + } + + List allVariableDeclarations = new ArrayList<>(); + allVariableDeclarations.addAll(params); + allVariableDeclarations.addAll(defaultVariableDeclaration); + + buildDefaultProcedures( + functionDeclaration, + defaultParameter, + allVariableDeclarations, + params, + defaultExpression, + defaultVariableDeclaration, + identifier, + token, + typeContext, + declarationTypeCopy); + + ProcedureDeclaration procDecl2; + + if (functionDeclaration) { + procDecl2 = + new FunctionDeclaration(position(token), identifier, (Block) visit(statementBlockContext), + allVariableDeclarations, declarationTypeCopy, new ResolvableIdentifier( + typeContext.ClassIdentifier().getText())); + } else { + procDecl2 = + new ProcedureDeclaration(position(token), identifier, (Block) visit(statementBlockContext), + allVariableDeclarations, declarationTypeCopy); + } + return procDecl2; + } + + @Override + public ASTNode visitFunctionDeclaration(FunctionDeclarationContext ctx) { + Identifier identifier; + if (ctx.binaryOperation() == null) { + identifier = new Identifier(getText(ctx.Identifier())); + } else { + identifier = new Identifier("operator" + ctx.binaryOperation().getText()); + } + + return buildProcedures(true, ctx.parameterList(), ctx.getStart(), ctx.type(), ctx.statementBlock(), identifier); + } + + @Override + public ASTNode visitClassDeclaration(ClassDeclarationContext ctx) { + List superClasses = new ArrayList<>(); + if (ctx.typeList() != null) { + for (TypeContext type : ctx.typeList().type()) { + superClasses.add(new ResolvableIdentifier(type.ClassIdentifier().getText())); + } + } + ClassDeclaration cl = + new ClassDeclaration(position(ctx.getStart()), new Identifier(ctx.ClassIdentifier().getText()), + superClasses, new Block(position(ctx.getStart()))); + + currentBlocks.push(cl.getBlock()); + for (MemberDeclarationContext member : ctx.memberDeclaration()) { + currentVariableContext = VariableDeclaration.DeclarationType.ATTRIBUTE; + currentProcedureContext = ProcedureDeclaration.DeclarationType.METHOD; + ASTNode astNode = visit(member); + if (astNode instanceof Declaration) { + + Declaration decl = (Declaration) astNode; + decl.setAccessModifier(AccessModifier.stringToAccess(member.accessModifier().modifier.getText())); + cl.getBlock().addDeclaration(decl); + } else if (astNode instanceof Assignment) { + + Assignment asgnmnt = + new Assignment(astNode.getPosition(), new MemberAccess(astNode.getPosition(), + new SelfExpression(new Position()), ((Assignment) astNode).getLeft()), + ((Assignment) astNode).getRight()); + cl.getBlock().addStatement(asgnmnt); + } + } + currentBlocks.pop(); + return cl; + } + + @Override + public ASTNode visitProcedureDeclaration(ProcedureDeclarationContext ctx) { + ProcedureDeclaration proc = + buildProcedures(false, ctx.parameterList(), ctx.start, null, ctx.statementBlock(), new Identifier( + getText(ctx.Identifier()))); + + List list = proc.getBody().getStatements(); + if ((list.isEmpty()) || !(list.get(list.size() - 1) instanceof ReturnStatement)) { + list.add(new ReturnStatement(new Position(), null)); + } + return proc; + } + + private List parameterListToVarDeclList(ParameterListContext parameter) { + if (parameter == null) { + return new ArrayList<>(); + } + ArrayList parameterList = new ArrayList<>(); + currentVariableContext = VariableDeclaration.DeclarationType.PARAMETER; + for (VariableDeclarationContext var : parameter.variableDeclaration()) { + parameterList.add((VariableDeclaration) visit(var)); + } + return parameterList; + } + + private List defaultParameterListToVarDeclList(ParameterListContext parameter) { + if (parameter == null) { + return new ArrayList<>(); + } + currentVariableContext = VariableDeclaration.DeclarationType.PARAMETER; + return parameter.defaultParameter(); + } + + @Override + public ASTNode visitWhileStatement(WhileStatementContext ctx) { + ASTNode expr = visit(ctx.expression()); + if (!(expr instanceof Expression)) { + + return null; + } + + WhileLoop loop = + new WhileLoop(position(ctx.getStart()), (Expression) expr, (Block) visit(ctx.statementBlock())); + + return loop; + } + + @Override + public ASTNode visitIfStatement(IfStatementContext ctx) { + + Block leastElseBlock = new Block(new Position()); + if (ctx.elseBlock != null) { + leastElseBlock = (Block) visit(ctx.elseBlock); + } + Block firstElseBlock; + + if (ctx.elif().isEmpty()) { + firstElseBlock = leastElseBlock; + } else { + + Block lastElseBlock = new Block(position(ctx.getStart())); + firstElseBlock = lastElseBlock; + Block currentElseBlock; + + for (int i = 0; i < ctx.elif().size(); i++) { + ElifContext currentCtx = ctx.elif(i); + + if (i == ctx.elif().size() - 1) { + currentElseBlock = leastElseBlock; + } else { + currentElseBlock = new Block(position(currentCtx.getStart())); + } + + lastElseBlock.addStatement(new ConditionalStatement(position(ctx.elif().get(i).getStart()), + (Expression) visit(currentCtx.elifCondition), (Block) visit(currentCtx.elifBlock), + currentElseBlock)); + lastElseBlock = currentElseBlock; + + } + } + return new ConditionalStatement(position(ctx.getStart()), (Expression) visit(ctx.ifCondition), + (Block) visit(ctx.thenBlock), firstElseBlock); + + } + + @Override + public ASTNode visitTryStatement(TryStatementContext ctx) { + ASTNode decl = visit(ctx.variableDeclaration().get(0)); + TryStatement tryStm = + new TryStatement(position(ctx.getStart()), (VariableDeclaration) decl, new Block( + position(ctx.getStart())), new Block(position(ctx.getStart()))); + addStatementsToBlock(tryStm.getTryBlock(), ctx.tryBlock.statement()); + addStatementsToBlock(tryStm.getHandleBlock(), ctx.handleBlock.statement()); + return tryStm; + } + + public void addStatementsToBlock(Block block, List statements) { + for (StatementContext stm : statements) { + currentVariableContext = VariableDeclaration.DeclarationType.VARIABLE; + currentProcedureContext = ProcedureDeclaration.DeclarationType.UNBOUND; + ASTNode node = visit(stm); + if (node instanceof Statement) { + block.addStatement((Statement) node); + } else { + block.addDeclaration((Declaration) node); + } + } + } + + @Override + public ASTNode visitIndependentDeclaration(IndependentDeclarationContext ctx) { + ASTNode node; + if (ctx.functionDeclaration() != null) { + node = visit(ctx.functionDeclaration()); + } else if (ctx.procedureDeclaration() != null) { + node = visit(ctx.procedureDeclaration()); + } else { + node = visit(ctx.variableDeclaration()); + if (ctx.expression() != null) { + currentBlocks.peek().addDeclaration((Declaration) node); + return new Assignment(position(ctx.getStart()), new VariableAccess(position(ctx.getStart()), + ResolvableIdentifier.convert(((VariableDeclaration) node).getIdentifier())), + (Expression) visit(ctx.expression())); + } + } + return node; + } + + @Override + public ASTNode visitStatementBlock(StatementBlockContext ctx) { + + Block block = new Block(position(ctx.getStart())); + currentBlocks.push(block); + addStatementsToBlock(block, ctx.statement()); + currentBlocks.pop(); + return block; + } + + @Override + public ASTNode visitReturnStm(ReturnStmContext ctx) { + ASTNode expr = null; + if (ctx.expression() != null) { + + expr = visit(ctx.expression()); + } + + return new ReturnStatement(position(ctx.getStart()), (Expression) expr); + } + + @Override + public ASTNode visitRaiseStm(RaiseStmContext ctx) { + ASTNode expr = null; + if (ctx.expression() != null) { + + expr = visit(ctx.expression()); + } + return new RaiseStatement(position(ctx.getStart()), (Expression) expr); + } + + @Override + public ASTNode visitBreakStm(BreakStmContext ctx) { + + return new BreakStatement(position(ctx.getStart())); + } + + @Override + public ASTNode visitSkipStm(SkipStmContext ctx) { + + return new SkipStatement(position(ctx.getStart())); + } + + @Override + public ASTNode visitExpression(ExpressionContext ctx) { + + if (ctx.primary() != null) { + return visit(ctx.primary()); + } else if (ctx.ifExpCondition != null && ctx.ifExprElse != null && ctx.ifExprThen != null) { + + return visitTernary(ctx); + } else if (ctx.functionCall() != null) { + + return visit(ctx.functionCall()); + } else if (ctx.array != null) { + List arguments = Arrays.asList((Expression) visit(ctx.array), (Expression) visit(ctx.index)); + return new FunctionCall(position(ctx.getStart()), new ResolvableIdentifier("operator[]"), arguments); + } else if (ctx.accessOperator() != null) { + + return visitMemberAccessExpr(ctx); + } else if (ctx.plusMinusOperator() != null && ctx.singleExpression != null) { + + return unaryExpression( + position(ctx.getStart()), + ctx.plusMinusOperator().operator.getText(), + ctx.singleExpression); + } else if (ctx.notOperator() != null) { + + return unaryExpression(position(ctx.getStart()), ctx.notOperator().operator.getText(), ctx.singleExpression); + } else if (ctx.powerOperator() != null) { + + return binaryExpression(position(ctx.getStart()), ctx.powerOperator().getText(), ctx.left, ctx.right); + } else if (ctx.dotOperator() != null) { + + return binaryExpression(position(ctx.getStart()), ctx.dotOperator().getText(), ctx.left, ctx.right); + } else if (ctx.plusMinusOperator() != null) { + + return binaryExpression(position(ctx.getStart()), ctx.plusMinusOperator().getText(), ctx.left, ctx.right); + } else if (ctx.compareOperator() != null) { + + return binaryExpression(position(ctx.getStart()), ctx.compareOperator().getText(), ctx.left, ctx.right); + } else if (ctx.eqOperator() != null) { + + return binaryExpression(position(ctx.getStart()), ctx.eqOperator().getText(), ctx.left, ctx.right); + } else if (ctx.inOperator() != null) { + + return binaryExpression(position(ctx.getStart()), ctx.inOperator().getText(), ctx.left, ctx.right); + } else if (ctx.andOperator() != null) { + + return binaryExpression(position(ctx.getStart()), ctx.andOperator().getText(), ctx.left, ctx.right); + } else if (ctx.orOperator() != null) { + + return binaryExpression(position(ctx.getStart()), ctx.orOperator().getText(), ctx.left, ctx.right); + } else if (ctx.asOperator() != null) { + return visitCastExpression(ctx); + } else if (ctx.isOperator() != null) { + return visitIsExpression(ctx); + } + return null; + } + + @Override + public ASTNode visitPrimary(PrimaryContext ctx) { + if (ctx.singleExpression != null) { + + return visit(ctx.singleExpression); + } else if (ctx.literal() != null) { + + return visit(ctx.literal()); + } else if (ctx.parent != null) { + + return visitParent(ctx); + } else if (ctx.Identifier() != null) { + + return visitIdentifier(ctx); + } else { + + return visitSelf(ctx); + } + } + + @Override + public ASTNode visitLiteral(LiteralContext ctx) { + + if (ctx.IntegerLiteral() != null) { + + return new IntegerLiteral(position(ctx.getStart()), + Integer.parseInt(ctx.IntegerLiteral().getSymbol().getText())); + } else if (ctx.RealLiteral() != null) { + + return new FloatLiteral(position(ctx.getStart()), Float.parseFloat(ctx.RealLiteral().getSymbol().getText())); + } else if (ctx.CharacterLiteral() != null) { + + return new CharacterLiteral(position(ctx.getStart()), + ctx.CharacterLiteral().getSymbol().getText().charAt(1)); + } else if (ctx.StringLiteral() != null) { + + return new StringLiteral(position(ctx.getStart()), ctx.StringLiteral().getSymbol().getText()); + } else if (ctx.arrayLiteral() != null) { + ArrayList elements = new ArrayList<>(); + for (ExpressionContext eContext : ctx.arrayLiteral().expression()) { + elements.add((Expression) visit(eContext)); + } + return new ArrayLiteral(position(ctx.getStart()), elements); + } else { + + return new BooleanLiteral(position(ctx.getStart()), Boolean.parseBoolean(ctx.BooleanLiteral().toString())); + } + } + + public ASTNode visitIdentifier(PrimaryContext ctx) { + + return new VariableAccess(position(ctx.getStart()), new ResolvableIdentifier(getText(ctx.Identifier()))); + } + + public ASTNode visitSelf(PrimaryContext ctx) { + + return new SelfExpression(position(ctx.getStart())); + } + + public ParentExpression visitParent(PrimaryContext ctx) { + return new ParentExpression(position(ctx.getStart()), new ResolvableIdentifier(getText(ctx.ClassIdentifier()))); + } + + public ASTNode visitTernary(ExpressionContext ctx) { + ASTNode condition = visit(ctx.ifExpCondition); + ASTNode thenExpr = visit(ctx.ifExprThen); + ASTNode elseExpr = visit(ctx.ifExprElse); + return new ConditionalExpression(position(ctx.getStart()), (Expression) condition, (Expression) thenExpr, + (Expression) elseExpr); + } + + @Override + public ASTNode visitMemberAccessStmt(@NotNull MemberAccessStmtContext ctx) { + ASTNode left = visit(ctx.left); + ASTNode right = visit(ctx.right); + return new MemberAccess(position(ctx.getStart()), (Expression) left, (Expression) right); + } + + public ASTNode visitMemberAccessExpr(ExpressionContext ctx) { + ASTNode left = visit(ctx.left); + ASTNode right = visit(ctx.right); + return new MemberAccess(position(ctx.getStart()), (Expression) left, (Expression) right); + } + + private MemberAccess unaryExpression(Position position, String operator, ExpressionContext expr) { + String underscore = ""; + if (operator.equals("not")) { + underscore = "_"; + } + Expression self = (Expression) visit(expr); + FunctionCall operatorCall = + new FunctionCall(position, new ResolvableIdentifier("operator" + underscore + operator), + new ArrayList()); + return new MemberAccess(position, self, operatorCall); + } + + private MemberAccess binaryExpression(Position position, String operator, ExpressionContext left, + ExpressionContext right) { + String underscore = ""; + List needsUnderscore = Arrays.asList("and", "or", "xor", "in"); + if (needsUnderscore.contains(operator)) { + underscore = "_"; + } + Expression self = (Expression) visit(left); + FunctionCall operatorCall = + new FunctionCall(position, new ResolvableIdentifier("operator" + underscore + operator), + Arrays.asList((Expression) visit(right))); + return new MemberAccess(position, self, operatorCall); + } + + private CastExpression visitCastExpression(ExpressionContext ctx) { + return new CastExpression(position(ctx.getStart()), (Expression) visit(ctx.expr), new ResolvableIdentifier( + getText(ctx.ClassIdentifier()))); + } + + private IsExpression visitIsExpression(ExpressionContext ctx) { + return new IsExpression(position(ctx.getStart()), (Expression) visit(ctx.expr), new ResolvableIdentifier( + getText(ctx.ClassIdentifier()))); + } + + protected ASTNode aggregateResult(ASTNode aggregate, ASTNode nextResult) { + return nextResult == null ? aggregate : nextResult; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/ASTNode.java b/src/main/java/de/uni/bremen/monty/moco/ast/ASTNode.java new file mode 100644 index 0000000..1ebb824 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/ASTNode.java @@ -0,0 +1,77 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast; + +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +public interface ASTNode { + + ASTNode getParentNode(); + + void setParentNode(ASTNode parentNode); + + Position getPosition(); + + void setScope(Scope scope); + + Scope getScope(); + + /** Visit this node using double-dispatch. + *

+ * This method is only called from within the BaseVisitor. Every actual subclass must implement this method with the + * following body: + * + *

+	 * {@code visitor.visit(this);}
+	 * 
. + * + * @param visitor + * the visitor to visit this node */ + void visit(BaseVisitor visitor); + + /** Comfort method to visit all children. + *

+ * Can be used from any visitor if the traversal order does not matter. The BaseVisitor uses this method by default. @ + * param visitor the visitor to viit this node + * + * @param visitor + * the visitor to visit this node */ + void visitChildren(BaseVisitor visitor); + +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/AccessModifier.java b/src/main/java/de/uni/bremen/monty/moco/ast/AccessModifier.java new file mode 100644 index 0000000..2341483 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/AccessModifier.java @@ -0,0 +1,62 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast; + +public enum AccessModifier { + + PUBLIC, PRIVATE, PROTECTED, PACKAGE; + + public static AccessModifier stringToAccess(String AccessStr) { + + switch (AccessStr) { + + case "+": + return AccessModifier.PUBLIC; + case "-": + return AccessModifier.PRIVATE; + case "#": + return AccessModifier.PROTECTED; + case "~": + return AccessModifier.PACKAGE; + default: + return AccessModifier.PUBLIC; + } + } + +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/AntlrAdapter.java b/src/main/java/de/uni/bremen/monty/moco/ast/AntlrAdapter.java new file mode 100644 index 0000000..370340d --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/AntlrAdapter.java @@ -0,0 +1,78 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ + +package de.uni.bremen.monty.moco.ast; + +import de.uni.bremen.monty.moco.antlr.MontyLexer; +import de.uni.bremen.monty.moco.antlr.MontyParser; +import de.uni.bremen.monty.moco.ast.declaration.ModuleDeclaration; +import org.antlr.v4.runtime.ANTLRInputStream; +import org.antlr.v4.runtime.CommonTokenStream; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.SequenceInputStream; + +public class AntlrAdapter { + + public MontyParser createParser(final InputStream file) throws IOException { + + InputStream in = createInputStream(file); + + // the additional line-break is needed because of our indentation rule + // and the fact that a statement should be terminated by a line break + ANTLRInputStream input = new ANTLRInputStream(in); + MontyLexer lexer = new MontyLexer(input); + CommonTokenStream tokens = new CommonTokenStream(lexer); + return new MontyParser(tokens); + } + + private InputStream createInputStream(InputStream file) { + return new SequenceInputStream(file, new ByteArrayInputStream("\n".getBytes())); + } + + public ModuleDeclaration parse(InputStream file, String fileName) throws IOException { + MontyParser parser = createParser(file); + + ASTBuilder astBuilder = new ASTBuilder(fileName); + ASTNode moduleNode = astBuilder.visit(parser.compilationUnit()); + return (ModuleDeclaration) moduleNode; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/BasicASTNode.java b/src/main/java/de/uni/bremen/monty/moco/ast/BasicASTNode.java new file mode 100644 index 0000000..74a5ce3 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/BasicASTNode.java @@ -0,0 +1,109 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast; + +/** Baseclass for every node in the AST. */ +public abstract class BasicASTNode implements ASTNode { + + /** Sourcecode position of this node. */ + private final Position position; + + /** Parent node. */ + private ASTNode parentNode; + + /** Associated scope. */ + private Scope scope; + + /** Constructor. + * + * @param position + * Position of this node */ + public BasicASTNode(Position position) { + this.position = position; + } + + /** {@inheritDoc} */ + @Override + public String toString() { + return getClass().getSimpleName(); + } + + /** Get parent node. + * + * @return the parent node */ + @Override + public ASTNode getParentNode() { + return parentNode; + } + + /** Set parent node. + * + * @param parentNode + * the parent node */ + @Override + public void setParentNode(ASTNode parentNode) { + this.parentNode = parentNode; + } + + /** Get the sourcecode position. + * + * @return the position */ + @Override + public Position getPosition() { + return position; + } + + /** Set the associated scope. + * + * @param scope + * the associated scope */ + @Override + public void setScope(Scope scope) { + this.scope = scope; + } + + /** Get the accociated scope. + * + * @return the scope */ + @Override + public Scope getScope() { + return scope; + } + +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/Block.java b/src/main/java/de/uni/bremen/monty/moco/ast/Block.java new file mode 100644 index 0000000..9948137 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/Block.java @@ -0,0 +1,119 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast; + +import java.util.*; + +import de.uni.bremen.monty.moco.ast.declaration.Declaration; +import de.uni.bremen.monty.moco.ast.statement.Statement; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +/** This node represents a block. + * + * A block contains declarations and statements. The declarations must be processed first. */ +public class Block extends BasicASTNode { + + /** The statements. */ + private final List statements; + + /** The declarations. */ + private final List declarations; + + /** Constructor. + * + * @param position + * Position of this node */ + public Block(Position position) { + super(position); + statements = new ArrayList(); + declarations = new ArrayList(); + } + + /** @return true if the block does not have any statements or declarations. */ + public boolean isEmpty() { + return statements.isEmpty() && declarations.isEmpty(); + } + + /** Add a statement to this block. + * + * @param statement + * the statement to add */ + public void addStatement(Statement statement) { + statements.add(statement); + } + + /** Add a declaration to this block. + * + * @param declaration + * the declaration to add */ + public void addDeclaration(Declaration declaration) { + declarations.add(declaration); + } + + /** Get the statements of this block. + * + * @return the statements */ + public List getStatements() { + return statements; + } + + /** Get the declarations of this block. + * + * @return the declarations */ + public List getDeclarations() { + return declarations; + } + + /** {@inheritDoc} */ + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + + /** {@inheritDoc} */ + @Override + public void visitChildren(BaseVisitor visitor) { + for (Declaration declaration : declarations) { + visitor.visitDoubleDispatched(declaration); + } + for (Statement statement : statements) { + visitor.visitDoubleDispatched(statement); + } + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/ClassScope.java b/src/main/java/de/uni/bremen/monty/moco/ast/ClassScope.java new file mode 100644 index 0000000..69b256a --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/ClassScope.java @@ -0,0 +1,159 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast; + +import de.uni.bremen.monty.moco.ast.declaration.*; +import de.uni.bremen.monty.moco.exception.*; +import java.util.List; +import java.util.ArrayList; + +/** A scope in which identifier are associated with declarations. + *

+ * To nest scopes or build a stack the parent scope is passed as an argument to the construtor. So you use it like this + *

+ * + *

+ * {@code
+ * // create a new scope and nest the old one
+ * currentScope = new ClassScope(currentScope);
+ * // do something
+ * // destroy this scope and use the old (nested) one
+ * currentScope = currentScope.getParentScope();
+ * }
+ * 
+ *

+ * This special scope searches its associations, the parent classes in inheritance hierachy and only then the parent + * scope. + *

+ * Note: only single inheritance so far. */ +public class ClassScope extends Scope { + + /** The parent class in inheritance hierachy. */ + private List parentClassesScopes; + + /** Constructor. + * + * @param parent + * the parent scope in nesting hierachy */ + public ClassScope(Scope parent) { + super(parent); + this.parentClassesScopes = new ArrayList<>(); + } + + public void addParentClassScope(ClassScope scope) { + parentClassesScopes.add(scope); + } + + /** Resolve an identifier in inherited scopes. + * + * @param identifier + * the identifier + * @return the declaration or null if nothing is found */ + protected Declaration resolveMember(ResolvableIdentifier identifier) { + Declaration declaration = members.get(identifier); + + if (declaration != null) { + return declaration; + } + for (ClassScope scope : parentClassesScopes) { + declaration = scope.resolveMember(identifier); + if (declaration != null) { + return declaration; + } + } + return null; + } + + /** Resolve an identifier for list of overloaded procedures or functions in inherited scope. + * + * @param identifier + * the identifier to resolve + * @return the list of procedure declarations */ + protected List resolveProcedureMember(ResolvableIdentifier identifier) { + List result = new ArrayList(); + + if (procedures.containsKey(identifier)) { + result.addAll(procedures.get(identifier)); + } + for (ClassScope scope : parentClassesScopes) { + result.addAll(scope.resolveProcedureMember(identifier)); + } + return result; + } + + /** Resolve an identifier for a declaration + *

+ * It first searches its associations, the parent classes in inheritance hierachy and only then the parent scope. + * + * @param identifier + * the identifier to resolve + * @return the declaration or null if nothing is found */ + @Override + public Declaration resolve(ResolvableIdentifier identifier) { + Declaration declaration = resolveMember(identifier); + + if (declaration != null) { + return declaration; + } + return super.resolve(identifier); + } + + /** Resolve an identifier for list of overloaded procedures or functions. + *

+ * It first searches its associations, the parent classes in inheritance hierachy and only then the parent scope. + * + * @param identifier + * the identifier to resolve + * @return the list of procedure declarations */ + @Override + public List resolveProcedure(ResolvableIdentifier identifier) { + List result = new ArrayList(); + result.addAll(resolveProcedureMember(identifier)); + if (parent != null) { + try { + result.addAll(parent.resolveProcedure(identifier)); + } catch (UnknownIdentifierException e) { + } + } + if (result.isEmpty()) { + throw new UnknownIdentifierException(identifier); + } + return result; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/CoreClasses.java b/src/main/java/de/uni/bremen/monty/moco/ast/CoreClasses.java new file mode 100644 index 0000000..71ed950 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/CoreClasses.java @@ -0,0 +1,102 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ + +package de.uni.bremen.monty.moco.ast; + +import de.uni.bremen.monty.moco.ast.declaration.ClassDeclaration; + +import java.util.Map; +import java.util.HashMap; +import java.util.Collection; +import java.util.Collections; + +public class CoreClasses { + + private static Map coreClasses = new HashMap(); + + static { + // TODO find name for void that is not a valid identifier + String[] classNames = new String[] { "Object", "Char", "String", "Int", "Float", "Bool", "Array", "__void" }; + for (String name : classNames) { + CoreClasses.setCoreClass(name, new ClassDeclaration(new Position("Dummy_" + name, 0, 0), new Identifier( + name), Collections. emptyList(), new Block( + new Position("Dummy_" + name, 1, 0)))); + } + } + + public static Collection getAllCoreClasses() { + return coreClasses.values(); + } + + public static void setCoreClass(String name, ClassDeclaration classDeclaration) { + coreClasses.put(name, classDeclaration); + } + + public static ClassDeclaration objectType() { + return coreClasses.get("Object"); + } + + public static ClassDeclaration charType() { + return coreClasses.get("Char"); + } + + public static ClassDeclaration stringType() { + return coreClasses.get("String"); + } + + public static ClassDeclaration intType() { + return coreClasses.get("Int"); + } + + public static ClassDeclaration floatType() { + return coreClasses.get("Float"); + } + + public static ClassDeclaration boolType() { + return coreClasses.get("Bool"); + } + + public static ClassDeclaration arrayType() { + return coreClasses.get("Array"); + } + + public static ClassDeclaration voidType() { + return coreClasses.get("__void"); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/Identifier.java b/src/main/java/de/uni/bremen/monty/moco/ast/Identifier.java new file mode 100644 index 0000000..f3de556 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/Identifier.java @@ -0,0 +1,93 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast; + +/** An Identifier is the user defined name of a declaration. + *

+ * During context-analysis the identifier with an associated declaration is stored in a scope. */ +public class Identifier { + + /** The name of the declaration. */ + private final String symbol; + + /** Constructor. + * + * @param symbol + * the name of the declaration */ + public Identifier(String symbol) { + this.symbol = symbol; + } + + /** Get the name of the declaration. + * + * @return the name */ + public String getSymbol() { + return symbol; + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } else if (other == null) { + return false; + } + + if (other instanceof Identifier) { + Identifier that = (Identifier) other; + return getSymbol().equals(that.getSymbol()); + } + + return false; + } + + @Override + public int hashCode() { + return symbol.hashCode(); + } + + @Override + public String toString() { + return symbol; + } + + public static Identifier convert(ResolvableIdentifier identifier) { + return new Identifier(identifier.getSymbol()); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/Import.java b/src/main/java/de/uni/bremen/monty/moco/ast/Import.java new file mode 100644 index 0000000..2ae0a3a --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/Import.java @@ -0,0 +1,70 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast; + +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +/** Represent the imported modules. */ +public class Import extends BasicASTNode { + + /** The identifier of the importline */ + private ResolvableIdentifier identifier; + + /** Constructor. + * + * @param position + * Position of this node */ + public Import(Position position, ResolvableIdentifier identifier) { + super(position); + this.identifier = identifier; + } + + /** {@inheritDoc} */ + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + + /** {@inheritDoc} */ + @Override + public void visitChildren(BaseVisitor visitor) { + // throw new NotYetImplementedException(); + } + +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/Package.java b/src/main/java/de/uni/bremen/monty/moco/ast/Package.java new file mode 100644 index 0000000..3ccb27c --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/Package.java @@ -0,0 +1,109 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ + +package de.uni.bremen.monty.moco.ast; + +import de.uni.bremen.monty.moco.ast.declaration.ModuleDeclaration; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +import java.util.ArrayList; +import java.util.List; + +public class Package extends BasicASTNode { + + private Identifier name; + + private List modules; + private List subPackages; + private boolean nativePackage = false; + + /** Constructor. + * + * @param name */ + public Package(Identifier name) { + super(new Position()); + this.name = name; + modules = new ArrayList<>(); + subPackages = new ArrayList<>(); + } + + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + + @Override + public void visitChildren(BaseVisitor visitor) { + for (Package subPackage : subPackages) { + visitor.visit(subPackage); + } + for (ModuleDeclaration module : modules) { + visitor.visit(module); + } + } + + public void addModule(ModuleDeclaration module) { + modules.add(module); + } + + public void addSubPackage(Package aPackage) { + subPackages.add(aPackage); + } + + public List getModules() { + return modules; + } + + public List getModulesRecursive() { + List allModules = new ArrayList<>(); + allModules.addAll(modules); + for (Package subPackage : subPackages) { + allModules.addAll(subPackage.getModulesRecursive()); + } + return allModules; + } + + public boolean isNativePackage() { + return nativePackage; + } + + public void setNativePackage(boolean nativePackage) { + this.nativePackage = nativePackage; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/PackageBuilder.java b/src/main/java/de/uni/bremen/monty/moco/ast/PackageBuilder.java new file mode 100644 index 0000000..31615b9 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/PackageBuilder.java @@ -0,0 +1,157 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ + +package de.uni.bremen.monty.moco.ast; + +import de.uni.bremen.monty.moco.ast.declaration.*; +import de.uni.bremen.monty.moco.util.MontyFile; +import de.uni.bremen.monty.moco.util.MontyJar; +import de.uni.bremen.monty.moco.util.MontyResource; +import de.uni.bremen.monty.moco.util.Params; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.Collections; + +public class PackageBuilder { + private final AntlrAdapter antlrAdapter; + private Params params; + + public PackageBuilder(Params params) { + this.params = params; + antlrAdapter = new AntlrAdapter(); + } + + public Package buildPackage() throws IOException { + Package basePackage = new Package(new Identifier("")); + String inputFile = params.getInputFile(); + if (inputFile != null) { + basePackage.addSubPackage(createPackageFromSingleModule(inputFile)); + } else { + basePackage.addSubPackage(createPackageFromSourceFolder(params)); + } + addCoreLib(basePackage); + return basePackage; + } + + private void addCoreLib(Package basePackage) throws IOException { + Package corePackage = createPackage(getCoreLibFolder()); + corePackage.setNativePackage(true); + basePackage.addSubPackage(corePackage); + + Block block = new Block(new Position()); + ModuleDeclaration module = + new ModuleDeclaration(new Position(), new Identifier("CoreClasses"), block, + Collections. emptyList()); + block.addDeclaration(CoreClasses.stringType()); + block.addDeclaration(CoreClasses.arrayType()); + block.addDeclaration(CoreClasses.voidType()); + corePackage.addModule(module); + setCoreClasses(corePackage); + } + + private void setCoreClasses(Package corePackage) { + for (ModuleDeclaration module : corePackage.getModulesRecursive()) { + for (Declaration declaration : module.getBlock().getDeclarations()) { + if (declaration instanceof ClassDeclaration) { + ClassDeclaration classDeclaration = (ClassDeclaration) declaration; + CoreClasses.setCoreClass(classDeclaration.getIdentifier().getSymbol(), classDeclaration); + } + } + } + } + + private MontyResource getCoreLibFolder() { + try { + Class aClass = PackageBuilder.class; + ClassLoader classLoader = aClass.getClassLoader(); + URL testProgramFolder = classLoader.getResource("corelib/"); + if (testProgramFolder.toString().startsWith("jar:")) { + return new MontyJar(testProgramFolder); + } else { + return new MontyFile(testProgramFolder.toURI()); + } + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private Package createPackageFromSourceFolder(Params params) throws IOException { + String baseFolder = params.getInputFolder(); + MontyResource inputFolder = new MontyFile(baseFolder); + return createPackage(inputFolder); + } + + private Package createPackageFromSingleModule(String inputFile) throws IOException { + MontyResource file = new MontyFile(inputFile); + + Package mainPackage = new Package(new Identifier("")); + addModules(new MontyResource[] { file }, mainPackage); + return mainPackage; + } + + private Package createPackage(MontyResource inputFolder) throws IOException { + MontyResource[] montyFiles = inputFolder.listSubModules(); + return createPackage(inputFolder, montyFiles); + } + + private Package createPackage(MontyResource inputFolder, MontyResource[] montyFiles) throws IOException { + Package mainPackage = new Package(new Identifier(inputFolder.getName())); + addModules(montyFiles, mainPackage); + addSubPackages(inputFolder, mainPackage); + return mainPackage; + } + + private void addModules(MontyResource[] montyFiles, Package aPackage) throws IOException { + for (MontyResource file : montyFiles) { + ModuleDeclaration module = antlrAdapter.parse(file.toInputStream(), file.getName()); + aPackage.addModule(module); + } + } + + private void addSubPackages(MontyResource inputFolder, Package mainPackage) throws IOException { + MontyResource[] subPackages = inputFolder.listSubPackages(); + for (MontyResource subPackage : subPackages) { + mainPackage.addSubPackage(createPackage(subPackage)); + } + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/Position.java b/src/main/java/de/uni/bremen/monty/moco/ast/Position.java new file mode 100644 index 0000000..48fe8c6 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/Position.java @@ -0,0 +1,96 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast; + +/** Represents a position in the source code. */ +public class Position { + + /** The source file name. */ + private String fileName = ""; + + /** The source file line number. */ + private int lineNumber = 0; + + /** The source file char number. */ + private int charNumber = 0; + + /** Default constructor. */ + public Position() { + + } + + /** Constructor. + * + * @param fileName + * the source file name + * @param lineNumber + * the source file line number + * @param charNumber + * the source file char number */ + public Position(String fileName, int lineNumber, int charNumber) { + this.fileName = fileName; + this.lineNumber = lineNumber; + this.charNumber = charNumber; + } + + public String toString() { + return String.format("file: %s, line: %d, char: %d", fileName, lineNumber, charNumber); + } + + /** Get the source file name. + * + * @return the source file name */ + public String getFileName() { + return fileName; + } + + /** Get the source file line number. + * + * @return the souce file line number */ + public int getLineNumber() { + return lineNumber; + } + + /** Get the source file char number. + * + * @return the source file char number */ + public int getCharNumber() { + return charNumber; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/ResolvableIdentifier.java b/src/main/java/de/uni/bremen/monty/moco/ast/ResolvableIdentifier.java new file mode 100644 index 0000000..bd43f14 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/ResolvableIdentifier.java @@ -0,0 +1,57 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast; + +/** A ResolvableIdentifier is similar to the Identifier a name of a declaration. + *

+ * During context-analysis this is resolved to a declaration using a scope. */ +public class ResolvableIdentifier extends Identifier { + + /** Constructor. + * + * @param symbol + * the name of the declaration */ + public ResolvableIdentifier(String symbol) { + super(symbol); + } + + public static ResolvableIdentifier convert(Identifier identifier) { + return new ResolvableIdentifier(identifier.getSymbol()); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/Scope.java b/src/main/java/de/uni/bremen/monty/moco/ast/Scope.java new file mode 100644 index 0000000..9ceb4e1 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/Scope.java @@ -0,0 +1,202 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast; + +import java.util.*; + +import de.uni.bremen.monty.moco.ast.declaration.*; +import de.uni.bremen.monty.moco.exception.*; + +/** A scope in which an identifier is associated with a declaration. + *

+ * To nest scopes or build a stack the parent scope is passed as an argument to the constructor. So you use it like + * this: + *

+ * + *

+ * {@code
+ * // create a new scope and nest the old one
+ * currentScope = new Scope(currentScope);
+ * // do something
+ * // destroy this scope and use the old (nested) one
+ * currentScope = currentScope.getParentScope();
+ * }
+ * 
*/ +public class Scope { + + /** The parent scope in nesting hierarchy. */ + protected Scope parent; + + /** The map to store the associations to procedure declarations. */ + protected Map> procedures; + + /** The map to store the remaining associations. */ + protected Map members; + + /** Constructor. + * + * @param parent + * the parent scope in nesting hierarchy */ + public Scope(Scope parent) { + this.parent = parent; + procedures = new HashMap>(); + members = new HashMap(); + } + + /** Get the parent scope in nesting hierarchy. + *

+ * This method acts as the 'pop()'-operation in the scope-stack analogy. + * + * @return the parent scope */ + public Scope getParentScope() { + return parent; + } + + /** Resolve an identifier for a declaration. + *

+ * First the declarations of this scope are searched. If the not successful the search continues recursively in the + * parent scope. + * + * @param identifier + * the identifier to resolve + * @return the declaration */ + public Declaration resolve(ResolvableIdentifier identifier) { + Declaration declaration = members.get(identifier); + + if (declaration != null) { + return declaration; + } + if (parent != null) { + return parent.resolve(identifier); + } + throw new UnknownIdentifierException(identifier); + } + + /** Resolve an identifier for a type declaration. + * + * @param identifier + * the identifier to resolve + * @return the declaration */ + public TypeDeclaration resolveType(ResolvableIdentifier identifier) { + try { + Declaration declaration = resolve(identifier); + if (declaration instanceof TypeDeclaration) { + return (TypeDeclaration) declaration; + } + throw new UnknownTypeException(identifier); + } catch (UnknownIdentifierException e) { + throw new UnknownTypeException(identifier); + } + } + + /** Resolve an identifier for list of overloaded procedures or functions. + * + * @param identifier + * the identifier to resolve + * @return the list of procedure declarations */ + public List resolveProcedure(ResolvableIdentifier identifier) { + List result = new ArrayList(); + + if (procedures.containsKey(identifier)) { + result.addAll(procedures.get(identifier)); + } + if (parent != null) { + try { + result.addAll(parent.resolveProcedure(identifier)); + } catch (UnknownIdentifierException e) { + } + } + if (result.isEmpty()) { + throw new UnknownIdentifierException(identifier); + } + return result; + } + + /** Associate an identifier with a declaration. + * + * This method uses define(Identifier, ProcedureDeclaration) if the given declaration is a procedure or function + * declaration. + * + * @param identifier + * the identifier + * @param declaration + * the declaration + * @throws RedeclarationException + * if the identifier is already defined or this is invalid overloading */ + public void define(Identifier identifier, Declaration declaration) throws RedeclarationException { + if (declaration instanceof ProcedureDeclaration) { + define(identifier, (ProcedureDeclaration) declaration); + } else if (members.get(identifier) != null) { + throw new RedeclarationException(declaration, identifier.getSymbol()); + } else { + members.put(identifier, declaration); + } + } + + /** Associate an identifier with a declaration. + *

+ * This differs from define(Identifier, Declaration) as this method uses the declaration's Identifier-attribute to + * call define(Identifier, Declaration) + * + * @param declaration + * the declaration + * @throws RedeclarationException + * if the identifier is already defined or this is invalid overloading */ + public void define(Declaration declaration) throws RedeclarationException { + define(declaration.getIdentifier(), declaration); + } + + /** Associate an identifier with a procedure or function declaration. + * + * This takes overloading into account and throws a RedeclarationException if the declaration is an instance of + * invalid overloading. + * + * @param identifier + * the identifier + * @param declaration + * the declaration + * @throws RedeclarationException + * if this is invalid overloading */ + public void define(Identifier identifier, ProcedureDeclaration declaration) throws RedeclarationException { + if (!procedures.containsKey(identifier)) { + procedures.put(identifier, new ArrayList()); + } + procedures.get(identifier).add(declaration); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/declaration/ClassDeclaration.java b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/ClassDeclaration.java new file mode 100644 index 0000000..75eda41 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/ClassDeclaration.java @@ -0,0 +1,188 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.declaration; + +import de.uni.bremen.monty.moco.ast.Block; +import de.uni.bremen.monty.moco.ast.Identifier; +import de.uni.bremen.monty.moco.ast.Position; +import de.uni.bremen.monty.moco.ast.ResolvableIdentifier; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +import java.util.List; +import java.util.ArrayList; + +/** A ClassDeclaration represents the declaration of a class in the AST. + *

+ * A ClassDeclaration has a list of superclasses and a list of nested declarations. It can be used as a type. */ +public class ClassDeclaration extends TypeDeclaration { + + /** Identifier of superclasses. */ + private final List superClassIdentifiers = new ArrayList<>(); + + /** Superclasses. */ + private final List superClassDeclarations = new ArrayList<>(); + + /** The generated default initializer to be called from every user defined initializer. */ + private ProcedureDeclaration defaultInitializer; + + /** Block with assignments */ + private final Block block; + + /** The virtal method table for this class */ + private List virtualMethodTable = new ArrayList<>(); + + /** The last index for the attributes of this class. This counter starts at `1` as index 0 is reserved for a pointer + * to the vmt. */ + private int lastAttributeIndex = 1; + + /** Constructor. + * + * @param position + * Position of this node + * @param identifier + * the identifier + * @param superClasses + * a list of direct super-classes + * @param block + * the block */ + public ClassDeclaration(Position position, Identifier identifier, List superClasses, + Block block) { + super(position, identifier); + this.block = block; + this.superClassIdentifiers.addAll(superClasses); + } + + /** Get the list of declarations and assignments. + * + * @return the block with declarations and assignments */ + public Block getBlock() { + return block; + } + + /** Get the list of identifiers of direct superclasses + * + * @return the identifier of superclasses */ + public List getSuperClassIdentifiers() { + return superClassIdentifiers; + } + + /** Get the list of direct superclasses this class inherits from. + * + * @return the superclasses */ + public List getSuperClassDeclarations() { + return superClassDeclarations; + } + + /** Get a list of all the declarations of superclasses and this one. */ + public List getSuperClassDeclarationsRecursive() { + List allSuperClassDeclarations = new ArrayList<>(); + for (TypeDeclaration superClass : superClassDeclarations) { + if (superClass instanceof ClassDeclaration) { + allSuperClassDeclarations.addAll(((ClassDeclaration) superClass).getSuperClassDeclarationsRecursive()); + } + } + allSuperClassDeclarations.add(this); + return allSuperClassDeclarations; + } + + /** set the last attribute index. + * + * @param lastAttributeIndex + * the last attribute index */ + public void setLastAttributeIndex(int lastAttributeIndex) { + this.lastAttributeIndex = lastAttributeIndex; + } + + /** get the last attribute index + * + * @return the last attribute index */ + public int getLastAttributeIndex() { + return lastAttributeIndex; + } + + /** Get the VMT. + * + * @return the VMT */ + public List getVirtualMethodTable() { + return virtualMethodTable; + } + + /** Get the default initializer. + * + * @return the default initializer */ + public ProcedureDeclaration getDefaultInitializer() { + return this.defaultInitializer; + } + + /** Set the default initializer. + * + * @param defaultInitializer + * the new default initializer */ + public void setDefaultInitializer(ProcedureDeclaration defaultInitializer) { + this.defaultInitializer = defaultInitializer; + } + + /** {@inheritDoc} */ + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + + /** {@inheritDoc} */ + @Override + public void visitChildren(BaseVisitor visitor) { + visitor.visitDoubleDispatched(block); + } + + /** {@inheritDoc} */ + @Override + public boolean matchesType(TypeDeclaration other) { + if (super.matchesType(other)) { + return true; + } + if (other instanceof ClassDeclaration) { + for (TypeDeclaration parentClass : superClassDeclarations) { + if (parentClass.matchesType(other)) { + return true; + } + } + } + return false; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/declaration/Declaration.java b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/Declaration.java new file mode 100644 index 0000000..3148ccc --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/Declaration.java @@ -0,0 +1,99 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.declaration; + +import de.uni.bremen.monty.moco.ast.*; + +/** The baseclass of every declaration. + *

+ * A declaration has an identifier, the name under which this declaration is known. */ +public abstract class Declaration extends BasicASTNode { + + /** The identifier. */ + private final Identifier identifier; + + /** The mangled identifier. */ + private Identifier mangledIdentifier; + + private AccessModifier access; + + /** Constructor. + * + * @param position + * Position of this node + * @param identifier + * the identifier */ + public Declaration(Position position, Identifier identifier) { + super(position); + this.identifier = identifier; + this.access = AccessModifier.PUBLIC; + } + + public Declaration(Position position, Identifier identifier, AccessModifier access) { + super(position); + this.identifier = identifier; + this.access = access; + } + + public void setAccessModifier(AccessModifier access) { + + this.access = access; + } + + /** Get the mangled Identifier. + * + * @return mangled Identifier */ + public Identifier getMangledIdentifier() { + return mangledIdentifier; + } + + /** Set the mangled Identifier. + * + * @param mangledIdentifier */ + public void setMangledIdentifier(Identifier mangledIdentifier) { + this.mangledIdentifier = mangledIdentifier; + } + + /** Get the identifier. + * + * @return the identifier */ + public Identifier getIdentifier() { + return identifier; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/declaration/FunctionDeclaration.java b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/FunctionDeclaration.java new file mode 100644 index 0000000..718d0c2 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/FunctionDeclaration.java @@ -0,0 +1,148 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.declaration; + +import de.uni.bremen.monty.moco.ast.*; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +import java.util.List; + +/** A FunctionDeclaration represents the declaration of a function in the AST. + *

+ * It can be used as a returnType. */ +public class FunctionDeclaration extends ProcedureDeclaration { + + /** The return returnType. */ + private ResolvableIdentifier returnTypeIdentifier; + private TypeDeclaration returnType; + + /** Constructor. + * + * @param position + * Position of this node + * @param identifier + * the identifier + * @param body + * the body of this function + * @param parameter + * the parameter of this function + * @param returnTypeIdentifier + * the return returnType */ + public FunctionDeclaration(Position position, Identifier identifier, Block body, + List parameter, ProcedureDeclaration.DeclarationType declarationType, + ResolvableIdentifier returnTypeIdentifier) { + super(position, identifier, body, parameter, declarationType); + this.returnTypeIdentifier = returnTypeIdentifier; + } + + public FunctionDeclaration(Position position, Identifier identifier, Block body, + List parameter, ResolvableIdentifier returnTypeIdentifier) { + this(position, identifier, body, parameter, ProcedureDeclaration.DeclarationType.UNBOUND, returnTypeIdentifier); + } + + /** Constructor + * + * @param position + * * Position of this node + * @param identifier + * the identifier + * @param body + * the body of this function + * @param parameter + * the parameter of this function + * @param returnType + * the return returnType */ + public FunctionDeclaration(Position position, Identifier identifier, Block body, + List parameter, ClassDeclaration returnType) { + super(position, identifier, body, parameter); + this.returnType = returnType; + this.returnTypeIdentifier = ResolvableIdentifier.convert(returnType.getIdentifier()); + } + + /** get the return returnType. + * + * @return the return returnType */ + public ResolvableIdentifier getReturnTypeIdentifier() { + return returnTypeIdentifier; + } + + /** {@inheritDoc} */ + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + + /** {@inheritDoc} */ + @Override + public void visitChildren(BaseVisitor visitor) { + super.visitChildren(visitor); + } + + /** get the returnType. + * + * @return the returnType */ + public TypeDeclaration getReturnType() { + return returnType; + } + + /** set the returnType + * + * @param returnType */ + public void setReturnType(TypeDeclaration returnType) { + this.returnType = returnType; + } + + /** Check equality of two types taking into account the AST object hierachy. + *

+ * + * @param other + * the other TypeDeclaration to check against + * @return if equal */ + @Override + public boolean matchesType(TypeDeclaration other) { + if (!super.matchesType(other)) { + return false; + } + if (!(other instanceof FunctionDeclaration)) { + return true; + } + FunctionDeclaration function = (FunctionDeclaration) other; + return returnType.matchesType(function.getReturnType()); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/declaration/ModuleDeclaration.java b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/ModuleDeclaration.java new file mode 100644 index 0000000..688bf0a --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/ModuleDeclaration.java @@ -0,0 +1,101 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.declaration; + +import java.util.List; + +import de.uni.bremen.monty.moco.ast.*; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +/** A ModuleDeclaration represents the declaration of a module in the AST. + *

+ * It can be used as a type. */ +public class ModuleDeclaration extends TypeDeclaration { + + /** The imports in this module. */ + private final List imports; + + /** The nested statements and declarations. */ + private final Block block; + + /** Constructor. + * + * @param position + * Position of this node + * @param identifier + * the identifier + * @param block + * the nested declarations and statements + * @param imports + * the imports in this module */ + public ModuleDeclaration(Position position, Identifier identifier, Block block, List imports) { + super(position, identifier); + this.imports = imports; + this.block = block; + } + + /** Get the body block. + * + * @return the block */ + public Block getBlock() { + return block; + } + + /** Get the list of imports. + * + * @return the imports */ + public List getImports() { + return imports; + } + + /** {@inheritDoc} */ + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + + /** {@inheritDoc} */ + @Override + public void visitChildren(BaseVisitor visitor) { + for (Import imp : imports) { + visitor.visitDoubleDispatched(imp); + } + visitor.visitDoubleDispatched(block); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/declaration/ProcedureDeclaration.java b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/ProcedureDeclaration.java new file mode 100644 index 0000000..6a769d6 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/ProcedureDeclaration.java @@ -0,0 +1,184 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.declaration; + +import java.util.List; + +import de.uni.bremen.monty.moco.ast.*; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +/** A ProcedureDeclaration represents the declaration of a procedure in the AST. + *

+ * It can be used as a type. */ +public class ProcedureDeclaration extends TypeDeclaration { + public enum DeclarationType { + INITIALIZER, METHOD, UNBOUND + } + + /** The declarations and statements within this declaration. */ + private final Block body; + + /** The parameters of this declaration. */ + private final List parameter; + + private DeclarationType declarationType; + + /** Index of the procedure in the vmt if it is a procedure in the class struct */ + private int vmtIndex; + + /** Constructor. + * + * @param position + * Position of this node + * @param identifier + * the identifier + * @param body + * the body of this procedure + * @param parameter + * the parameter of this procedure */ + public ProcedureDeclaration(Position position, Identifier identifier, Block body, + List parameter, DeclarationType declarationType) { + super(position, identifier); + this.body = body; + this.parameter = parameter; + this.declarationType = declarationType; + this.vmtIndex = -1; + } + + public ProcedureDeclaration(Position position, Identifier identifier, Block body, + List parameter) { + this(position, identifier, body, parameter, DeclarationType.UNBOUND); + } + + /** Get the body block. + * + * @return the body */ + public Block getBody() { + return body; + } + + /** Get the list of parameter. + * + * @return the paramter */ + public List getParameter() { + return parameter; + } + + /** set the declaration type */ + public void setDeclarationType(DeclarationType type) { + this.declarationType = type; + } + + /** get the declaration type + * + * @return the declaration type */ + public DeclarationType getDeclarationType() { + return declarationType; + } + + public boolean isInitializer() { + return declarationType == DeclarationType.INITIALIZER; + } + + public boolean isMethod() { + return declarationType == DeclarationType.METHOD; + } + + public boolean isUnbound() { + return declarationType == DeclarationType.UNBOUND; + } + + public ClassDeclaration getDefiningClass() { + if (isMethod() || isInitializer()) { + return (ClassDeclaration) getParentNode().getParentNode(); + } + return null; + } + + /** Get the vmtIndex. */ + public int getVMTIndex() { + return vmtIndex; + } + + /** Set the vmtIndex. */ + public void setVMTIndex(int vmtIndex) { + this.vmtIndex = vmtIndex; + } + + /** {@inheritDoc} */ + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + + /** {@inheritDoc} */ + @Override + public void visitChildren(BaseVisitor visitor) { + for (VariableDeclaration variableDeclaration : parameter) { + visitor.visitDoubleDispatched(variableDeclaration); + } + visitor.visitDoubleDispatched(body); + } + + /** Check equality of two types taking into account the AST object hierachy. + *

+ * + * @param other + * the other TypeDeclaration to check against + * @return if equal */ + @Override + public boolean matchesType(TypeDeclaration other) { + if (!super.matchesType(other)) { + return false; + } + if (!(other instanceof ProcedureDeclaration)) { + return false; + } + List otherParameter = ((ProcedureDeclaration) other).getParameter(); + if (parameter.size() != otherParameter.size()) { + return false; + } + for (int i = 0; i < parameter.size(); i++) { + if (!parameter.get(i).getType().matchesType(otherParameter.get(i).getType())) { + return false; + } + } + return true; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/declaration/TypeDeclaration.java b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/TypeDeclaration.java new file mode 100644 index 0000000..235583e --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/TypeDeclaration.java @@ -0,0 +1,67 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.declaration; + +import de.uni.bremen.monty.moco.ast.Identifier; +import de.uni.bremen.monty.moco.ast.Position; + +/** The baseclass of every declaration that describes a new type. + *

+ * The TypeDeclarations are used as types for Expressions. */ +public abstract class TypeDeclaration extends Declaration { + /** Constructor. + * + * @param position + * Position of this node + * @param identifier + * the identifier */ + public TypeDeclaration(Position position, Identifier identifier) { + super(position, identifier); + } + + /** Check equality of two types taking into account the AST object hierachy. + *

+ * + * @param other + * the other TypeDeclaration to check against + * @return if equal */ + public boolean matchesType(TypeDeclaration other) { + return getIdentifier().equals(other.getIdentifier()); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/declaration/VariableDeclaration.java b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/VariableDeclaration.java new file mode 100644 index 0000000..b5864a0 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/VariableDeclaration.java @@ -0,0 +1,151 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.declaration; + +import de.uni.bremen.monty.moco.ast.*; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +public class VariableDeclaration extends Declaration { + public enum DeclarationType { + VARIABLE, PARAMETER, ATTRIBUTE + } + + private ResolvableIdentifier typeIdentifier; + private TypeDeclaration type; + private DeclarationType declarationType; + private boolean isGlobal; + + /* Index of the variable if it is an attribute in the class struct */ + private int attributeIndex; + + public VariableDeclaration(Position position, Identifier identifier, ResolvableIdentifier typeIdentifier, + DeclarationType declarationType) { + this(position, identifier, typeIdentifier); + this.declarationType = declarationType; + } + + public VariableDeclaration(Position position, Identifier identifier, ResolvableIdentifier typeIdentifier) { + super(position, identifier); + this.typeIdentifier = typeIdentifier; + this.declarationType = DeclarationType.VARIABLE; + attributeIndex = -1; + } + + /** set the declaration type */ + public void setDeclarationType(DeclarationType type) { + this.declarationType = type; + } + + /** get the declaration type + * + * @return the declaration type */ + public DeclarationType getDeclarationType() { + return declarationType; + } + + public boolean isVariable() { + return declarationType == DeclarationType.VARIABLE; + } + + public boolean isParameter() { + return declarationType == DeclarationType.PARAMETER; + } + + public boolean isAttribute() { + return declarationType == DeclarationType.ATTRIBUTE; + } + + /** get the identifier of the type. + * + * @return the type identifier */ + public ResolvableIdentifier getTypeIdentifier() { + return typeIdentifier; + } + + /** get the type. + * + * @return the type */ + public TypeDeclaration getType() { + return type; + } + + /** set the type + * + * @param type */ + public void setType(TypeDeclaration type) { + this.type = type; + } + + /** get if this variable is global. + * + * @return if global */ + public boolean getIsGlobal() { + return isGlobal; + } + + /** set if this variable is global. + * + * @param isGlobal + * if global */ + public void setIsGlobal(boolean isGlobal) { + this.isGlobal = isGlobal; + } + + /** Get the attributeIndex. */ + public int getAttributeIndex() { + return attributeIndex; + } + + /** Set the attributeIndex. */ + public void setAttributeIndex(int attributeIndex) { + this.attributeIndex = attributeIndex; + } + + /** {@inheritDoc} */ + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + + /** {@inheritDoc} */ + @Override + public void visitChildren(BaseVisitor visitor) { + } + +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/expression/CastExpression.java b/src/main/java/de/uni/bremen/monty/moco/ast/expression/CastExpression.java new file mode 100644 index 0000000..0c6f85a --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/expression/CastExpression.java @@ -0,0 +1,73 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.expression; + +import de.uni.bremen.monty.moco.ast.*; +import de.uni.bremen.monty.moco.ast.declaration.*; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +public class CastExpression extends Expression { + + private Expression expression; + private ResolvableIdentifier castIdentifier; + + public CastExpression(Position position, Expression expression, ResolvableIdentifier castIdentifier) { + super(position); + this.expression = expression; + this.castIdentifier = castIdentifier; + } + + public ResolvableIdentifier getCastIdentifier() { + return castIdentifier; + } + + public Expression getExpression() { + return expression; + } + + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + + @Override + public void visitChildren(BaseVisitor visitor) { + visitor.visitDoubleDispatched(expression); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/expression/ConditionalExpression.java b/src/main/java/de/uni/bremen/monty/moco/ast/expression/ConditionalExpression.java new file mode 100644 index 0000000..420a729 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/expression/ConditionalExpression.java @@ -0,0 +1,92 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.expression; + +import de.uni.bremen.monty.moco.ast.*; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +public class ConditionalExpression extends Expression { + private final Expression condition; + private final Expression thenExpression; + private final Expression elseExpression; + + public ConditionalExpression(Position position, Expression condition, Expression thenExpression, + Expression elseExpression) { + super(position); + this.condition = condition; + this.thenExpression = thenExpression; + this.elseExpression = elseExpression; + } + + /** get the condition. + * + * @return the condition */ + public Expression getCondition() { + return condition; + } + + /** get the expression of the then part. + * + * @return the then expression */ + public Expression getThenExpression() { + return thenExpression; + } + + /** get the expression of the else part. + * + * @return the else expression */ + public Expression getElseExpression() { + return elseExpression; + } + + /** {@inheritDoc} */ + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + + /** {@inheritDoc} */ + @Override + public void visitChildren(BaseVisitor visitor) { + visitor.visitDoubleDispatched(condition); + visitor.visitDoubleDispatched(thenExpression); + visitor.visitDoubleDispatched(elseExpression); + } + +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/expression/Expression.java b/src/main/java/de/uni/bremen/monty/moco/ast/expression/Expression.java new file mode 100644 index 0000000..e5d8c92 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/expression/Expression.java @@ -0,0 +1,74 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.expression; + +import de.uni.bremen.monty.moco.ast.*; +import de.uni.bremen.monty.moco.ast.declaration.TypeDeclaration; + +/** The base class for every expression. + *

+ * An expression has a type which must be set by a visitor. */ +public abstract class Expression extends BasicASTNode { + + /** The type. */ + private TypeDeclaration type; + + /** Constructor. + * + * @param position + * Position of this node */ + public Expression(Position position) { + super(position); + } + + /** Set the type. + * + * @param type + * the new type */ + public void setType(TypeDeclaration type) { + this.type = type; + } + + /** Get the type. + * + * @return the type */ + public TypeDeclaration getType() { + return type; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/expression/FunctionCall.java b/src/main/java/de/uni/bremen/monty/moco/ast/expression/FunctionCall.java new file mode 100644 index 0000000..6f7ca2f --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/expression/FunctionCall.java @@ -0,0 +1,106 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.expression; + +import de.uni.bremen.monty.moco.ast.Position; +import de.uni.bremen.monty.moco.ast.ResolvableIdentifier; +import de.uni.bremen.monty.moco.ast.Identifier; +import de.uni.bremen.monty.moco.ast.declaration.ProcedureDeclaration; +import de.uni.bremen.monty.moco.ast.statement.Statement; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +import java.util.List; + +public class FunctionCall extends Expression implements Statement { + private final ResolvableIdentifier identifier; + private final List arguments; + private ProcedureDeclaration declaration; + + public FunctionCall(Position position, ResolvableIdentifier identifier, List arguments) { + super(position); + this.identifier = identifier; + this.arguments = arguments; + } + + /** get the identifier. + * + * @return the identifier */ + public ResolvableIdentifier getIdentifier() { + return identifier; + } + + /** get the List of paramter + * + * @return the paramters */ + public List getArguments() { + return arguments; + } + + /** {@inheritDoc} */ + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + + /** {@inheritDoc} */ + @Override + public void visitChildren(BaseVisitor visitor) { + for (Expression expression : arguments) { + visitor.visitDoubleDispatched(expression); + } + } + + /** @return the declaration */ + public ProcedureDeclaration getDeclaration() { + return declaration; + } + + /** @param declaration + * the declaration to set */ + public void setDeclaration(ProcedureDeclaration declaration) { + this.declaration = declaration; + } + + /** Get mangled identifier + * + * @return the mangled identifier */ + public Identifier getMangledIdentifier() { + return declaration.getMangledIdentifier(); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/expression/IsExpression.java b/src/main/java/de/uni/bremen/monty/moco/ast/expression/IsExpression.java new file mode 100644 index 0000000..024978d --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/expression/IsExpression.java @@ -0,0 +1,82 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.expression; + +import de.uni.bremen.monty.moco.ast.*; +import de.uni.bremen.monty.moco.ast.declaration.*; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +public class IsExpression extends Expression { + + private Expression expression; + private ResolvableIdentifier isIdentifier; + private TypeDeclaration toType; + + public IsExpression(Position position, Expression expression, ResolvableIdentifier isIdentifier) { + super(position); + this.expression = expression; + this.isIdentifier = isIdentifier; + } + + public ResolvableIdentifier getIsIdentifier() { + return isIdentifier; + } + + public Expression getExpression() { + return expression; + } + + public void setToType(TypeDeclaration toType) { + this.toType = toType; + } + + public TypeDeclaration getToType() { + return toType; + } + + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + + @Override + public void visitChildren(BaseVisitor visitor) { + visitor.visitDoubleDispatched(expression); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/expression/MemberAccess.java b/src/main/java/de/uni/bremen/monty/moco/ast/expression/MemberAccess.java new file mode 100644 index 0000000..b055f22 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/expression/MemberAccess.java @@ -0,0 +1,82 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.expression; + +import de.uni.bremen.monty.moco.ast.Position; +import de.uni.bremen.monty.moco.ast.statement.Statement; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +public class MemberAccess extends Expression implements Statement { + private final Expression left; + private final Expression right; + + public MemberAccess(Position position, Expression left, Expression right) { + super(position); + this.left = left; + this.right = right; + } + + /** get the left expression + * + * @return left */ + public Expression getLeft() { + return left; + } + + /** get the right expression + * + * @return right */ + public Expression getRight() { + return right; + } + + /** {@inheritDoc} */ + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + + /** {@inheritDoc} */ + @Override + public void visitChildren(BaseVisitor visitor) { + visitor.visitDoubleDispatched(left); + visitor.visitDoubleDispatched(right); + } + +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/expression/ParentExpression.java b/src/main/java/de/uni/bremen/monty/moco/ast/expression/ParentExpression.java new file mode 100644 index 0000000..4cb5c22 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/expression/ParentExpression.java @@ -0,0 +1,75 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.expression; + +import de.uni.bremen.monty.moco.ast.*; +import de.uni.bremen.monty.moco.ast.declaration.*; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +public class ParentExpression extends Expression { + + private ResolvableIdentifier parentIdentifier; + private ClassDeclaration selfType; + + public ParentExpression(Position position, ResolvableIdentifier parentIdentifier) { + super(position); + this.parentIdentifier = parentIdentifier; + } + + public ResolvableIdentifier getParentIdentifier() { + return parentIdentifier; + } + + public ClassDeclaration getSelfType() { + return selfType; + } + + public void setSelfType(ClassDeclaration selfType) { + this.selfType = selfType; + } + + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + + @Override + public void visitChildren(BaseVisitor visitor) { + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/expression/SelfExpression.java b/src/main/java/de/uni/bremen/monty/moco/ast/expression/SelfExpression.java new file mode 100644 index 0000000..95a1885 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/expression/SelfExpression.java @@ -0,0 +1,58 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.expression; + +import de.uni.bremen.monty.moco.ast.Position; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +public class SelfExpression extends Expression { + + public SelfExpression(Position position) { + super(position); + } + + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + + @Override + public void visitChildren(BaseVisitor visitor) { + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/expression/VariableAccess.java b/src/main/java/de/uni/bremen/monty/moco/ast/expression/VariableAccess.java new file mode 100644 index 0000000..8ea145d --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/expression/VariableAccess.java @@ -0,0 +1,107 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.expression; + +import de.uni.bremen.monty.moco.ast.*; +import de.uni.bremen.monty.moco.ast.declaration.Declaration; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +/** VariableAccess is an expression that references a local variable or a member of an object. */ +public class VariableAccess extends Expression { + + /** Identifier of the variable to access. */ + private final ResolvableIdentifier identifier; + private Declaration declaration; + + /** Is this a L-value? */ + private boolean lValue = false; + + public VariableAccess(Position position, ResolvableIdentifier identifier) { + super(position); + this.identifier = identifier; + } + + /** Get the identifier of the variable to access. + * + * @return the identifier */ + public ResolvableIdentifier getIdentifier() { + return identifier; + } + + /** {@inheritDoc} */ + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + + /** {@inheritDoc} */ + @Override + public void visitChildren(BaseVisitor visitor) { + } + + /** Mark this VariableAccess as a L-value. */ + public void setLValue() { + lValue = true; + } + + /** Is this a L-value? + * + * @return if L-value */ + public boolean getLValue() { + return lValue; + } + + /** @return the declaration */ + public Declaration getDeclaration() { + return declaration; + } + + /** @param declaration + * the declaration to set */ + public void setDeclaration(Declaration declaration) { + this.declaration = declaration; + } + + /** Get mangled identifier + * + * @return the mangled identifier */ + public Identifier getMangledIdentifier() { + return declaration.getMangledIdentifier(); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/ArrayLiteral.java b/src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/ArrayLiteral.java new file mode 100644 index 0000000..d41f185 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/ArrayLiteral.java @@ -0,0 +1,78 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ + +package de.uni.bremen.monty.moco.ast.expression.literal; + +import de.uni.bremen.monty.moco.ast.Position; +import de.uni.bremen.monty.moco.ast.expression.Expression; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +import java.util.ArrayList; +import java.util.List; + +public class ArrayLiteral extends Expression { + + private List entries; + + /** Constructor. + * + * @param position + * Position of this node + * @param entries */ + public ArrayLiteral(Position position, ArrayList entries) { + super(position); + this.entries = entries; + } + + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + + @Override + public void visitChildren(BaseVisitor visitor) { + for (Expression entry : entries) { + entry.visit(visitor); + } + } + + public List getEntries() { + return entries; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/BooleanLiteral.java b/src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/BooleanLiteral.java new file mode 100644 index 0000000..2121e34 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/BooleanLiteral.java @@ -0,0 +1,56 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.expression.literal; + +import de.uni.bremen.monty.moco.ast.CoreClasses; +import de.uni.bremen.monty.moco.ast.Position; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +public class BooleanLiteral extends LiteralExpression { + + public BooleanLiteral(Position position, Boolean value) { + super(position, value); + } + + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/CharacterLiteral.java b/src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/CharacterLiteral.java new file mode 100644 index 0000000..81f8a6e --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/CharacterLiteral.java @@ -0,0 +1,56 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ + +package de.uni.bremen.monty.moco.ast.expression.literal; + +import de.uni.bremen.monty.moco.ast.CoreClasses; +import de.uni.bremen.monty.moco.ast.Position; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +public class CharacterLiteral extends LiteralExpression { + public CharacterLiteral(Position position, Character value) { + super(position, value); + } + + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/FloatLiteral.java b/src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/FloatLiteral.java new file mode 100644 index 0000000..86cac4b --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/FloatLiteral.java @@ -0,0 +1,56 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.expression.literal; + +import de.uni.bremen.monty.moco.ast.CoreClasses; +import de.uni.bremen.monty.moco.ast.Position; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +public class FloatLiteral extends LiteralExpression { + + public FloatLiteral(Position position, Float value) { + super(position, value); + } + + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/IntegerLiteral.java b/src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/IntegerLiteral.java new file mode 100644 index 0000000..8880f74 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/IntegerLiteral.java @@ -0,0 +1,56 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.expression.literal; + +import de.uni.bremen.monty.moco.ast.CoreClasses; +import de.uni.bremen.monty.moco.ast.Position; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +public class IntegerLiteral extends LiteralExpression { + + public IntegerLiteral(Position position, Integer value) { + super(position, value); + } + + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/LiteralExpression.java b/src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/LiteralExpression.java new file mode 100644 index 0000000..3e99bf4 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/LiteralExpression.java @@ -0,0 +1,60 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.expression.literal; + +import de.uni.bremen.monty.moco.ast.Position; +import de.uni.bremen.monty.moco.ast.expression.Expression; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +public abstract class LiteralExpression extends Expression { + protected T value; + + public LiteralExpression(Position position, T value) { + super(position); + this.value = value; + } + + public T getValue() { + return value; + } + + @Override + public final void visitChildren(BaseVisitor visitor) { + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/StringLiteral.java b/src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/StringLiteral.java new file mode 100644 index 0000000..d15f4d6 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/StringLiteral.java @@ -0,0 +1,56 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.expression.literal; + +import de.uni.bremen.monty.moco.ast.CoreClasses; +import de.uni.bremen.monty.moco.ast.Position; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +public class StringLiteral extends LiteralExpression { + public StringLiteral(Position position, String value) { + super(position, value.replaceAll("\"", "")); + setType(CoreClasses.stringType()); + } + + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/statement/Assignment.java b/src/main/java/de/uni/bremen/monty/moco/ast/statement/Assignment.java new file mode 100644 index 0000000..bd6b4bb --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/statement/Assignment.java @@ -0,0 +1,94 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.statement; + +import de.uni.bremen.monty.moco.ast.*; +import de.uni.bremen.monty.moco.ast.expression.Expression; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +public class Assignment extends BasicASTNode implements Statement { + + /** The left side. */ + private final Expression left; + + /** The right side. */ + private final Expression right; + + /** Constructor. + * + * @param position + * Position of this node + * @param left + * the left side + * @param right + * the right side */ + public Assignment(Position position, Expression left, Expression right) { + super(position); + this.left = left; + this.right = right; + } + + /** Get the left side. + * + * @return the left side */ + public Expression getLeft() { + return left; + } + + /** Get the right side. + * + * @return the right side */ + public Expression getRight() { + return right; + } + + /** {@inheritDoc} */ + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + + /** {@inheritDoc} */ + @Override + public void visitChildren(BaseVisitor visitor) { + visitor.visitDoubleDispatched(left); + visitor.visitDoubleDispatched(right); + } + +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/statement/BreakStatement.java b/src/main/java/de/uni/bremen/monty/moco/ast/statement/BreakStatement.java new file mode 100644 index 0000000..a0ece7b --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/statement/BreakStatement.java @@ -0,0 +1,75 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.statement; + +import de.uni.bremen.monty.moco.ast.*; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +public class BreakStatement extends BasicASTNode implements Statement { + + /** The loop to skip.* */ + private WhileLoop loop; + + /** Constructor. + * + * @param position + * Position of this node */ + public BreakStatement(Position position) { + super(position); + } + + public void setLoop(WhileLoop loop) { + this.loop = loop; + } + + public WhileLoop getLoop() { + return loop; + } + + /** {@inheritDoc} */ + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + + /** {@inheritDoc} */ + @Override + public void visitChildren(BaseVisitor visitor) { + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/statement/ConditionalStatement.java b/src/main/java/de/uni/bremen/monty/moco/ast/statement/ConditionalStatement.java new file mode 100644 index 0000000..b8b34bd --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/statement/ConditionalStatement.java @@ -0,0 +1,103 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.statement; + +import de.uni.bremen.monty.moco.ast.*; +import de.uni.bremen.monty.moco.ast.expression.Expression; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +public class ConditionalStatement extends BasicASTNode implements Statement { + + private final Expression condition; + private final Block thenBlock; + private final Block elseBlock; + + /** Constructor. + * + * @param position + * Position of this node + * @param condition + * the condition + * @param thenBlock + * block if condition is true + * @param elseBlock + * block if condition is false */ + public ConditionalStatement(Position position, Expression condition, Block thenBlock, Block elseBlock) { + super(position); + this.condition = condition; + this.thenBlock = thenBlock; + this.elseBlock = elseBlock; + } + + /** get the condition + * + * @return the condition */ + public Expression getCondition() { + return condition; + } + + /** get the then block + * + * @return the then block */ + public Block getThenBlock() { + return thenBlock; + } + + /** get the else block + * + * @return the else block */ + public Block getElseBlock() { + return elseBlock; + } + + /** {@inheritDoc} */ + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + + /** {@inheritDoc} */ + @Override + public void visitChildren(BaseVisitor visitor) { + visitor.visitDoubleDispatched(condition); + visitor.visitDoubleDispatched(thenBlock); + visitor.visitDoubleDispatched(elseBlock); + } + +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/statement/ContinueStatement.java b/src/main/java/de/uni/bremen/monty/moco/ast/statement/ContinueStatement.java new file mode 100644 index 0000000..71a5f2e --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/statement/ContinueStatement.java @@ -0,0 +1,66 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.statement; + +import de.uni.bremen.monty.moco.ast.*; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +public class ContinueStatement extends BasicASTNode implements Statement { + + /** Constructor + * + * @param position + * Position of this node */ + public ContinueStatement(Position position) { + super(position); + } + + /** {@inheritDoc} */ + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + + /** {@inheritDoc} */ + @Override + public void visitChildren(BaseVisitor visitor) { + + } + +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/statement/RaiseStatement.java b/src/main/java/de/uni/bremen/monty/moco/ast/statement/RaiseStatement.java new file mode 100644 index 0000000..be776c3 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/statement/RaiseStatement.java @@ -0,0 +1,63 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.statement; + +import de.uni.bremen.monty.moco.ast.BasicASTNode; +import de.uni.bremen.monty.moco.ast.Position; +import de.uni.bremen.monty.moco.ast.expression.Expression; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +public class RaiseStatement extends BasicASTNode implements Statement { + + private Expression expression; + + public RaiseStatement(Position position, Expression expression) { + super(position); + this.expression = expression; + } + + @Override + public void visit(BaseVisitor visitor) { + } + + @Override + public void visitChildren(BaseVisitor visitor) { + } + +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/statement/ReturnStatement.java b/src/main/java/de/uni/bremen/monty/moco/ast/statement/ReturnStatement.java new file mode 100644 index 0000000..8ae4025 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/statement/ReturnStatement.java @@ -0,0 +1,80 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.statement; + +import de.uni.bremen.monty.moco.ast.*; +import de.uni.bremen.monty.moco.ast.expression.Expression; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +public class ReturnStatement extends BasicASTNode implements Statement { + private Expression parameter; + + /** Constructor. + * + * @param position + * Position of this node + * @param parameter + * the expression to return */ + public ReturnStatement(Position position, Expression parameter) { + super(position); + this.parameter = parameter; + } + + /** get the paramter + * + * @return the paramter */ + public Expression getParameter() { + return parameter; + } + + /** {@inheritDoc} */ + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + + /** {@inheritDoc} */ + @Override + public void visitChildren(BaseVisitor visitor) { + if (parameter != null) { + visitor.visitDoubleDispatched(parameter); + } + } + +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/statement/SkipStatement.java b/src/main/java/de/uni/bremen/monty/moco/ast/statement/SkipStatement.java new file mode 100644 index 0000000..159852e --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/statement/SkipStatement.java @@ -0,0 +1,71 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.statement; + +import de.uni.bremen.monty.moco.ast.BasicASTNode; +import de.uni.bremen.monty.moco.ast.Position; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +public class SkipStatement extends BasicASTNode implements Statement { + + /** The loop to skip.* */ + private WhileLoop loop; + + public SkipStatement(Position position) { + super(position); + } + + public void setLoop(WhileLoop loop) { + this.loop = loop; + } + + public WhileLoop getLoop() { + return loop; + } + + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + + } + + @Override + public void visitChildren(BaseVisitor visitor) { + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/statement/Statement.java b/src/main/java/de/uni/bremen/monty/moco/ast/statement/Statement.java new file mode 100644 index 0000000..fe6b4f3 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/statement/Statement.java @@ -0,0 +1,46 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.statement; + +import de.uni.bremen.monty.moco.ast.*; + +/** The baseclass for every statement. */ +public interface Statement extends ASTNode { + +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/statement/TryStatement.java b/src/main/java/de/uni/bremen/monty/moco/ast/statement/TryStatement.java new file mode 100644 index 0000000..e13dd39 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/statement/TryStatement.java @@ -0,0 +1,80 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.statement; + +import de.uni.bremen.monty.moco.ast.*; +import de.uni.bremen.monty.moco.ast.declaration.VariableDeclaration; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +public class TryStatement extends BasicASTNode implements Statement { + + VariableDeclaration handle; + Block tryBlock; + Block handleBlock; + + public TryStatement(Position position, VariableDeclaration handle, Block tryBlock, Block handleBlock) { + super(position); + this.handle = handle; + this.tryBlock = tryBlock; + this.handleBlock = handleBlock; + } + + public Block getTryBlock() { + + return tryBlock; + } + + public Block getHandleBlock() { + + return handleBlock; + } + + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + + @Override + public void visitChildren(BaseVisitor visitor) { + visitor.visitDoubleDispatched(tryBlock); + visitor.visitDoubleDispatched(handleBlock); + + } + +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/statement/WhileLoop.java b/src/main/java/de/uni/bremen/monty/moco/ast/statement/WhileLoop.java new file mode 100644 index 0000000..a0aaed9 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/statement/WhileLoop.java @@ -0,0 +1,91 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.statement; + +import de.uni.bremen.monty.moco.ast.*; +import de.uni.bremen.monty.moco.ast.expression.Expression; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +public class WhileLoop extends BasicASTNode implements Statement { + + private final Expression condition; + private final Block body; + + /** Constructor. + * + * @param position + * Position of this node + * @param condition + * the condition + * @param body + * loop-body */ + public WhileLoop(Position position, Expression condition, Block body) { + super(position); + this.condition = condition; + this.body = body; + } + + /** get the condition + * + * @return the condition */ + public Expression getCondition() { + return condition; + } + + /** get the body + * + * @return the body */ + public Block getBody() { + return body; + } + + /** {@inheritDoc} */ + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + + /** {@inheritDoc} */ + @Override + public void visitChildren(BaseVisitor visitor) { + visitor.visitDoubleDispatched(condition); + visitor.visitDoubleDispatched(body); + } + +} diff --git a/src/main/java/de/uni/bremen/monty/moco/codegeneration/CodeGenerator.java b/src/main/java/de/uni/bremen/monty/moco/codegeneration/CodeGenerator.java new file mode 100644 index 0000000..c120b66 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/codegeneration/CodeGenerator.java @@ -0,0 +1,584 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.codegeneration; + +import de.uni.bremen.monty.moco.ast.ASTNode; +import de.uni.bremen.monty.moco.ast.CoreClasses; +import de.uni.bremen.monty.moco.ast.declaration.*; +import de.uni.bremen.monty.moco.codegeneration.context.CodeContext; +import de.uni.bremen.monty.moco.codegeneration.context.CodeContext.LLVMFunctionAttribute; +import de.uni.bremen.monty.moco.codegeneration.context.CodeContext.Linkage; +import de.uni.bremen.monty.moco.codegeneration.context.Operations; +import de.uni.bremen.monty.moco.codegeneration.identifier.FunctionSignature; +import de.uni.bremen.monty.moco.codegeneration.identifier.LLVMIdentifier; +import de.uni.bremen.monty.moco.codegeneration.identifier.LLVMIdentifierFactory; +import de.uni.bremen.monty.moco.codegeneration.types.*; +import de.uni.bremen.monty.moco.codegeneration.voodoo.BlackMagic; + +import java.util.*; + +import static de.uni.bremen.monty.moco.codegeneration.types.LLVMTypeFactory.*; + +/** This class should contain most of the logic for the CodeGeneration. Mainly methods are called from the + * CodeGenerationVisitor and have a Parameter 'CodeContext c'. On this argument LLVM instructions can be executed. + * + * It is an mapping layer between the CodeGenerationVisitor on one side and CodeContext on the other. The + * CodeGenerationVisitor is mainly influenced by the Monty-AST and the CodeContext only know LLVM instructions. So the + * CodeGenerator is the where most parts of the mapping between those two languages exists. + * + * An simple task of mapping is e.g. map from monty-Types (TypeDeclaration) to LLVM-Types(LLVMType) */ +public class CodeGenerator { + private final Operations operations; + private final BlackMagic blackMagic; + private final TypeConverter typeConverter; + + /* + * Map an ASTNode to a label prefix. + */ + protected HashMap node2label = new HashMap<>(); + + /* + * Map each label to its number of occurrences. We use this information to create unique labels in the resulting + * LLVM code. + */ + protected HashMap label2occurrences = new HashMap<>(); + + private LLVMIdentifierFactory llvmIdentifierFactory; + + public CodeGenerator(TypeConverter typeConverter, LLVMIdentifierFactory llvmIdentifierFactory) { + this.typeConverter = typeConverter; + this.llvmIdentifierFactory = llvmIdentifierFactory; + operations = new Operations(this, llvmIdentifierFactory); + blackMagic = new BlackMagic(operations); + initFormatStrings(); + } + + public void initFormatStrings() { + LLVMArrayType stringType = array(int8(), 3); + LLVMIdentifier> stringFormatIdent = + llvmIdentifierFactory.newGlobal(".stringFormat", stringType); + operations.setStringFormat(llvmIdentifierFactory.elementPointerTo(stringFormatIdent)); + LLVMIdentifier> intFormatIdent = + llvmIdentifierFactory.newGlobal(".intFormat", stringType); + operations.setIntFormat(llvmIdentifierFactory.elementPointerTo(intFormatIdent)); + LLVMIdentifier> floatFormatIdent = + llvmIdentifierFactory.newGlobal(".floatFormat", stringType); + operations.setFloatFormat(llvmIdentifierFactory.elementPointerTo(floatFormatIdent)); + LLVMIdentifier> charFormatIdent = + llvmIdentifierFactory.newGlobal(".charFormat", stringType); + operations.setCharFormat(llvmIdentifierFactory.elementPointerTo(charFormatIdent)); + } + + private LLVMIdentifier> castIfNeeded(CodeContext c, + LLVMIdentifier> variable, LLVMPointer toType) { + if (!variable.getType().equals(toType)) { + LLVMIdentifier> castedVariable = + llvmIdentifierFactory.newLocal(toType, variable.needToBeResolved()); + c.bitcast(castedVariable, variable); + return castedVariable; + } + return variable; + } + + private LLVMIdentifier castIfNeeded(CodeContext c, LLVMIdentifier variable, T toType) { + if ((variable.getType() instanceof LLVMPointer) && (toType instanceof LLVMPointer)) { + return (LLVMIdentifier) (LLVMIdentifier) castIfNeeded( + c, + (LLVMIdentifier>) (LLVMIdentifier) variable, + (LLVMPointer) toType); + } + return variable; + } + + private LLVMIdentifier resolveIfNeeded(CodeContext c, LLVMIdentifier addr) { + if (addr.needToBeResolved()) { + LLVMIdentifier> sourcePointer = llvmIdentifierFactory.pointerTo(addr); + LLVMIdentifier targetPointer = llvmIdentifierFactory.newLocal(addr.getType(), false); + return c.load(sourcePointer, targetPointer); + } else { + return addr; + } + } + + private List> resolveArgumentsIfNeeded(CodeContext c, + List> arguments, List parameters) { + List> resolvedArguments = new ArrayList<>(arguments.size()); + for (int i = 0; i < arguments.size(); i++) { + LLVMIdentifier resolvedArgument = resolveIfNeeded(c, (LLVMIdentifier) arguments.get(i)); + LLVMType expectedType = mapToLLVMType(parameters.get(i)); + resolvedArguments.add(castIfNeeded(c, resolvedArgument, expectedType)); + } + return resolvedArguments; + } + + private List> unboxArgumentsIfNeeded(CodeContext c, + List> arguments) { + List> unboxedArguments = new ArrayList<>(arguments.size()); + for (LLVMIdentifier llvmIdentifier : arguments) { + if (llvmIdentifier.getType().equals(mapToLLVMType(CoreClasses.intType()))) { + unboxedArguments.add(unboxType(c, (LLVMIdentifier) llvmIdentifier, int64())); + } else if (llvmIdentifier.getType().equals(mapToLLVMType(CoreClasses.boolType()))) { + unboxedArguments.add(unboxType(c, (LLVMIdentifier) llvmIdentifier, int1())); + } else if (llvmIdentifier.getType().equals(mapToLLVMType(CoreClasses.floatType()))) { + unboxedArguments.add(unboxType(c, (LLVMIdentifier) llvmIdentifier, double64())); + } else if (llvmIdentifier.getType().equals(mapToLLVMType(CoreClasses.charType()))) { + unboxedArguments.add(unboxType(c, (LLVMIdentifier) llvmIdentifier, int8())); + } else { + unboxedArguments.add(llvmIdentifier); + } + } + return unboxedArguments; + } + + private LLVMIdentifier> addStringToDataField(CodeContext c, String value) { + int length = value.length() + 1; + + LLVMArrayType type = array(int8(), length); + LLVMIdentifier> identifier = llvmIdentifierFactory.newGlobal(type); + String internValue = "c\"" + value + "\\00\";"; + c.global(Linkage.priv, (LLVMIdentifier) (LLVMIdentifier) identifier, true, internValue); + return identifier; + } + + private LLVMIdentifier> getVMTPointer(CodeContext c, + LLVMIdentifier> selfReference, ClassDeclaration classDeclaration) { + LLVMPointer vmtType = + pointer((LLVMType) struct(classDeclaration.getMangledIdentifier().getSymbol() + "_vmt_type")); + LLVMIdentifier> vmtPointer = llvmIdentifierFactory.newLocal(vmtType, true); + c.getelementptr( + (LLVMIdentifier) (LLVMIdentifier) vmtPointer, + selfReference, + llvmIdentifierFactory.constant(int32(), 0), + llvmIdentifierFactory.constant(int32(), 0)); + return vmtPointer; + } + + private LLVMIdentifier> getFunctionPointer(CodeContext c, + LLVMIdentifier> selfReference, ProcedureDeclaration declaration) { + LLVMIdentifier> vmtPointer = + getVMTPointer(c, selfReference, (ClassDeclaration) declaration.getParentNode().getParentNode()); + + LLVMPointer functionType = mapToLLVMType(declaration); + LLVMIdentifier> functionPointer = llvmIdentifierFactory.newLocal(functionType); + c.getelementptr( + functionPointer, + resolveIfNeeded(c, vmtPointer), + llvmIdentifierFactory.constant(int32(), 0), + llvmIdentifierFactory.constant(int32(), declaration.getVMTIndex())); + return functionPointer; + } + + public void buildConstructor(CodeContext c, ClassDeclaration classDeclaration) { + List> llvmParameter = new ArrayList<>(); + String constructorName = classDeclaration.getMangledIdentifier().getSymbol() + "_constructor"; + addFunction(c, classDeclaration, llvmParameter, constructorName); + + LLVMPointer selfType = mapToLLVMType(classDeclaration); + LLVMIdentifier> selfReference = llvmIdentifierFactory.newLocal(selfType, false); + malloc(c, selfReference); + + LLVMIdentifier vmtPointer = + (LLVMIdentifier) (LLVMIdentifier) getVMTPointer(c, selfReference, classDeclaration); + LLVMIdentifier vmtData = + llvmIdentifierFactory.newGlobal( + classDeclaration.getMangledIdentifier().getSymbol() + "_vmt_data", + vmtPointer.getType()); + c.store(vmtData, llvmIdentifierFactory.pointerTo(vmtPointer)); + + returnValue(c, (LLVMIdentifier) selfReference, classDeclaration); + } + + public LLVMIdentifier callConstructor(CodeContext c, ClassDeclaration classDeclaration) { + LLVMIdentifier result = llvmIdentifierFactory.newLocal(mapToLLVMType(classDeclaration), false); + LLVMIdentifier signature = + llvmIdentifierFactory.newGlobal( + classDeclaration.getMangledIdentifier().getSymbol() + "_constructor", + result.getType()); + c.call(signature, result); + return result; + } + + /** Create a unique label prefix and store it under an association with the given node. */ + public String createLabelPrefix(String name, ASTNode node) { + if (!label2occurrences.containsKey(name)) { + label2occurrences.put(name, 0); + } + int id = label2occurrences.get(name); + String label = name + id; + label2occurrences.put(name, id + 1); + node2label.put(node, label); + return label; + } + + /** Get the unique label prefix associated with the given node. + * + * This is a Map lookup so the error will be thrown if node does not exist as key */ + public String getLabelPrefix(ASTNode node) { + return node2label.get(node); + } + + public LLVMIdentifier declareGlobalVariable(CodeContext c, String name, TypeDeclaration type) { + LLVMType llvmType = mapToLLVMType(type); + LLVMIdentifier variable = llvmIdentifierFactory.newGlobal(name, llvmType); + c.global(Linkage.priv, variable, false); + return variable; + } + + public LLVMIdentifier declareLocalVariable(CodeContext c, String name, TypeDeclaration type) { + LLVMType llvmType = mapToLLVMType(type); + + LLVMIdentifier variable = llvmIdentifierFactory.newLocal(name, llvmType, true); + c.alloca(variable, llvmType); + return variable; + } + + public LLVMIdentifier resolveLocalVarName(String name, TypeDeclaration type, + boolean resolvable) { + T llvmType = mapToLLVMType(type); + return llvmIdentifierFactory.newLocal(name, llvmType, resolvable); + } + + public LLVMIdentifier resolveGlobalVarName(String name, TypeDeclaration type) { + T llvmType = mapToLLVMType(type); + return llvmIdentifierFactory.newGlobal(name, llvmType); + } + + public void addMain(CodeContext active) { + + FunctionSignature mainFunction = + llvmIdentifierFactory.newFunction( + int32(), + "main", + Collections.> emptyList()); + + active.define(Arrays.asList(LLVMFunctionAttribute.ssp), mainFunction); + active.label("entry"); + } + + public void addFunction(CodeContext c, TypeDeclaration returnType, + List> llvmParameter, String name) { + LLVMType llvmReturnType = mapToLLVMType(returnType); + c.define( + new ArrayList(), + llvmIdentifierFactory.newFunction(llvmReturnType, name, llvmParameter)); + c.label("entry"); + } + + public void addNativeFunction(CodeContext c, TypeDeclaration returnType, + List> llvmParameter, String name) { + addFunction(c, returnType, llvmParameter, name); + + List> unboxedParameter = unboxArgumentsIfNeeded(c, llvmParameter); + + LLVMIdentifier result = + (LLVMIdentifier) blackMagic.generateNativeFunction(c, name, unboxedParameter); + if (result != null) { + if (result.getType() instanceof LLVMPointer) { + returnValue(c, result, returnType); + } else { + returnValue(c, boxType(c, result, returnType), returnType); + } + } else { + returnValue( + c, + (LLVMIdentifier) (LLVMIdentifier) llvmIdentifierFactory.voidId(), + CoreClasses.voidType()); + } + } + + public void returnMain(CodeContext c) { + c.ret(llvmIdentifierFactory.constant(int32(), 0)); + } + + public void returnValue(CodeContext c, LLVMIdentifier returnValue, TypeDeclaration expectedType) { + LLVMIdentifier resolved = resolveIfNeeded(c, returnValue); + LLVMIdentifier casted = castIfNeeded(c, resolved, mapToLLVMType(expectedType)); + c.ret(casted); + } + + public LLVMIdentifier> addConstantString(CodeContext constant, String value) { + LLVMIdentifier> nameOfDataField = addStringToDataField(constant, value); + LLVMIdentifier> stringAsCharPointer = + llvmIdentifierFactory.elementPointerTo(nameOfDataField); + return stringAsCharPointer; + } + + public void exit(CodeContext c, int statusCode) { + LLVMIdentifier signature = llvmIdentifierFactory.newGlobal("exit", (LLVMType) voidType()); + c.callVoid(signature, llvmIdentifierFactory.constant(int32(), statusCode)); + } + + /** Allocates heap memory for the given type and return a typed pointer. */ + public LLVMIdentifier> malloc(CodeContext c, + LLVMIdentifier> result) { + return malloc(c, result, (LLVMPointer) result.getType()); + } + + /** Allocates heap memory for the given type and return a typed pointer. */ + public LLVMIdentifier> malloc(CodeContext c, + LLVMIdentifier> result, LLVMPointer inputType) { + + LLVMIdentifier> sizePtr = llvmIdentifierFactory.newLocal(inputType); + c.getelementptr( + sizePtr, + llvmIdentifierFactory.constantNull(inputType), + llvmIdentifierFactory.constant(int32(), 1)); + LLVMIdentifier sizeInt = llvmIdentifierFactory.newLocal((LLVMType) int32()); + c.ptrtoint(sizeInt, (LLVMIdentifier) sizePtr); + + LLVMIdentifier> s = llvmIdentifierFactory.newGlobal("malloc", pointer(int8())); + LLVMIdentifier> mallocPtr = llvmIdentifierFactory.newLocal(s.getType()); + c.call((LLVMIdentifier) (LLVMIdentifier) s, mallocPtr, sizeInt); + c.bitcast((LLVMIdentifier) result, (LLVMIdentifier) mallocPtr); + return result; + } + + public void assign(CodeContext c, LLVMIdentifier target, LLVMIdentifier source) { + source = resolveIfNeeded(c, source); + source = castIfNeeded(c, source, target.getType()); + LLVMIdentifier> targetPointer = llvmIdentifierFactory.pointerTo(target); + c.store(source, targetPointer); + } + + public LLVMIdentifier accessMember(CodeContext c, LLVMIdentifier> pointer, + int attributeOffset, TypeDeclaration type, boolean load) { + + LLVMIdentifier result = llvmIdentifierFactory.newLocal(mapToLLVMType(type), load); + c.getelementptr( + result, + resolveIfNeeded(c, pointer), + llvmIdentifierFactory.constant(int32(), 0), + llvmIdentifierFactory.constant(int32(), attributeOffset)); + return result; + } + + public T mapToLLVMType(TypeDeclaration type) { + return typeConverter.mapToLLVMType(type); + } + + public LLVMIdentifier> castClass(CodeContext c, + LLVMIdentifier> pointer, ClassDeclaration sourceType, ClassDeclaration resultType, + String labelPrefix) { + + String successLabel = labelPrefix + ".success"; + String failureLabel = labelPrefix + ".failure"; + + pointer = resolveIfNeeded(c, pointer); + LLVMIdentifier isaCmpResult = isClass(c, pointer, sourceType, resultType); + + c.branch(isaCmpResult, successLabel, failureLabel); + c.label(failureLabel); + exit(c, 1); + c.branch(successLabel); + c.label(successLabel); + return castIfNeeded(c, pointer, (LLVMPointer) mapToLLVMType(resultType)); + } + + public LLVMIdentifier isClass(CodeContext c, LLVMIdentifier> pointer, + ClassDeclaration sourceType, ClassDeclaration resultType) { + + pointer = resolveIfNeeded(c, pointer); + LLVMIdentifier> vmt = getVMTPointer(c, pointer, sourceType); + vmt = resolveIfNeeded(c, vmt); + + LLVMType ctType = array(pointer(int8()), sourceType.getSuperClassDeclarationsRecursive().size() + 1); + LLVMIdentifier> ct = llvmIdentifierFactory.newLocal(pointer(ctType), true); + c.getelementptr(ct, vmt, llvmIdentifierFactory.constant(int32(), 0), llvmIdentifierFactory.constant(int32(), 0)); + ct = resolveIfNeeded(c, ct); + + LLVMType pointerArrayType = array(pointer(int8()), 0); + LLVMIdentifier> pointerArray = llvmIdentifierFactory.newLocal(pointer(pointerArrayType)); + c.bitcast(pointerArray, ct); + + LLVMType resultVMTType = struct(resultType.getMangledIdentifier().getSymbol() + "_vmt_type"); + LLVMIdentifier> resultVMT = + llvmIdentifierFactory.newGlobal( + resultType.getMangledIdentifier().getSymbol() + "_vmt_data", + pointer(resultVMTType)); + LLVMIdentifier> resultPointer = + llvmIdentifierFactory.newLocal(pointer((LLVMType) int8())); + c.bitcast(resultPointer, resultVMT); + + LLVMIdentifier isaCmpResult = llvmIdentifierFactory.newLocal(int1(), false); + LLVMIdentifier isaSignature = llvmIdentifierFactory.newGlobal("vmt_isa_class", int1()); + c.call((LLVMIdentifier) (LLVMIdentifier) isaSignature, isaCmpResult, pointerArray, resultPointer); + return isaCmpResult; + } + + public void checkArrayBounds(CodeContext c, LLVMIdentifier> array, + LLVMIdentifier index) { + + List arrayTypeList = Arrays.asList(int64(), array(pointer(int8()), 0)); + array = castIfNeeded(c, array, pointer(struct(arrayTypeList))); + LLVMIdentifier boundsCheckSignature = + llvmIdentifierFactory.newGlobal("array_bounds_check", voidType()); + c.callVoid((LLVMIdentifier) (LLVMIdentifier) boundsCheckSignature, array, index); + } + + public LLVMIdentifier call(CodeContext c, String functionName, TypeDeclaration returnType, + List> arguments, List parameters) { + LLVMType llvmReturnType = mapToLLVMType(returnType); + LLVMIdentifier functionSignature = llvmIdentifierFactory.newGlobal(functionName, llvmReturnType); + List> resolvedArguments = resolveArgumentsIfNeeded(c, arguments, parameters); + return c.call( + functionSignature, + llvmIdentifierFactory.newLocal(functionSignature.getType(), false), + resolvedArguments); + } + + public void callVoid(CodeContext c, String functionName, List> arguments, + List parameters) { + List> resolvedArguments = resolveArgumentsIfNeeded(c, arguments, parameters); + c.callVoid(llvmIdentifierFactory.newGlobal(functionName, (LLVMType) voidType()), resolvedArguments); + } + + public LLVMIdentifier callMethod(CodeContext c, FunctionDeclaration declaration, + List> arguments, List parameters) { + List> resolvedArguments = resolveArgumentsIfNeeded(c, arguments, parameters); + + LLVMIdentifier> functionPointer = + getFunctionPointer(c, (LLVMIdentifier>) resolvedArguments.get(0), declaration); + return c.call( + (LLVMIdentifier) (LLVMIdentifier) resolveIfNeeded(c, functionPointer), + llvmIdentifierFactory.newLocal(mapToLLVMType(declaration.getReturnType()), false), + resolvedArguments); + } + + public void callVoidMethod(CodeContext c, ProcedureDeclaration declaration, List> arguments, + List parameters) { + List> resolvedArguments = resolveArgumentsIfNeeded(c, arguments, parameters); + + LLVMIdentifier> functionPointer = + getFunctionPointer(c, (LLVMIdentifier>) resolvedArguments.get(0), declaration); + c.callVoid( + (LLVMIdentifier) (LLVMIdentifier) resolveIfNeeded(c, functionPointer), + resolvedArguments); + } + + public void branch(CodeContext c, LLVMIdentifier expression, String trueLabel, String falseLabel) { + LLVMIdentifier boxedValue = resolveIfNeeded(c, expression); + LLVMIdentifier value = unboxType(c, boxedValue, int1()); + c.branch(value, trueLabel, falseLabel); + } + + public LLVMIdentifier loadInt(Integer value) { + return llvmIdentifierFactory.constant(int64(), value); + } + + public LLVMIdentifier loadFloat(Float value) { + return llvmIdentifierFactory.constant(double64(), value); + } + + public LLVMIdentifier loadBool(Boolean value) { + return llvmIdentifierFactory.constant(int1(), value); + } + + public LLVMIdentifier loadChar(Character value) { + return llvmIdentifierFactory.constant(int8(), value); + } + + public LLVMIdentifier> addArray(CodeContext c, int size, ClassDeclaration type) { + + LLVMPointer array = mapToLLVMType(type); + LLVMIdentifier> var = llvmIdentifierFactory.newLocal(array, false); + + // Temporary until object or generic + LLVMType arrayType = mapToLLVMType((TypeDeclaration) CoreClasses.intType()); + List mallocList = Arrays.asList(int64(), array(arrayType, size)); + malloc(c, var, pointer((LLVMType) struct(mallocList))); + + LLVMIdentifier arraySize = + (LLVMIdentifier) (LLVMIdentifier) llvmIdentifierFactory.constant(int64(), size); + LLVMIdentifier> sizeField = llvmIdentifierFactory.newLocal(pointer(arraySize.getType())); + c.getelementptr( + sizeField, + var, + llvmIdentifierFactory.constant(int32(), 0), + llvmIdentifierFactory.constant(int32(), 0)); + c.store(arraySize, sizeField); + + return var; + } + + public void setArrayElement(CodeContext c, LLVMIdentifier> array, int index, + LLVMIdentifier value) { + + // Temporary until object or generic + LLVMType internalType = mapToLLVMType((TypeDeclaration) CoreClasses.intType()); + LLVMIdentifier> element = llvmIdentifierFactory.newLocal(pointer(internalType)); + + c.getelementptr( + element, + array, + llvmIdentifierFactory.constant(int32(), 0), + llvmIdentifierFactory.constant(int32(), 1), + llvmIdentifierFactory.constant(int32(), index)); + c.store(value, element); + } + + public LLVMIdentifier boxType(CodeContext c, LLVMIdentifier toBox, TypeDeclaration type) { + + LLVMIdentifier boxedValue = callConstructor(c, (ClassDeclaration) type); + LLVMIdentifier boxedValueField = llvmIdentifierFactory.newLocal(toBox.getType()); + c.getelementptr( + boxedValueField, + boxedValue, + llvmIdentifierFactory.constant(int32(), 0), + llvmIdentifierFactory.constant(int32(), 1)); + LLVMIdentifier> targetPointer = llvmIdentifierFactory.pointerTo(boxedValueField); + c.store(toBox, targetPointer); + return boxedValue; + } + + public LLVMIdentifier unboxType(CodeContext c, LLVMIdentifier toUnbox, T llvmtype) { + toUnbox = resolveIfNeeded(c, toUnbox); + LLVMIdentifier unboxedValue = llvmIdentifierFactory.newLocal(llvmtype); + + c.getelementptr( + unboxedValue, + toUnbox, + llvmIdentifierFactory.constant(int32(), 0), + llvmIdentifierFactory.constant(int32(), 1)); + LLVMIdentifier> sourcePointer = llvmIdentifierFactory.pointerTo(unboxedValue); + LLVMIdentifier targetPointer = llvmIdentifierFactory.newLocal(unboxedValue.getType(), false); + + c.load(sourcePointer, targetPointer); + return targetPointer; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/codegeneration/CodeWriter.java b/src/main/java/de/uni/bremen/monty/moco/codegeneration/CodeWriter.java new file mode 100644 index 0000000..34c98cd --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/codegeneration/CodeWriter.java @@ -0,0 +1,84 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.codegeneration; + +import de.uni.bremen.monty.moco.util.Params; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.io.IOUtils; + +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class CodeWriter { + + private OutputStream llOutputStream; + + public CodeWriter(Params params) throws IOException { + llOutputStream = initLlvmOutput(params); + IOUtils.copy(getClass().getResourceAsStream("/std_llvm_include.ll"), llOutputStream); + } + + private OutputStream initLlvmOutput(Params params) throws FileNotFoundException { + OutputStream llOutputStream; + if (params.isGenerateOnlyLLVM()) { + if (params.getOutputFile() == null) { + llOutputStream = System.out; + } else { + llOutputStream = new FileOutputStream(params.getOutputFile()); + } + } else { + String llFile; + if (params.getInputFile() != null) { + llFile = FilenameUtils.removeExtension(params.getInputFile()) + ".ll"; + } else { + llFile = params.getInputFolder() + "/Main.ll"; + } + llOutputStream = new FileOutputStream(llFile); + params.setLlFile(llFile); + } + return llOutputStream; + } + + public void write(String data) throws IOException { + llOutputStream.write(data.getBytes()); + llOutputStream.flush(); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/codegeneration/Native.java b/src/main/java/de/uni/bremen/monty/moco/codegeneration/Native.java new file mode 100644 index 0000000..2afc5ca --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/codegeneration/Native.java @@ -0,0 +1,51 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ + +package de.uni.bremen.monty.moco.codegeneration; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface Native { + String value(); +} diff --git a/src/main/java/de/uni/bremen/monty/moco/codegeneration/context/CodeContext.java b/src/main/java/de/uni/bremen/monty/moco/codegeneration/context/CodeContext.java new file mode 100644 index 0000000..17be5fe --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/codegeneration/context/CodeContext.java @@ -0,0 +1,452 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.codegeneration.context; + +import static de.uni.bremen.monty.moco.codegeneration.types.LLVMTypeFactory.pointer; + +import java.util.List; +import java.util.Arrays; +import org.apache.commons.lang3.StringUtils; + +import de.uni.bremen.monty.moco.codegeneration.identifier.FunctionSignature; +import de.uni.bremen.monty.moco.codegeneration.identifier.LLVMIdentifier; +import de.uni.bremen.monty.moco.codegeneration.types.LLVMPointer; +import de.uni.bremen.monty.moco.codegeneration.types.LLVMStructType; +import de.uni.bremen.monty.moco.codegeneration.types.LLVMType; +import de.uni.bremen.monty.moco.codegeneration.types.LLVMTypeFactory.LLVMBool; +import de.uni.bremen.monty.moco.codegeneration.types.LLVMTypeFactory.LLVMIntType; + +/** The CodeContext provides methods representing LLVM-Instruction. + * + * In LLVM-IR is e.g. the load instruction, so there is a load Method in CodeContext. + * + * For convenience CodeContext extends from Context. From the perspective of it's users you have only one instance + * knowing where to write (Context) and how/what to write (CodeContext). */ +public class CodeContext extends Context { + + /** @param commentAppender + * the comment appender to be used */ + public CodeContext(CommentAppender commentAppender) { + super(commentAppender); + } + + // --------------Memory Access and Addressing Operations-------------------- + + /** Allocates space for a variable + * + * @param identifierOfLocalVar + * identifier of the local variable + * @param llvmType + * type of the local variable + * @return identifier of the local variable */ + public LLVMIdentifier alloca(LLVMIdentifier identifierOfLocalVar, LLVMType llvmType) { + append(identifierOfLocalVar.getName() + " = alloca " + llvmType); + return identifierOfLocalVar; + } + + /** Dereferences a pointer + * + * @param sourcePointer + * the pointer to dereferences + * @param + * Type encapsulated from the Pointer + * @return Address of the dereferenced value */ + public LLVMIdentifier load(LLVMIdentifier> sourcePointer, + LLVMIdentifier identifier) { + append(identifier.getName() + " = load " + sourcePointer); + return identifier; + } + + /** Stores a value + * + * @param source + * the value + * @param targetPointer + * target address + * @param + * the type of the value */ + public void store(LLVMIdentifier source, LLVMIdentifier> targetPointer) { + append("store " + source + ", " + targetPointer); + } + + /** Gets an element pointer + * + * @param varIdentifier + * the LLVMIdentifier + * @param pointer + * the pointer + * @param offsets + * the offset added to pointer */ + + @SafeVarargs + public final void getelementptr(LLVMIdentifier varIdentifier, + LLVMIdentifier pointer, LLVMIdentifier... offsets) { + append(varIdentifier.getName() + " = getelementptr inbounds " + pointer + ", " + + + StringUtils.join(offsets, ',')); + } + + // ---------------- Other Operations --------------------------------------- + + /** Compares two Integers + * + * @param icmpOperand + * How to compare + * @param arg1 + * First argument. Should be an Integer. + * @param arg2 + * Second argument. Should be an Integer. + * @return Address of the calculated result */ + public LLVMIdentifier icmp(IcmpOperand icmpOperand, LLVMIdentifier arg1, LLVMIdentifier arg2, + LLVMIdentifier product) { + + append(product.getName() + " = icmp " + icmpOperand.name() + " " + arg1 + "," + arg2.getName()); + return product; + } + + /** Compares two Integers + * + * @param fcmpOperand + * How to compare + * @param arg1 + * First argument. Should be an Integer. + * @param arg2 + * Second argument. Should be an Integer. + * @return Address of the calculated result */ + public LLVMIdentifier fcmp(FcmpOperand fcmpOperand, LLVMIdentifier arg1, LLVMIdentifier arg2, + LLVMIdentifier product) { + + append(product.getName() + " = fcmp " + fcmpOperand.name() + " " + arg1 + "," + arg2.getName()); + return product; + } + + /** The phi instruction. + * + * This must be the first instruction in a basic block. identifier and label must be nonempty and of the same + * length. + * + * @param type + * the result type + * @param resolvable + * if the result needs to be resolved + * @param identifiers + * list of identifier + * @param labels + * list of labels + * @param + * Return Type + * @return Identifier for result */ + + public LLVMIdentifier phi(T type, boolean resolvable, List> identifiers, + LLVMIdentifier identifier, List labels) { + + String typeStr = resolvable ? pointer(type).toString() : type.toString(); + StringBuilder sb = new StringBuilder(); + sb.append(String.format("%s = phi %s ", identifier.getName(), typeStr)); + for (int i = 0; i < identifiers.size(); i++) { + sb.append(String.format("[%s, %%%s]", identifiers.get(i).getName(), labels.get(i))); + + if (i != (identifiers.size() - 1)) { + sb.append(", "); + } + } + append(sb.toString()); + return identifier; + } + + /** @param signature + * Name and return type of the function + * @param arguments + * List of Arguments + * @param + * Return Type + * @return Identifier for result */ + public LLVMIdentifier call(LLVMIdentifier signature, + LLVMIdentifier identifier, LLVMIdentifier... arguments) { + return call(signature, identifier, Arrays.asList(arguments)); + } + + /** @param signature + * Name and return type of the function + * @param arguments + * List of Arguments + * @param + * Return Type + * @return Identifier for result */ + public LLVMIdentifier call(LLVMIdentifier signature, + LLVMIdentifier identifier, List> arguments) { + return call(signature, identifier, arguments, ""); + } + + /** Calls a function + * + * @param signature + * Name and return type of the function + * @param arguments + * List of Arguments + * @param overloadArgs + * Special argument that is used for overloaded methods. + * @param + * Return Type + * @return Identifier for result */ + public LLVMIdentifier call(LLVMIdentifier signature, + LLVMIdentifier identifier, List> arguments, String overloadArgs) { + append(identifier.getName() + " = call " + signature.getType() + " " + overloadArgs + " " + signature.getName() + + "(" + StringUtils.join(arguments, ',') + ")"); + return identifier; + } + + /** Calls a Procedure + * + * @param signature + * Name and return type of the function + * @param arguments + * List of Arguments */ + public void callVoid(LLVMIdentifier signature, LLVMIdentifier... arguments) { + callVoid(signature, Arrays.asList(arguments)); + } + + /** Calls a Procedure + * + * @param signature + * Name and return type of the function + * @param arguments + * List of Arguments */ + public void callVoid(LLVMIdentifier signature, List> arguments) { + append("call " + signature + "(" + StringUtils.join(arguments, ',') + ")"); + } + + /** Defines a function. Appends the function signature and opens a new scope. Instructions called after this will be + * inside this new scope until {@link #close()} is used. + * + * @param fNAttr + * LLVM-Attributes like 'ssp' + * @param functionSignature + * function Signature: name, return type and parameter */ + public void define(List fNAttr, FunctionSignature functionSignature) { + emptyLine(); + append("define " + functionSignature + " " + StringUtils.join(fNAttr, ' ') + " {"); + indent(); + } + + public enum LLVMFunctionAttribute { + ssp, nounwind + } + + /** Appends a label + * + * A label starts a basic block. Because a basic block must end with a terminator instruction the last instruction + * before this label must be a terminator instruction. `br` (branch instruction) is one of those. + * + * @param label + * name of the label */ + public void label(String label) { + append(label + ":"); + } + + /** Append a global variable. + * + * Dont use this method unless you know why, use global(Linkage, LLVMIdentifier, boolean, + * LLVMIdentifier) or global(Linkage, LLVMIdentifier, boolean) instead. */ + public LLVMIdentifier global(Linkage linkage, LLVMIdentifier target, boolean isConstant, + String initializer) { + String globalOrConstant = isConstant ? " constant " : " global "; + append(target.getName() + " = " + linkage + globalOrConstant + target.getType() + initializer); + return target; + } + + /** Append a global variable. + * + * initializer should be a StructConstant or an ArrayConstant. */ + public LLVMIdentifier global(Linkage linkage, LLVMIdentifier target, boolean isConstant, + LLVMIdentifier initializer) { + return global(linkage, target, isConstant, initializer.getName()); + } + + /** Append a global variable with a zeroinitializer. */ + public LLVMIdentifier global(Linkage linkage, LLVMIdentifier target, boolean isConstant) { + return global(linkage, target, isConstant, " zeroinitializer"); + } + + public enum Linkage { + + priv("private"), internal; + + private String name; + + private Linkage(String name) { + this.name = name; + } + + private Linkage() { + + } + + public String toString() { + if (name == null) { + return name(); + } else { + return name; + } + } + } + + /** Return instruction for functions + * + * @param llvmIdentifier + * Value to return */ + public void ret(LLVMIdentifier llvmIdentifier) { + append("ret " + llvmIdentifier); + } + + /** Declares a function. Declare means the implementation of the function is somewhere else. + * + * @param functionSignature + * Name and return type of the function */ + public void declare(FunctionSignature functionSignature) { + append("declare " + functionSignature); + } + + /** Closes the scope opened from a {@link #define(List, FunctionSignature)}. Last instruction for a function + * definition */ + public void close() { + dedent(); + append("}"); + emptyLine(); + } + + /** Unconditional branch. */ + public void branch(String label) { + append("br label %" + label); + } + + /** Conditional branch. */ + public void branch(LLVMIdentifier value, String trueLabel, String falseLabel) { + append("br " + value + ", label %" + trueLabel + ", label %" + falseLabel); + } + + /** Adds a type declaration Compares two Integers + * + * @param type + * name and structur of the new type */ + public void type(LLVMStructType type, List list) { + String variableType = " = type { "; + if (!list.isEmpty()) { + variableType += list.get(0).toString(); + for (int i = 1; i < list.size(); i++) { + variableType += ", " + list.get(i).toString(); + } + } + + append(type + variableType + " }"); + } + + @SuppressWarnings("unchecked") + public LLVMIdentifier binaryOperation(String operator, LLVMIdentifier arg1, + LLVMIdentifier arg2, LLVMIdentifier product) { + append(product.getName() + " = " + operator + " " + arg1 + "," + arg2.getName()); + return (LLVMIdentifier) product; + } + + /** Converts a pointer to an integer */ + public void ptrtoint(LLVMIdentifier target, LLVMIdentifier> source) { + append(target.getName() + " = ptrtoint " + source + " to " + target.getType()); + } + + /** Casts a pointer to a pointer of a different type */ + public void bitcast(LLVMIdentifier> target, + LLVMIdentifier> source) { + append(target.getName() + " = bitcast " + source + " to " + target.getType()); + } + + /** The sext instruction. + * + * Casts an integer of small bitsize to an integer of larger bitsize. + * + * @param result + * variable for the result + * @param toCast + * variable to cast + * @param toType + * type to cast to */ + public LLVMIdentifier sext(LLVMIdentifier toCast, LLVMIntType toType, + LLVMIdentifier result) { + append(result.getName() + " = sext " + toCast + " to " + toType); + return result; + } + + /** Compare modi for {@link #icmp(IcmpOperand, LLVMIdentifier, LLVMIdentifier, LLVMIdentifier)} */ + public enum IcmpOperand { + /** equals */ + eq, + /** not equals */ + ne, + /** unsigned greater than */ + ugt, + /** unsigned greater or equal */ + uge, + /** unsigned less than */ + ult, + /** unsigned less or equal */ + ule, + /** signed greater than */ + sgt, + /** signed greater or equal */ + sge, + /** signed less than */ + slt, + /** signed less or equal */ + sle; + } + + public enum FcmpOperand { + /** ordered and equal */ + oeq, + /** ordered and not equal */ + one, + /** ordered and greater than */ + ogt, + /** ordered and greater than or equal */ + oge, + /** ordered and less than */ + olt, + /** ordered and less than or equal */ + ole + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/codegeneration/context/CommentAppender.java b/src/main/java/de/uni/bremen/monty/moco/codegeneration/context/CommentAppender.java new file mode 100644 index 0000000..658457c --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/codegeneration/context/CommentAppender.java @@ -0,0 +1,78 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.codegeneration.context; + +import de.uni.bremen.monty.moco.ast.ASTNode; +import de.uni.bremen.monty.moco.ast.Position; +import org.apache.commons.lang3.StringUtils; + +/** Adds a comment after each line in llvm. That comment contains the Class of the ASTNode and the line in the monty File + * that is responsible for the llvm instruction. */ +public class CommentAppender { + + private ASTNode currentNode; + + /** Adds a comment + * + * @param string + * the llvm instruction + * @return the llvm with comment */ + public String addComment(String string) { + Position position = currentNode.getPosition(); + StringBuilder builder = new StringBuilder(); + + builder.append(StringUtils.rightPad(string, 90)); + builder.append("; "); + builder.append(currentNode.getClass().getSimpleName()); + builder.append(" in "); + builder.append(position.getLineNumber()); + builder.append(":"); + builder.append(position.getCharNumber()); + + return builder.toString(); + } + + /** Links the LLVM-Instructions to Monty-Nodes + * + * @param currentNode + * Node that is currently processed. */ + public void setNode(ASTNode currentNode) { + this.currentNode = currentNode; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/codegeneration/context/Context.java b/src/main/java/de/uni/bremen/monty/moco/codegeneration/context/Context.java new file mode 100644 index 0000000..c257eca --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/codegeneration/context/Context.java @@ -0,0 +1,104 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.codegeneration.context; + +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; +import java.util.List; + +/** An .ll File is composed by a Tree of Context. This Tree is realized in this class with a recursive Structure that is + * created with the attribute {@link #innerContexts} + * + * The leaves are lines holding a single Instruction represented as {@link StringData}. Those leaves can be composed + * together in a Context. For e.g. a function in llvm is a context because it is a composition of statements. One could + * further subdivide a function into multiple parts. All functions inside a .ll file are further composed into a + * context, which is then the root of the .ll file. */ +public class Context implements ContextData { + + /** Recursive Structure creating a Tree */ + private List innerContexts; + private CommentAppender commentAppender; + private int indentation = 0; + + public Context(CommentAppender commentAppender) { + this.commentAppender = commentAppender; + innerContexts = new ArrayList<>(); + } + + /** Adds an LLVM-Instruction as a Leaf to the Tree. + * + * @param data */ + public void append(String data) { + data = StringUtils.repeat(" ", indentation * 4) + data; + // data = commentAppender.addComment(data); + innerContexts.add(new StringData(data + "\n")); + } + + /** Appends a Context to the Tree. This increases the depth of the Tree... + * + * @param c */ + public void append(Context c) { + innerContexts.add(c); + } + + /** Converts this into a List of instruction as a String. Each Instruction is a new Line in the String. This is done + * by flattening the Tree by concatenating. + * + * @return All the children in a String */ + public String getData() { + StringBuilder s = new StringBuilder(); + for (ContextData contextData : innerContexts) { + s.append(contextData.getData()); + } + return s.toString(); + } + + protected void indent() { + indentation++; + } + + protected void dedent() { + indentation--; + } + + protected void emptyLine() { + innerContexts.add(new StringData("\n")); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/codegeneration/context/ContextData.java b/src/main/java/de/uni/bremen/monty/moco/codegeneration/context/ContextData.java new file mode 100644 index 0000000..58e93c4 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/codegeneration/context/ContextData.java @@ -0,0 +1,43 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.codegeneration.context; + +interface ContextData { + public String getData(); +} diff --git a/src/main/java/de/uni/bremen/monty/moco/codegeneration/context/ContextUtils.java b/src/main/java/de/uni/bremen/monty/moco/codegeneration/context/ContextUtils.java new file mode 100644 index 0000000..d5e6813 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/codegeneration/context/ContextUtils.java @@ -0,0 +1,123 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.codegeneration.context; + +import de.uni.bremen.monty.moco.ast.ASTNode; + +import java.util.Stack; + +/** Utility class for accessing different {@link Context} + * + * Holds the {@link #baseContext} which is the Context that represent a whole .ll file. */ +public class ContextUtils { + + private final CommentAppender commentAppender; + + /** represents a whole .ll file */ + private final CodeContext baseContext; + + /** on top of each .ll file there is an area where all constant declaration should be located. */ + private final CodeContext constantsContext; + + /** each function should have it's own CodeContext. This is where those are stored. The first Context in the Stack is + * the container of all functions in the .ll file and not the container for all statements in a function. + * + * A Stack is used because monty allows to have functions inside functions.(Despite having closures) LLVM doesn't + * support that feature. So while processing a function you may find another function, which you have to process. + * You start processing the new one, while saving the state of the old one in the stack */ + private Stack activeContexts; + + /** Creates a {@link #baseContext} and a {@link #constantsContext} and makes the constantContext part of the + * baseContext. */ + public ContextUtils() { + commentAppender = new CommentAppender(); + + baseContext = new CodeContext(commentAppender); + activeContexts = new Stack<>(); + activeContexts.push(baseContext); + + constantsContext = new CodeContext(commentAppender); + baseContext.append(constantsContext); + } + + /** Sets the current Node to the {@link #commentAppender} + * + * @param node + * ast node */ + public void setNode(ASTNode node) { + commentAppender.setNode(node); + } + + /** Returns the active Context. That is the Context in which the next instruction for LLVM from an 'normal' monty + * Statement should be saved. + * + * @return the active Context. */ + public CodeContext active() { + return activeContexts.peek(); + } + + /** Returns the constant Context. That is the Context in which the constant LLVM-declarations should be located. Like + * string literals. + * + * @return the constant Context. */ + public CodeContext constant() { + return constantsContext; + } + + /** Converts the {@link #baseContext} into a string. The baseContext represents a whole .ll File. So the data is the + * content of a .ll file. + * + * @return the converted {@link #baseContext} */ + public String getData() { + return baseContext.getData(); + } + + /** Adds a new Context to the {@link #activeContexts}. This should be used in the beginning of the processing of a + * monty function. So that the llvm instructions of the monty statements stored into this new Context */ + public void addNewContext() { + CodeContext context = new CodeContext(commentAppender); + activeContexts.push(context); + baseContext.append(context); + } + + /** Closes a Context opened with {@link #addNewContext()}. This should be done at the end of processing a function. */ + public void closeContext() { + activeContexts.pop(); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/codegeneration/context/Operations.java b/src/main/java/de/uni/bremen/monty/moco/codegeneration/context/Operations.java new file mode 100644 index 0000000..c978124 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/codegeneration/context/Operations.java @@ -0,0 +1,334 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ + +package de.uni.bremen.monty.moco.codegeneration.context; + +import static de.uni.bremen.monty.moco.codegeneration.types.LLVMTypeFactory.double64; +import static de.uni.bremen.monty.moco.codegeneration.types.LLVMTypeFactory.int1; +import static de.uni.bremen.monty.moco.codegeneration.types.LLVMTypeFactory.int32; +import static de.uni.bremen.monty.moco.codegeneration.types.LLVMTypeFactory.int64; +import static de.uni.bremen.monty.moco.codegeneration.types.LLVMTypeFactory.int8; +import static de.uni.bremen.monty.moco.codegeneration.types.LLVMTypeFactory.pointer; + +import java.util.Arrays; + +import de.uni.bremen.monty.moco.ast.CoreClasses; +import de.uni.bremen.monty.moco.codegeneration.Native; +import de.uni.bremen.monty.moco.codegeneration.CodeGenerator; +import de.uni.bremen.monty.moco.codegeneration.context.CodeContext.FcmpOperand; +import de.uni.bremen.monty.moco.codegeneration.context.CodeContext.IcmpOperand; +import de.uni.bremen.monty.moco.codegeneration.identifier.LLVMIdentifier; +import de.uni.bremen.monty.moco.codegeneration.identifier.LLVMIdentifierFactory; +import de.uni.bremen.monty.moco.codegeneration.types.*; +import de.uni.bremen.monty.moco.codegeneration.types.LLVMTypeFactory.*; + +import static de.uni.bremen.monty.moco.codegeneration.types.LLVMTypeFactory.*; + +public class Operations { + + private CodeGenerator codeGenerator; + private LLVMIdentifierFactory llvmIdentifierFactory; + + private LLVMIdentifier> stringFormat; + private LLVMIdentifier> intFormat; + private LLVMIdentifier> floatFormat; + private LLVMIdentifier> charFormat; + + public Operations(CodeGenerator codeGenerator, LLVMIdentifierFactory llvmIdentifierFactory) { + this.codeGenerator = codeGenerator; + this.llvmIdentifierFactory = llvmIdentifierFactory; + } + + @Native("M.Print.P.print$M.Char.C.Char") + public void printChar(CodeContext c, LLVMIdentifier addr) { + LLVMType type = addr.getType(); + LLVMIdentifier signature = llvmIdentifierFactory.newGlobal("printf", int32()); + c.call( + (LLVMIdentifier) (LLVMIdentifier) signature, + llvmIdentifierFactory.newLocal(signature.getType(), false), + Arrays.> asList(charFormat, addr), + "(i8*, ...)*"); + } + + @Native("M.Print.P.print$M.std.C.String") + public void printString(CodeContext c, LLVMIdentifier addr) { + LLVMType type = addr.getType(); + LLVMIdentifier signature = llvmIdentifierFactory.newGlobal("printf", int32()); + c.call( + (LLVMIdentifier) (LLVMIdentifier) signature, + llvmIdentifierFactory.newLocal(signature.getType(), false), + Arrays.> asList(stringFormat, addr), + "(i8*, ...)*"); + } + + @Native("M.Print.P.print$M.Int.C.Int") + public void printInt(CodeContext c, LLVMIdentifier addr) { + LLVMType type = addr.getType(); + LLVMIdentifier signature = llvmIdentifierFactory.newGlobal("printf", int32()); + c.call( + (LLVMIdentifier) (LLVMIdentifier) signature, + llvmIdentifierFactory.newLocal(signature.getType(), false), + Arrays.> asList(intFormat, addr), + "(i8*, ...)*"); + } + + @Native("M.Print.P.print$M.Bool.C.Bool") + public void printBool(CodeContext c, LLVMIdentifier addr) { + LLVMType type = addr.getType(); + LLVMIdentifier signature = llvmIdentifierFactory.newGlobal("printf", int32()); + c.call( + (LLVMIdentifier) (LLVMIdentifier) signature, + llvmIdentifierFactory.newLocal(signature.getType(), false), + Arrays.> asList(intFormat, addr), + "(i8*, ...)*"); + } + + @Native("M.Print.P.print$M.Float.C.Float") + public void printFloat(CodeContext c, LLVMIdentifier addr) { + LLVMType type = addr.getType(); + LLVMIdentifier signature = llvmIdentifierFactory.newGlobal("printf", int32()); + c.call( + (LLVMIdentifier) (LLVMIdentifier) signature, + llvmIdentifierFactory.newLocal(signature.getType(), false), + Arrays.> asList(floatFormat, addr), + "(i8*, ...)*"); + } + + @Native("M.Int.C.Int.F.operator_plus$M.Int.C.Int$M.Int.C.Int") + public LLVMIdentifier add(CodeContext c, LLVMIdentifier arg1, LLVMIdentifier arg2) { + return c.binaryOperation("add", arg1, arg2, llvmIdentifierFactory.newLocal(arg1.getType(), false)); + } + + @Native("M.Float.C.Float.F.operator_plus$M.Float.C.Float$M.Float.C.Float") + public LLVMIdentifier fadd(CodeContext c, LLVMIdentifier arg1, + LLVMIdentifier arg2) { + return c.binaryOperation("fadd", arg1, arg2, llvmIdentifierFactory.newLocal(arg1.getType(), false)); + } + + @Native("M.Int.C.Int.F.operator_minus$M.Int.C.Int$M.Int.C.Int") + public LLVMIdentifier sub(CodeContext c, LLVMIdentifier arg1, LLVMIdentifier arg2) { + return c.binaryOperation("sub", arg1, arg2, llvmIdentifierFactory.newLocal(arg1.getType(), false)); + } + + @Native("M.Int.C.Int.F.operator_minus$M.Int.C.Int") + public LLVMIdentifier sub(CodeContext c, LLVMIdentifier arg1) { + return c.binaryOperation( + "sub", + llvmIdentifierFactory.constant(int64(), 0), + arg1, + llvmIdentifierFactory.newLocal(arg1.getType(), false)); + } + + @Native("M.Float.C.Float.F.operator_minus$M.Float.C.Float") + public LLVMIdentifier fsub(CodeContext c, LLVMIdentifier arg1) { + return c.binaryOperation( + "fsub", + llvmIdentifierFactory.constant(double64(), 0.0f), + arg1, + llvmIdentifierFactory.newLocal(arg1.getType(), false)); + } + + @Native("M.Float.C.Float.F.operator_minus$M.Float.C.Float$M.Float.C.Float") + public LLVMIdentifier fsub(CodeContext c, LLVMIdentifier arg1, + LLVMIdentifier arg2) { + return c.binaryOperation("fsub", arg1, arg2, llvmIdentifierFactory.newLocal(arg1.getType(), false)); + } + + @Native("M.Int.C.Int.F.operator_mult$M.Int.C.Int$M.Int.C.Int") + public LLVMIdentifier mul(CodeContext c, LLVMIdentifier arg1, LLVMIdentifier arg2) { + return c.binaryOperation("mul", arg1, arg2, llvmIdentifierFactory.newLocal(arg1.getType(), false)); + } + + @Native("M.Float.C.Float.F.operator_mult$M.Float.C.Float$M.Float.C.Float") + public LLVMIdentifier fmul(CodeContext c, LLVMIdentifier arg1, + LLVMIdentifier arg2) { + return c.binaryOperation("fmul", arg1, arg2, llvmIdentifierFactory.newLocal(arg1.getType(), false)); + } + + @Native("M.Int.C.Int.F.operator_div$M.Int.C.Int$M.Int.C.Int") + public LLVMIdentifier sdiv(CodeContext c, LLVMIdentifier arg1, LLVMIdentifier arg2) { + return c.binaryOperation("sdiv", arg1, arg2, llvmIdentifierFactory.newLocal(arg1.getType(), false)); + } + + @Native("M.Float.C.Float.F.operator_div$M.Float.C.Float$M.Float.C.Float") + public LLVMIdentifier fdiv(CodeContext c, LLVMIdentifier arg1, + LLVMIdentifier arg2) { + return c.binaryOperation("fdiv", arg1, arg2, llvmIdentifierFactory.newLocal(arg1.getType(), false)); + } + + @Native("M.Int.C.Int.F.operator_equal$M.Bool.C.Bool$M.Int.C.Int") + public LLVMIdentifier intEq(CodeContext c, LLVMIdentifier arg1, LLVMIdentifier arg2) { + return c.icmp(IcmpOperand.eq, arg1, arg2, llvmIdentifierFactory.newLocal(int1(), false)); + } + + @Native("M.Bool.C.Bool.F.operator_equal$M.Bool.C.Bool$M.Bool.C.Bool") + public LLVMIdentifier boolEq(CodeContext c, LLVMIdentifier arg1, LLVMIdentifier arg2) { + return c.icmp(IcmpOperand.eq, arg1, arg2, llvmIdentifierFactory.newLocal(int1(), false)); + } + + @Native("M.Float.C.Float.F.operator_equal$M.Bool.C.Bool$M.Float.C.Float") + public LLVMIdentifier floatEq(CodeContext c, LLVMIdentifier arg1, + LLVMIdentifier arg2) { + return c.fcmp(FcmpOperand.oeq, arg1, arg2, llvmIdentifierFactory.newLocal(int1(), false)); + } + + @Native("M.Int.C.Int.F.operator_not_equal$M.Bool.C.Bool$M.Int.C.Int") + public LLVMIdentifier intNe(CodeContext c, LLVMIdentifier arg1, LLVMIdentifier arg2) { + return c.icmp(IcmpOperand.ne, arg1, arg2, llvmIdentifierFactory.newLocal(int1(), false)); + } + + @Native("M.Bool.C.Bool.F.operator_not_equal$M.Bool.C.Bool$M.Bool.C.Bool") + public LLVMIdentifier boolNe(CodeContext c, LLVMIdentifier arg1, LLVMIdentifier arg2) { + return c.icmp(IcmpOperand.ne, arg1, arg2, llvmIdentifierFactory.newLocal(int1(), false)); + } + + @Native("M.Float.C.Float.F.operator_not_equal$M.Bool.C.Bool$M.Float.C.Float") + public LLVMIdentifier floatNe(CodeContext c, LLVMIdentifier arg1, + LLVMIdentifier arg2) { + return c.fcmp(FcmpOperand.one, arg1, arg2, llvmIdentifierFactory.newLocal(int1(), false)); + } + + @Native("M.Int.C.Int.F.operator_lesser$M.Bool.C.Bool$M.Int.C.Int") + public LLVMIdentifier intSlt(CodeContext c, LLVMIdentifier arg1, LLVMIdentifier arg2) { + return c.icmp(IcmpOperand.slt, arg1, arg2, llvmIdentifierFactory.newLocal(int1(), false)); + } + + @Native("M.Float.C.Float.F.operator_lesser$M.Bool.C.Bool$M.Float.C.Float") + public LLVMIdentifier floatSlt(CodeContext c, LLVMIdentifier arg1, + LLVMIdentifier arg2) { + return c.fcmp(FcmpOperand.olt, arg1, arg2, llvmIdentifierFactory.newLocal(int1(), false)); + } + + @Native("M.Int.C.Int.F.operator_lesser_equal$M.Bool.C.Bool$M.Int.C.Int") + public LLVMIdentifier intSle(CodeContext c, LLVMIdentifier arg1, LLVMIdentifier arg2) { + return c.icmp(IcmpOperand.sle, arg1, arg2, llvmIdentifierFactory.newLocal(int1(), false)); + } + + @Native("M.Float.C.Float.F.operator_lesser_equal$M.Bool.C.Bool$M.Float.C.Float") + public LLVMIdentifier floatSle(CodeContext c, LLVMIdentifier arg1, + LLVMIdentifier arg2) { + return c.fcmp(FcmpOperand.ole, arg1, arg2, llvmIdentifierFactory.newLocal(int1(), false)); + } + + @Native("M.Int.C.Int.F.operator_greater$M.Bool.C.Bool$M.Int.C.Int") + public LLVMIdentifier intSgt(CodeContext c, LLVMIdentifier arg1, LLVMIdentifier arg2) { + return c.icmp(IcmpOperand.sgt, arg1, arg2, llvmIdentifierFactory.newLocal(int1(), false)); + } + + @Native("M.Float.C.Float.F.operator_greater$M.Bool.C.Bool$M.Float.C.Float") + public LLVMIdentifier floatSgt(CodeContext c, LLVMIdentifier arg1, + LLVMIdentifier arg2) { + return c.fcmp(FcmpOperand.ogt, arg1, arg2, llvmIdentifierFactory.newLocal(int1(), false)); + } + + @Native("M.Int.C.Int.F.operator_greater_equal$M.Bool.C.Bool$M.Int.C.Int") + public LLVMIdentifier intSge(CodeContext c, LLVMIdentifier arg1, LLVMIdentifier arg2) { + return c.icmp(IcmpOperand.sge, arg1, arg2, llvmIdentifierFactory.newLocal(int1(), false)); + } + + @Native("M.Float.C.Float.F.operator_greater_equal$M.Bool.C.Bool$M.Float.C.Float") + public LLVMIdentifier floatSge(CodeContext c, LLVMIdentifier arg1, + LLVMIdentifier arg2) { + return c.fcmp(FcmpOperand.oge, arg1, arg2, llvmIdentifierFactory.newLocal(int1(), false)); + } + + @Native("M.Bool.C.Bool.F.operator_and$M.Bool.C.Bool$M.Bool.C.Bool") + public LLVMIdentifier and(CodeContext c, LLVMIdentifier arg1, LLVMIdentifier arg2) { + return c.binaryOperation("and", arg1, arg2, llvmIdentifierFactory.newLocal(arg1.getType(), false)); + } + + @Native("M.Bool.C.Bool.F.operator_or$M.Bool.C.Bool$M.Bool.C.Bool") + public LLVMIdentifier or(CodeContext c, LLVMIdentifier arg1, LLVMIdentifier arg2) { + return c.binaryOperation("or", arg1, arg2, llvmIdentifierFactory.newLocal(arg1.getType(), false)); + } + + @Native("M.Bool.C.Bool.F.operator_xor$M.Bool.C.Bool$M.Bool.C.Bool") + public LLVMIdentifier xor(CodeContext c, LLVMIdentifier arg1, LLVMIdentifier arg2) { + return c.binaryOperation("xor", arg1, arg2, llvmIdentifierFactory.newLocal(arg1.getType(), false)); + } + + @Native("M.Bool.C.Bool.F.operator_not$M.Bool.C.Bool") + public LLVMIdentifier not(CodeContext c, LLVMIdentifier arg1) { + return c.binaryOperation( + "xor", + arg1, + llvmIdentifierFactory.constant(int1(), 1), + llvmIdentifierFactory.newLocal(arg1.getType(), false)); + } + + @Native("M.Int.C.Int.F.operator_rem$M.Int.C.Int$M.Int.C.Int") + public LLVMIdentifier srem(CodeContext c, LLVMIdentifier arg1, LLVMIdentifier arg2) { + return c.binaryOperation("srem", arg1, arg2, llvmIdentifierFactory.newLocal(arg1.getType(), false)); + } + + @Native("M.Array.F.operator_array_access$M.Int.C.Int$M.std.C.Array$M.Int.C.Int") + public LLVMIdentifier arrayAccess(CodeContext c, LLVMIdentifier arrayPointer, + LLVMIdentifier index) { + + LLVMIdentifier> arrayStructPointer = + (LLVMIdentifier>) (LLVMIdentifier) arrayPointer; + + codeGenerator.checkArrayBounds(c, arrayStructPointer, index); + LLVMIdentifier result = + llvmIdentifierFactory.newLocal(codeGenerator.mapToLLVMType(CoreClasses.intType())); + c.getelementptr( + result, + arrayStructPointer, + llvmIdentifierFactory.constant(int32(), 0), + llvmIdentifierFactory.constant(int32(), 1), + index); + return result; + } + + public void setStringFormat(LLVMIdentifier> stringFormat) { + this.stringFormat = stringFormat; + } + + public void setIntFormat(LLVMIdentifier> intFormat) { + this.intFormat = intFormat; + } + + public void setFloatFormat(LLVMIdentifier> floatFormat) { + this.floatFormat = floatFormat; + } + + public void setCharFormat(LLVMIdentifier> charformat) { + this.charFormat = charformat; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/codegeneration/context/StringData.java b/src/main/java/de/uni/bremen/monty/moco/codegeneration/context/StringData.java new file mode 100644 index 0000000..090ab37 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/codegeneration/context/StringData.java @@ -0,0 +1,52 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.codegeneration.context; + +class StringData implements ContextData { + private String data; + + public StringData(String data) { + this.data = data; + } + + @Override + public String getData() { + return data; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/codegeneration/identifier/ArrayConstant.java b/src/main/java/de/uni/bremen/monty/moco/codegeneration/identifier/ArrayConstant.java new file mode 100644 index 0000000..e413f3e --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/codegeneration/identifier/ArrayConstant.java @@ -0,0 +1,64 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.codegeneration.identifier; + +import de.uni.bremen.monty.moco.codegeneration.types.LLVMType; +import de.uni.bremen.monty.moco.codegeneration.types.LLVMArrayType; +import org.apache.commons.lang3.StringUtils; + +import java.util.List; + +public class ArrayConstant extends LLVMIdentifier { + + private List> arguments; + + ArrayConstant(LLVMArrayType type, List> arguments) { + super(type, "", false); + this.arguments = arguments; + } + + public List> getArguments() { + return arguments; + } + + @Override + public String getName() { + return " [ " + StringUtils.join(arguments, ", ") + " ]"; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/codegeneration/identifier/FunctionSignature.java b/src/main/java/de/uni/bremen/monty/moco/codegeneration/identifier/FunctionSignature.java new file mode 100644 index 0000000..c97ce59 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/codegeneration/identifier/FunctionSignature.java @@ -0,0 +1,59 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.codegeneration.identifier; + +import de.uni.bremen.monty.moco.codegeneration.types.LLVMType; +import org.apache.commons.lang3.StringUtils; + +import java.util.List; + +public class FunctionSignature extends LLVMIdentifier { + + private List> parameter; + + FunctionSignature(T type, String name, List> parameter) { + super(type, name, false); + this.parameter = parameter; + } + + @Override + public String toString() { + return type + " " + name + "(" + StringUtils.join(parameter, ", ") + ")"; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/codegeneration/identifier/LLVMIdentifier.java b/src/main/java/de/uni/bremen/monty/moco/codegeneration/identifier/LLVMIdentifier.java new file mode 100644 index 0000000..6983921 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/codegeneration/identifier/LLVMIdentifier.java @@ -0,0 +1,96 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.codegeneration.identifier; + +import de.uni.bremen.monty.moco.codegeneration.types.LLVMType; + +/** LLVMIdentifier is the simple composition of an LLVMType and a name. In LLVM-IR you often have to write s.th. like + * 'i64 %0' as a part of an instruction. This is an LLVMIdentifier. And if you use {@link #toString()} it gives you the + * representation for LLVM-IR. + * + * The Type can be composed, see {@link LLVMType}. And the name can be more complex too. e.g. ' getelementptr inbounds + * (i8* %0, i32 0, i32 0) ' is currently modeled as a simple name for an identifier. + * + * Instances should only be created with the {@link LLVMIdentifierFactory}. + * + * @param + * The Type that is encapsulated in the Identifier. If you have e.g. 'i64* %2' the Type will be + * LLVMIdentifier> */ +public class LLVMIdentifier { + protected final String name; + protected final T type; + + /** This is indicates if this value is a concrete value, or a pointer to a value, that needs to be resolved or + * dereference to gets its value. */ + private boolean resolvable; + + /** Don't use this. Only {@link LLVMIdentifierFactory} should create instances. + * + * @param type + * @param name + * @param resolvable */ + LLVMIdentifier(T type, String name, boolean resolvable) { + this.name = name; + this.type = type; + this.resolvable = resolvable; + } + + public String getName() { + return name; + } + + public T getType() { + return type; + } + + /** @returns the LLVM-IR representation. e.g. new LLVMIdentifier(pointer(int64(),"%foobar").toString() == + * "i64* %foobar" */ + @Override + public String toString() { + return type + " " + name; + } + + /** Is it a value or a pointer to value + * + * @return true if its a pointer to a value */ + public boolean needToBeResolved() { + return resolvable; + } + +} diff --git a/src/main/java/de/uni/bremen/monty/moco/codegeneration/identifier/LLVMIdentifierFactory.java b/src/main/java/de/uni/bremen/monty/moco/codegeneration/identifier/LLVMIdentifierFactory.java new file mode 100644 index 0000000..08ce3a0 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/codegeneration/identifier/LLVMIdentifierFactory.java @@ -0,0 +1,165 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.codegeneration.identifier; + +import de.uni.bremen.monty.moco.codegeneration.types.LLVMArrayType; +import de.uni.bremen.monty.moco.codegeneration.types.LLVMPointer; +import de.uni.bremen.monty.moco.codegeneration.types.LLVMStructType; +import de.uni.bremen.monty.moco.codegeneration.types.LLVMType; + +import java.util.List; +import java.util.Stack; +import java.util.concurrent.atomic.AtomicInteger; + +import static de.uni.bremen.monty.moco.codegeneration.types.LLVMTypeFactory.*; + +/** This Factory creates LLVMIdentifier. It has various Methods allowing you to create global or local Identifier, with a + * given name or a generated name, resolvable or not, and even elementPointer and functionSignatures + * + * LLVM use prefixes to differ local from global values. '@' is global '%' is local + * + * Abstract on LLVM Name Policy for local values: If you don't care about the name of a value you can just use a number. + * Like '%3' BUT this number must start with 0 for the first value in the scope and have to increment, without omitting + * one. This counter is only valid in a local scope. + * + * This is where the {@link #scope} comes into play. */ +public class LLVMIdentifierFactory { + + /** Global counter for global values. */ + private int strIndex = 0; + + /** + * + */ + private Stack scope = new Stack<>(); + + public LLVMIdentifierFactory() { + scope.push(new AtomicInteger()); + } + + public LLVMIdentifier newLocal(String symbol, T type, boolean resolvable) { + return new LLVMIdentifier<>(type, "%" + symbol, resolvable); + } + + public LLVMIdentifier newLocal(T type) { + return newLocal(type, true); + } + + private String newName() { + return "_unnamed_" + scope.peek().getAndIncrement(); + } + + private String newGlobalName() { + return "." + strIndex++; + } + + public void openScope() { + scope.push(new AtomicInteger()); + } + + public void closeScope() { + scope.pop(); + } + + public LLVMIdentifier newGlobal(String symbol, T type) { + return new LLVMIdentifier<>(type, "@" + symbol, true); + } + + public LLVMIdentifier newGlobal(T type) { + return new LLVMIdentifier<>(type, "@" + newGlobalName(), true); + } + + public LLVMIdentifier> pointerTo(LLVMIdentifier right) { + return new LLVMIdentifier<>(pointer(right.getType()), right.getName(), false); + } + + public LLVMIdentifier constant(T llvmType, int value) { + return new LLVMIdentifier<>(llvmType, value + "", false); + } + + public LLVMIdentifier constant(T llvmType, float value) { + return new LLVMIdentifier<>(llvmType, value + "", false); + } + + public LLVMIdentifier constant(T llvmType, boolean value) { + return new LLVMIdentifier<>(llvmType, value + "", false); + } + + public LLVMIdentifier> constantNull(LLVMPointer llvmType) { + return new LLVMIdentifier<>(llvmType, "null", false); + } + + public StructConstant constant(LLVMStructType llvmType, List> arguments) { + return new StructConstant(llvmType, arguments); + } + + public ArrayConstant constant(LLVMArrayType llvmType, List> arguments) { + return new ArrayConstant(llvmType, arguments); + } + + public LLVMIdentifier> elementPointerTo( + LLVMIdentifier> identifier) { + LLVMArrayType arrayType = identifier.getType(); + T typeInArray = arrayType.getInternalType(); + LLVMPointer pointer = pointer(typeInArray); + return new LLVMIdentifier<>(pointer, "getelementptr inbounds (" + arrayType + "* " + identifier.getName() + + ", i32 0, i32 0)", false); + } + + public FunctionSignature newFunction(T type, String s, + List> llvmTypes) { + return new FunctionSignature<>(type, "@" + s, llvmTypes); + } + + public LLVMIdentifier bitcast(LLVMIdentifier identifier, LLVMType toType) { + return new LLVMIdentifier<>(toType, "bitcast (" + identifier + " to " + toType + ")", false); + } + + public LLVMIdentifier newLocal(T type, boolean resolvable) { + return new LLVMIdentifier<>(type, "%" + newName(), resolvable); + } + + public LLVMIdentifier nameless(T type) { + return new LLVMIdentifier<>(type, "", false); + } + + public LLVMIdentifier voidId() { + return nameless(voidType()); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/codegeneration/identifier/StructConstant.java b/src/main/java/de/uni/bremen/monty/moco/codegeneration/identifier/StructConstant.java new file mode 100644 index 0000000..31814fa --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/codegeneration/identifier/StructConstant.java @@ -0,0 +1,64 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.codegeneration.identifier; + +import de.uni.bremen.monty.moco.codegeneration.types.LLVMType; +import de.uni.bremen.monty.moco.codegeneration.types.LLVMStructType; +import org.apache.commons.lang3.StringUtils; + +import java.util.List; + +public class StructConstant extends LLVMIdentifier { + + private List> arguments; + + StructConstant(LLVMStructType type, List> arguments) { + super(type, "", false); + this.arguments = arguments; + } + + public List> getArguments() { + return arguments; + } + + @Override + public String getName() { + return " { " + StringUtils.join(arguments, ", ") + " }"; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/codegeneration/types/LLVMArrayType.java b/src/main/java/de/uni/bremen/monty/moco/codegeneration/types/LLVMArrayType.java new file mode 100644 index 0000000..3555729 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/codegeneration/types/LLVMArrayType.java @@ -0,0 +1,84 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.codegeneration.types; + +/** {@inheritDoc} */ +public class LLVMArrayType extends LLVMType { + + private final T internalType; + private final int size; + + LLVMArrayType(T internalType, int size) { + super(); + this.internalType = internalType; + this.size = size; + } + + @Override + public String toString() { + return "[" + size + " x " + internalType.toString() + "]"; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + LLVMArrayType llvmArray = (LLVMArrayType) o; + + if (size != llvmArray.size) return false; + + return internalType.equals(llvmArray.internalType); + } + + @Override + public int hashCode() { + int result = internalType.hashCode(); + result = 31 * result + size; + return result; + } + + public T getInternalType() { + return internalType; + } + + public int getSize() { + return size; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/codegeneration/types/LLVMFunctionType.java b/src/main/java/de/uni/bremen/monty/moco/codegeneration/types/LLVMFunctionType.java new file mode 100644 index 0000000..d6c6d5d --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/codegeneration/types/LLVMFunctionType.java @@ -0,0 +1,83 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ + +package de.uni.bremen.monty.moco.codegeneration.types; + +import org.apache.commons.lang3.StringUtils; +import java.util.List; +import java.util.Objects; + +/** A function type in LLVM. This is the type of a pointer to a function. */ +public class LLVMFunctionType extends LLVMType { + + private LLVMType returnType; + private List parameter; + + LLVMFunctionType(LLVMType returnType, List parameter) { + this.returnType = returnType; + this.parameter = parameter; + } + + public LLVMType getReturnType() { + return returnType; + } + + public List getParameter() { + return parameter; + } + + @Override + public String toString() { + return returnType.toString() + " ( " + StringUtils.join(parameter, ",") + " )"; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + LLVMFunctionType that = (LLVMFunctionType) o; + return returnType.equals(that.returnType) && parameter.equals(that.parameter); + } + + @Override + public int hashCode() { + return Objects.hash(returnType, parameter); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/codegeneration/types/LLVMPointer.java b/src/main/java/de/uni/bremen/monty/moco/codegeneration/types/LLVMPointer.java new file mode 100644 index 0000000..2d95655 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/codegeneration/types/LLVMPointer.java @@ -0,0 +1,74 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.codegeneration.types; + +/** {@inheritDoc} */ +public class LLVMPointer extends LLVMType { + private T internalType; + + LLVMPointer(T internalType) { + this.internalType = internalType; + } + + @Override + public String toString() { + return internalType.toString() + "*"; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + LLVMPointer that = (LLVMPointer) o; + + if (!internalType.equals(that.internalType)) return false; + + return true; + } + + @Override + public int hashCode() { + return internalType.hashCode(); + } + + public T getInternalType() { + return internalType; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/codegeneration/types/LLVMSimpleType.java b/src/main/java/de/uni/bremen/monty/moco/codegeneration/types/LLVMSimpleType.java new file mode 100644 index 0000000..222b8ec --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/codegeneration/types/LLVMSimpleType.java @@ -0,0 +1,72 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.codegeneration.types; + +/** {@inheritDoc} */ +public class LLVMSimpleType extends LLVMType { + + private String type; + + LLVMSimpleType(String type) { + this.type = type; + } + + @Override + public String toString() { + return type; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + LLVMSimpleType llvmType = (LLVMSimpleType) o; + + if (type != null ? !type.equals(llvmType.type) : llvmType.type != null) return false; + + return true; + } + + @Override + public int hashCode() { + return type != null ? type.hashCode() : 0; + } + +} diff --git a/src/main/java/de/uni/bremen/monty/moco/codegeneration/types/LLVMStructType.java b/src/main/java/de/uni/bremen/monty/moco/codegeneration/types/LLVMStructType.java new file mode 100644 index 0000000..d614b6b --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/codegeneration/types/LLVMStructType.java @@ -0,0 +1,72 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.codegeneration.types; + +/** A struct type in LLVM. In LLVM there are no classes, only structs. So the attributes of a class can be modeled as a + * struct but the functions have to be defined somewhere else. */ +public class LLVMStructType extends LLVMType { + + private String name; + + LLVMStructType(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + LLVMStructType that = (LLVMStructType) o; + + if (!name.equals(that.name)) return false; + + return true; + } + + @Override + public int hashCode() { + return name.hashCode(); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/codegeneration/types/LLVMType.java b/src/main/java/de/uni/bremen/monty/moco/codegeneration/types/LLVMType.java new file mode 100644 index 0000000..0ed0eb8 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/codegeneration/types/LLVMType.java @@ -0,0 +1,61 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.codegeneration.types; + +/** An LLVMType represents a type for LLVM-IR. This can be a LLVMSimpleType like 'i64' or an composed Type like 'i8*'. + * SubTypes like LLVMPointer or LLVMArrayType are designed that they can be composed freely. + * + * If you want an Pointer to an Array with Pointers to boolean values you can write: + * LLVMPointer>> type = pointer(array(pointer(int1()),2)) using the factory Methods + * in LLVMTypeFactory. + * + * {@link #toString()} is overwritten in such a way, that it results in the String that represent this type in LLVM-IR + * e.g. type.toString() == "[2 x i1*]*" + * + * Only use {@link LLVMTypeFactory} to instantiate LLVMTypes. */ +public abstract class LLVMType { + + public abstract String toString(); + + @Override + public abstract boolean equals(Object o); + + @Override + public abstract int hashCode(); +} diff --git a/src/main/java/de/uni/bremen/monty/moco/codegeneration/types/LLVMTypeFactory.java b/src/main/java/de/uni/bremen/monty/moco/codegeneration/types/LLVMTypeFactory.java new file mode 100644 index 0000000..f43ce80 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/codegeneration/types/LLVMTypeFactory.java @@ -0,0 +1,154 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.codegeneration.types; + +import java.util.List; +import org.apache.commons.lang3.StringUtils; + +public class LLVMTypeFactory { + + public static LLVMInt64 int64() { + return new LLVMInt64(); + } + + public static LLVMInt8 int8() { + return new LLVMInt8(); + } + + public static LLVMInt32 int32() { + return new LLVMInt32(); + } + + public static LLVMBool int1() { + return new LLVMBool(); + } + + public static LLVMFloat float32() { + return new LLVMFloat(); + } + + public static LLVMDouble double64() { + return new LLVMDouble(); + } + + public static LLVMPointer pointer(T type) { + return new LLVMPointer<>(type); + } + + public static LLVMArrayType array(T type, int size) { + return new LLVMArrayType<>(type, size); + } + + public static LLVMNotDefinedType notDefined() { + return new LLVMNotDefinedType(); + } + + public static LLVMVoidType voidType() { + return new LLVMVoidType(); + } + + public static interface LLVMIntType { + } + + public static class LLVMVoidType extends LLVMSimpleType { + public LLVMVoidType() { + super("void"); + } + } + + public static class LLVMNotDefinedType extends LLVMSimpleType { + public LLVMNotDefinedType() { + super("..."); + } + } + + public abstract static class LLVMInt extends LLVMSimpleType { + LLVMInt(String type) { + super(type); + } + } + + public static class LLVMInt64 extends LLVMInt { + public LLVMInt64() { + super("i64"); + } + } + + public static class LLVMInt8 extends LLVMInt { + public LLVMInt8() { + super("i8"); + } + } + + public static class LLVMInt32 extends LLVMInt { + public LLVMInt32() { + super("i32"); + } + } + + public static class LLVMBool extends LLVMSimpleType implements LLVMIntType { + public LLVMBool() { + super("i1"); + } + } + + public static class LLVMFloat extends LLVMSimpleType { + public LLVMFloat() { + super("float"); + } + } + + public static class LLVMDouble extends LLVMSimpleType { + public LLVMDouble() { + super("double"); + } + } + + public static LLVMStructType struct(String name) { + return new LLVMStructType("%" + name); + } + + public static LLVMStructType struct(List types) { + return new LLVMStructType(" { " + StringUtils.join(types, ", ") + " }"); + } + + public static LLVMFunctionType function(LLVMType returnType, List parameter) { + return new LLVMFunctionType(returnType, parameter); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/codegeneration/types/TypeConverter.java b/src/main/java/de/uni/bremen/monty/moco/codegeneration/types/TypeConverter.java new file mode 100644 index 0000000..02b945d --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/codegeneration/types/TypeConverter.java @@ -0,0 +1,217 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ + +package de.uni.bremen.monty.moco.codegeneration.types; + +import de.uni.bremen.monty.moco.ast.ASTNode; +import de.uni.bremen.monty.moco.ast.CoreClasses; +import de.uni.bremen.monty.moco.ast.declaration.*; +import de.uni.bremen.monty.moco.codegeneration.identifier.LLVMIdentifier; +import de.uni.bremen.monty.moco.codegeneration.identifier.LLVMIdentifierFactory; +import de.uni.bremen.monty.moco.codegeneration.context.CodeContext; +import de.uni.bremen.monty.moco.codegeneration.context.CodeContext.Linkage; + +import java.util.*; + +import static de.uni.bremen.monty.moco.codegeneration.types.LLVMTypeFactory.*; + +public class TypeConverter { + private Map typeMap = new HashMap<>(); + private LLVMIdentifierFactory llvmIdentifierFactory; + private CodeContext constantContext; + + public TypeConverter(LLVMIdentifierFactory llvmIdentifierFactory, CodeContext constantContext) { + this.llvmIdentifierFactory = llvmIdentifierFactory; + this.constantContext = constantContext; + initPreDefinedTypes(); + } + + private void initPreDefinedTypes() { + typeMap.put(CoreClasses.stringType(), pointer(int8())); + typeMap.put(CoreClasses.voidType(), voidType()); + } + + private LLVMPointer convertType(ProcedureDeclaration type) { + List parameter = new ArrayList<>(); + final ASTNode grandFatherNode = type.getParentNode().getParentNode(); + if (grandFatherNode instanceof ClassDeclaration) { + ClassDeclaration typeDeclaration = (ClassDeclaration) grandFatherNode; + parameter.add(mapToLLVMType(typeDeclaration)); + } + for (VariableDeclaration varDecl : type.getParameter()) { + parameter.add(mapToLLVMType(varDecl.getType())); + } + if (type instanceof FunctionDeclaration) { + FunctionDeclaration func = (FunctionDeclaration) type; + return pointer(function(mapToLLVMType(func.getReturnType()), parameter)); + } + return pointer(function(voidType(), parameter)); + } + + private LLVMPointer convertType(ClassDeclaration type) { + return pointer(struct(type.getMangledIdentifier().getSymbol())); + } + + public TypeDeclaration mapToBoxedType(LLVMType type) { + if (type instanceof LLVMBool) { + return CoreClasses.boolType(); + } else if (type instanceof LLVMInt) { + return CoreClasses.intType(); + } else if (type instanceof LLVMDouble) { + return CoreClasses.floatType(); + } else if (type instanceof LLVMInt8) { + return CoreClasses.charType(); + } + return null; + } + + private T convertType(TypeDeclaration type) { + if (type instanceof ProcedureDeclaration) { + return (T) convertType((ProcedureDeclaration) type); + } + return (T) convertType((ClassDeclaration) type); + } + + private void addType(TypeDeclaration typeDecl) { + if (typeDecl == CoreClasses.arrayType()) { + addArray(typeDecl); + } else if (typeDecl instanceof ClassDeclaration) { + addClass((ClassDeclaration) typeDecl); + } + } + + private void addClass(ClassDeclaration classDecl) { + String mangledNodeName = classDecl.getMangledIdentifier().getSymbol(); + LLVMStructType llvmClassType = struct(classDecl.getMangledIdentifier().getSymbol()); + List llvmClassTypeDeclarations = new ArrayList<>(); + + LLVMStructType llvmVMTType = struct(mangledNodeName + "_vmt_type"); + List llvmVMTTypeDeclarations = new ArrayList<>(); + llvmClassTypeDeclarations.add(pointer(llvmVMTType)); + + LLVMIdentifier llvmVMTDataIdentifier = + llvmIdentifierFactory.newGlobal(mangledNodeName + "_vmt_data", (LLVMType) llvmVMTType); + List> llvmVMTDataInitializer = new ArrayList<>(); + + List recursiveSuperClassDeclarations = classDecl.getSuperClassDeclarationsRecursive(); + LLVMArrayType llvmCTDataType = array(pointer(int8()), recursiveSuperClassDeclarations.size() + 1); + LLVMIdentifier llvmCTDataIdentifier = + llvmIdentifierFactory.newGlobal(mangledNodeName + "_ct_data", (LLVMType) llvmCTDataType); + List> llvmCTDataInitializer = new ArrayList<>(); + + llvmVMTTypeDeclarations.add(pointer(llvmCTDataType)); + llvmVMTDataInitializer.add((LLVMIdentifier) (LLVMIdentifier) llvmIdentifierFactory.pointerTo(llvmCTDataIdentifier)); + + for (ClassDeclaration classDeclaration : recursiveSuperClassDeclarations) { + // Ensure that addType() was called for this classDeclaration so that a VMT/CT was generated. + mapToLLVMType(classDeclaration); + LLVMIdentifier vmtDataIdent = + llvmIdentifierFactory.newGlobal( + classDeclaration.getMangledIdentifier().getSymbol() + "_vmt_data", + (LLVMType) pointer(struct(classDeclaration.getMangledIdentifier().getSymbol() + "_vmt_type"))); + llvmCTDataInitializer.add(llvmIdentifierFactory.bitcast(vmtDataIdent, pointer(int8()))); + } + llvmCTDataInitializer.add((LLVMIdentifier) (LLVMIdentifier) llvmIdentifierFactory.constantNull(pointer(int8()))); + + if (classDecl == CoreClasses.intType()) { + llvmClassTypeDeclarations.add(LLVMTypeFactory.int64()); + } else if (classDecl == CoreClasses.boolType()) { + llvmClassTypeDeclarations.add(LLVMTypeFactory.int1()); + } else if (classDecl == CoreClasses.floatType()) { + llvmClassTypeDeclarations.add(LLVMTypeFactory.double64()); + } else if (classDecl == CoreClasses.charType()) { + llvmClassTypeDeclarations.add(LLVMTypeFactory.int8()); + } + + for (ClassDeclaration classDeclaration : recursiveSuperClassDeclarations) { + for (Declaration decl : classDeclaration.getBlock().getDeclarations()) { + if (decl instanceof VariableDeclaration) { + llvmClassTypeDeclarations.add(mapToLLVMType(((VariableDeclaration) decl).getType())); + } + } + } + for (ProcedureDeclaration procedure : classDecl.getVirtualMethodTable()) { + if (!procedure.isInitializer()) { + LLVMType signature = mapToLLVMType(procedure); + llvmVMTTypeDeclarations.add(signature); + llvmVMTDataInitializer.add(llvmIdentifierFactory.newGlobal( + procedure.getMangledIdentifier().getSymbol(), + signature)); + } + } + constantContext.type(llvmVMTType, llvmVMTTypeDeclarations); + constantContext.type(llvmClassType, llvmClassTypeDeclarations); + constantContext.global( + Linkage.priv, + llvmCTDataIdentifier, + true, + llvmIdentifierFactory.constant(llvmCTDataType, llvmCTDataInitializer)); + constantContext.global( + Linkage.priv, + llvmVMTDataIdentifier, + true, + llvmIdentifierFactory.constant(llvmVMTType, llvmVMTDataInitializer)); + } + + private void addArray(TypeDeclaration typeDecl) { + // Temporary until object or generic + LLVMType llvmType = mapToLLVMType((TypeDeclaration) CoreClasses.intType()); + List list = Arrays.asList(int64(), array(llvmType, 0)); + LLVMStructType type = struct(typeDecl.getMangledIdentifier().getSymbol()); + constantContext.type(type, list); + } + + public LLVMPointer mapToLLVMType(ClassDeclaration type) { + return (LLVMPointer) mapToLLVMType((TypeDeclaration) type); + } + + public LLVMPointer mapToLLVMType(ProcedureDeclaration type) { + return (LLVMPointer) mapToLLVMType((TypeDeclaration) type); + } + + public T mapToLLVMType(TypeDeclaration type) { + T llvmType = (T) typeMap.get(type); + if (llvmType == null) { + llvmType = convertType(type); + typeMap.put(type, llvmType); + addType(type); + } + return llvmType; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/codegeneration/voodoo/BlackMagic.java b/src/main/java/de/uni/bremen/monty/moco/codegeneration/voodoo/BlackMagic.java new file mode 100644 index 0000000..a4abf65 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/codegeneration/voodoo/BlackMagic.java @@ -0,0 +1,93 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ + +package de.uni.bremen.monty.moco.codegeneration.voodoo; + +import de.uni.bremen.monty.moco.codegeneration.Native; +import de.uni.bremen.monty.moco.codegeneration.context.CodeContext; +import de.uni.bremen.monty.moco.codegeneration.context.Operations; +import de.uni.bremen.monty.moco.codegeneration.identifier.LLVMIdentifier; +import de.uni.bremen.monty.moco.codegeneration.types.LLVMType; +import de.uni.bremen.monty.moco.exception.NotYetImplementedException; +import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class BlackMagic { + private Operations operations; + + public BlackMagic(Operations operations) { + this.operations = operations; + } + + public LLVMIdentifier generateNativeFunction(CodeContext c, String symbol, List> arguments) { + Method[] methods = Operations.class.getMethods(); + for (Method method : methods) { + if (correctMethod(method, symbol)) { + try { + return (LLVMIdentifier) method.invoke(operations, mergeArguments(c, arguments)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + throw new NotYetImplementedException("\"" + symbol + "\" is not defined yet"); + } + + private Object[] mergeArguments(CodeContext c, List> arguments) { + ArrayList mergedArgs = new ArrayList(); + mergedArgs.add(c); + mergedArgs.addAll(arguments); + return mergedArgs.toArray(); + } + + private boolean correctMethod(Method method, String symbol) { + Native nativeAnnotation = method.getAnnotation(Native.class); + if (nativeAnnotation != null) { + boolean isOperation = nativeAnnotation.value().equals(symbol); + boolean otherNativeFunction = nativeAnnotation.value().equals(symbol); + + return otherNativeFunction || isOperation; + } + return false; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/exception/InvalidControlFlowException.java b/src/main/java/de/uni/bremen/monty/moco/exception/InvalidControlFlowException.java new file mode 100644 index 0000000..0beaa4a --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/exception/InvalidControlFlowException.java @@ -0,0 +1,47 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.exception; + +import de.uni.bremen.monty.moco.ast.ASTNode; + +public class InvalidControlFlowException extends MontyBaseException { + public InvalidControlFlowException(ASTNode node, String message) { + super(node, message); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/exception/InvalidExpressionException.java b/src/main/java/de/uni/bremen/monty/moco/exception/InvalidExpressionException.java new file mode 100644 index 0000000..13066be --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/exception/InvalidExpressionException.java @@ -0,0 +1,47 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.exception; + +import de.uni.bremen.monty.moco.ast.ASTNode; + +public class InvalidExpressionException extends MontyBaseException { + public InvalidExpressionException(ASTNode node, String message) { + super(node, message); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/exception/InvalidPlaceToDeclareException.java b/src/main/java/de/uni/bremen/monty/moco/exception/InvalidPlaceToDeclareException.java new file mode 100644 index 0000000..8badd49 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/exception/InvalidPlaceToDeclareException.java @@ -0,0 +1,47 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.exception; + +import de.uni.bremen.monty.moco.ast.ASTNode; + +public class InvalidPlaceToDeclareException extends MontyBaseException { + public InvalidPlaceToDeclareException(ASTNode node, String message) { + super(node, message); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/exception/MontyBaseException.java b/src/main/java/de/uni/bremen/monty/moco/exception/MontyBaseException.java new file mode 100644 index 0000000..e7b89ad --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/exception/MontyBaseException.java @@ -0,0 +1,59 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ + +package de.uni.bremen.monty.moco.exception; + +import de.uni.bremen.monty.moco.ast.ASTNode; + +public class MontyBaseException extends RuntimeException { + protected ASTNode node; + + public MontyBaseException(String message) { + super(message); + } + + public MontyBaseException(ASTNode node, String message) { + super(message); + this.node = node; + } + + public ASTNode getNode() { + return node; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/exception/NotYetImplementedException.java b/src/main/java/de/uni/bremen/monty/moco/exception/NotYetImplementedException.java new file mode 100644 index 0000000..430e353 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/exception/NotYetImplementedException.java @@ -0,0 +1,49 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.exception; + +public class NotYetImplementedException extends RuntimeException { + + public NotYetImplementedException() { + } + + public NotYetImplementedException(String message) { + super(message); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/exception/RedeclarationException.java b/src/main/java/de/uni/bremen/monty/moco/exception/RedeclarationException.java new file mode 100644 index 0000000..5d73586 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/exception/RedeclarationException.java @@ -0,0 +1,47 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.exception; + +import de.uni.bremen.monty.moco.ast.ASTNode; + +public class RedeclarationException extends MontyBaseException { + public RedeclarationException(ASTNode node, String message) { + super(node, message); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/exception/TypeMismatchException.java b/src/main/java/de/uni/bremen/monty/moco/exception/TypeMismatchException.java new file mode 100644 index 0000000..dbee276 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/exception/TypeMismatchException.java @@ -0,0 +1,47 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.exception; + +import de.uni.bremen.monty.moco.ast.ASTNode; + +public class TypeMismatchException extends MontyBaseException { + public TypeMismatchException(ASTNode node, String message) { + super(node, message); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/exception/UnknownIdentifierException.java b/src/main/java/de/uni/bremen/monty/moco/exception/UnknownIdentifierException.java new file mode 100644 index 0000000..d6f9fc4 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/exception/UnknownIdentifierException.java @@ -0,0 +1,48 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.exception; + +import de.uni.bremen.monty.moco.ast.ResolvableIdentifier; + +public class UnknownIdentifierException extends MontyBaseException { + + public UnknownIdentifierException(ResolvableIdentifier identifier) { + super("Identifier is not defined: " + identifier); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/exception/UnknownTypeException.java b/src/main/java/de/uni/bremen/monty/moco/exception/UnknownTypeException.java new file mode 100644 index 0000000..2cb3278 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/exception/UnknownTypeException.java @@ -0,0 +1,48 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.exception; + +import de.uni.bremen.monty.moco.ast.ResolvableIdentifier; + +public class UnknownTypeException extends MontyBaseException { + + public UnknownTypeException(ResolvableIdentifier identifier) { + super("Type is not defined: " + identifier); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/util/MontyFile.java b/src/main/java/de/uni/bremen/monty/moco/util/MontyFile.java new file mode 100644 index 0000000..a66585f --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/util/MontyFile.java @@ -0,0 +1,87 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ + +package de.uni.bremen.monty.moco.util; + +import org.apache.commons.io.filefilter.DirectoryFileFilter; +import org.apache.commons.io.filefilter.SuffixFileFilter; + +import java.io.*; +import java.net.URI; +import java.util.Arrays; + +public class MontyFile extends File implements MontyResource { + + public MontyFile(URI uri) { + super(uri); + } + + @Override + public MontyResource[] listSubPackages() { + File[] files = listFiles((FileFilter) DirectoryFileFilter.DIRECTORY); + MontyResource[] montyResources = convertAllFiles(files); + Arrays.sort(montyResources); + return montyResources; + } + + private MontyResource[] convertAllFiles(File[] files) { + MontyResource[] resources = new MontyResource[files.length]; + for (int i = 0; i < files.length; i++) { + resources[i] = new MontyFile(files[i].toURI()); + } + return resources; + } + + @Override + public InputStream toInputStream() throws FileNotFoundException { + return new FileInputStream(this); + } + + @Override + public MontyResource[] listSubModules() { + MontyResource[] montyResources = convertAllFiles(listFiles((FilenameFilter) new SuffixFileFilter(".monty"))); + Arrays.sort(montyResources); + return montyResources; + } + + public MontyFile(String pathname) { + super(pathname); + } + +} diff --git a/src/main/java/de/uni/bremen/monty/moco/util/MontyJar.java b/src/main/java/de/uni/bremen/monty/moco/util/MontyJar.java new file mode 100644 index 0000000..456d4e5 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/util/MontyJar.java @@ -0,0 +1,126 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ + +package de.uni.bremen.monty.moco.util; + +import org.apache.commons.lang3.StringUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.net.JarURLConnection; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Enumeration; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +public class MontyJar implements MontyResource { + + private final JarFile jarFile; + private final JarEntry jarEntry; + private final static Comparator comparator = createComparator(); + + public MontyJar(URL url) throws IOException { + JarURLConnection urlConnection = (JarURLConnection) url.openConnection(); + jarFile = urlConnection.getJarFile(); + jarEntry = urlConnection.getJarEntry(); + } + + public MontyJar(JarFile jarFile, JarEntry jarEntry) { + this.jarFile = jarFile; + this.jarEntry = jarEntry; + } + + @Override + public MontyResource[] listSubPackages() { + return getSubResources(true); + } + + @Override + public InputStream toInputStream() throws IOException { + return jarFile.getInputStream(jarEntry); + } + + @Override + public String getName() { + return jarEntry.getName(); + } + + @Override + public MontyResource[] listSubModules() throws IOException { + return getSubResources(false); + } + + private MontyResource[] getSubResources(boolean showFiles) { + ArrayList list = new ArrayList<>(); + + Enumeration entries = jarFile.entries(); + while (entries.hasMoreElements()) { + JarEntry x = entries.nextElement(); + + if (x.getName().startsWith(jarEntry.getName())) { + String substring = x.getName().substring(jarEntry.getName().length()); + + if (!substring.equals("")) { + if (showFiles == substring.contains("/")) { + if (!showFiles || StringUtils.countMatches(substring, "/") == 1 + && substring.indexOf("/") == substring.length() - 1) { + list.add(new MontyJar(jarFile, x)); + } + } + } + + } + } + MontyResource[] montyResources = list.toArray(new MontyResource[list.size()]); + Arrays.sort(montyResources, comparator); + return montyResources; + } + + private static Comparator createComparator() { + return new Comparator() { + @Override + public int compare(MontyResource o1, MontyResource o2) { + return o1.getName().compareTo(o2.getName()); + } + }; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/util/MontyResource.java b/src/main/java/de/uni/bremen/monty/moco/util/MontyResource.java new file mode 100644 index 0000000..04cddb4 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/util/MontyResource.java @@ -0,0 +1,54 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ + +package de.uni.bremen.monty.moco.util; + +import java.io.IOException; +import java.io.InputStream; + +public interface MontyResource { + + abstract public MontyResource[] listSubPackages(); + + abstract public InputStream toInputStream() throws IOException; + + abstract public String getName(); + + abstract public MontyResource[] listSubModules() throws IOException; +} diff --git a/src/main/java/de/uni/bremen/monty/moco/util/Params.java b/src/main/java/de/uni/bremen/monty/moco/util/Params.java new file mode 100644 index 0000000..c8dc423 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/util/Params.java @@ -0,0 +1,146 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.util; + +import java.io.File; + +public class Params { + private String inputFolder; + private String mainModule; + + private boolean debugParseTree; + private String inputFile; + private String outputFile; + private boolean usePrintVisitor; + private boolean generateOnlyLLVM; + private boolean keepLLVMCode; + private boolean stopOnFirstError; + private String llFile; + + public Params(String[] args) { + if (args.length == 0 || args[0].equals("-h") || args[0].equals("--help")) { + printHelp(); + } + + for (int i = 0; i < args.length; i++) { + String arg = args[i]; + if (arg.equals("-p")) { + usePrintVisitor = true; + } else if (arg.equals("-ll")) { + generateOnlyLLVM = true; + } else if (arg.equals("-o")) { + outputFile = args[++i]; + } else if (arg.equals("-k")) { + keepLLVMCode = true; + } else if (arg.equals("-s")) { + debugParseTree = true; + } else if (arg.equals("-e")) { + stopOnFirstError = true; + } else { + if (new File(args[i]).isDirectory()) { + inputFolder = args[i]; + } else if (inputFolder != null) { + mainModule = args[i]; + } else { + inputFile = args[i]; + } + } + } + + if (inputFile == null && (inputFolder == null || mainModule == null)) { + printHelp(); + } + } + + public String getInputFile() { + return inputFile; + } + + public String getOutputFile() { + return outputFile; + } + + public boolean usePrintVisitor() { + return usePrintVisitor; + } + + public boolean isGenerateOnlyLLVM() { + return generateOnlyLLVM; + } + + public boolean isKeepLLVMCode() { + return keepLLVMCode; + } + + public boolean isStopOnFirstError() { + return stopOnFirstError; + } + + public boolean isDebugParseTree() { + return debugParseTree; + } + + public void printHelp() { + System.out.println("moco [args] inputFile [-o outputFile]"); + System.out.println("execute monty File"); + + System.out.println("-s\tdebug ANTLR parse Tree"); + System.out.println("-p\tprint AST without code generation"); + System.out.println("-ll\tgenerate only LLVM code"); + System.out.println("-k\tkeep LLVM Code"); + System.out.println("-e\tstop on first error"); + System.exit(-1); + } + + public void setLlFile(String llFile) { + this.llFile = llFile; + } + + public String getLlFile() { + return llFile; + } + + public String getInputFolder() { + return inputFolder; + } + + public String getMainModule() { + return mainModule; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/util/ParseTreePrinter.java b/src/main/java/de/uni/bremen/monty/moco/util/ParseTreePrinter.java new file mode 100644 index 0000000..21f58b7 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/util/ParseTreePrinter.java @@ -0,0 +1,127 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.util; + +import org.antlr.v4.runtime.Parser; +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.misc.Utils; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTreeListener; +import org.antlr.v4.runtime.tree.TerminalNode; +import org.antlr.v4.runtime.tree.Trees; + +import java.util.Arrays; +import java.util.List; + +public class ParseTreePrinter implements ParseTreeListener { + private final List ruleNames; + private final StringBuilder builder = new StringBuilder(); + private int intend = 0; + private ParserRuleContext lastOne; + private boolean intended; + + public ParseTreePrinter(Parser parser) { + this.ruleNames = Arrays.asList(parser.getRuleNames()); + } + + @Override + public void visitTerminal(TerminalNode node) { + if (builder.length() > 0) { + builder.append(' '); + } + + append(Utils.escapeWhitespace(Trees.getNodeText(node, ruleNames), false)); + } + + @Override + public void visitErrorNode(ErrorNode node) { + if (builder.length() > 0) { + builder.append(' '); + } + + append(Utils.escapeWhitespace(Trees.getNodeText(node, ruleNames), false)); + } + + @Override + public void enterEveryRule(ParserRuleContext ctx) { + builder.append("\n"); + intended = false; + + if (builder.length() > 0) { + builder.append(' '); + } + + if (!ctx.equals(lastOne)) { + intend++; + } + + int ruleIndex = ctx.getRuleIndex(); + String ruleName; + if (ruleIndex >= 0 && ruleIndex < ruleNames.size()) { + ruleName = ruleNames.get(ruleIndex); + } else { + ruleName = Integer.toString(ruleIndex); + } + + append(ruleName); + lastOne = ctx; + } + + private void append(String ruleName) { + if (!intended) { + for (int i = 0; i < intend; i++) { + builder.append(' '); + } + intended = true; + } + builder.append(ruleName); + } + + @Override + public void exitEveryRule(ParserRuleContext ctx) { + if (ctx.getChildCount() > 0) { + intend--; + } + } + + @Override + public String toString() { + return builder.toString(); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/visitor/BaseVisitor.java b/src/main/java/de/uni/bremen/monty/moco/visitor/BaseVisitor.java new file mode 100644 index 0000000..f393647 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/visitor/BaseVisitor.java @@ -0,0 +1,449 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.visitor; + +import de.uni.bremen.monty.moco.ast.ASTNode; +import de.uni.bremen.monty.moco.ast.Block; +import de.uni.bremen.monty.moco.ast.Import; +import de.uni.bremen.monty.moco.ast.Package; +import de.uni.bremen.monty.moco.ast.declaration.*; +import de.uni.bremen.monty.moco.ast.expression.*; +import de.uni.bremen.monty.moco.ast.expression.literal.*; +import de.uni.bremen.monty.moco.ast.statement.*; +import de.uni.bremen.monty.moco.exception.MontyBaseException; + +/** This is the base-visitor to be subclassed by all visitors. + * + * It implements methods for all node-types that call node.visitChildren() (so the node must implement this method). + * Override if necessary. + * + * If you want to visit a node in the implementation of a visit()-method just use visit(node). */ +public class BaseVisitor { + + /** Count the exceptions caught in visit(ASTNode) **/ + private int errorCounter; + + /** Stop on the first error that is encountered **/ + private boolean stopOnFirstError; + + /** Comfort method to visit a node via double-dispatch. + * + * @param node + * the node to visit */ + public final void visitDoubleDispatched(ASTNode node) { + try { + onEnterEachNode(node); + node.visit(this); + onExitEachNode(node); + } catch (RuntimeException exception) { + errorCounter += 1; + if (stopOnFirstError) { + throw exception; + } else { + logError(exception); + } + } + } + + /** Returns information used in the exceptions that includes the ASTNodes name (optional additional information) and + * (if available) the position. + * + * @return the node information */ + public String getNodeInformation(ASTNode node) { + if (node == null) { + return "null"; + } else if (node.getPosition() != null) { + return String.format("%s at %s", node.toString(), node.getPosition().toString()); + } + return node.toString(); + } + + /** Log an exception. + *

+ * This method logs the exception or prints it if it's not a Monty exception. */ + public void logError(RuntimeException exception) { + if (exception instanceof MontyBaseException) { + MontyBaseException exc = (MontyBaseException) exception; + System.err.println(String.format( + "%s caught error in %s: %s", + getClass().getSimpleName(), + getNodeInformation(exc.getNode()), + exc.getMessage())); + } else { + exception.printStackTrace(); + } + } + + /** Was there an error during the execution of this visitor? + * + * @return true if no error was caught, false otherwise */ + public boolean foundError() { + return errorCounter != 0; + } + + // Declaration + + /** Visitor method to visit a ModuleDeclaration. + * + * @param node + * the node to visit */ + public void visit(ModuleDeclaration node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + /** Visitor method to visit a ClassDeclaration. + * + * @param node + * the node to visit */ + public void visit(ClassDeclaration node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + /** Visitor method to visit a FunctionDeclaration. + * + * @param node + * the node to visit */ + public void visit(FunctionDeclaration node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + /** Visitor method to visit a ProcedureDeclaration. + * + * @param node + * the node to visit */ + public void visit(ProcedureDeclaration node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + /** Visitor method to visit a VariableDeclaration. + * + * @param node + * the node to visit */ + public void visit(VariableDeclaration node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + // Expression + + /** Visitor method to visit a ConditionalExpression. + * + * @param node + * the node to visit */ + public void visit(ConditionalExpression node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + /** Visitor method to visit a SelfExpression. + * + * @param node + * the node to visit */ + public void visit(SelfExpression node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + /** Visitor method to visit a ParentExpression. + * + * @param node + * the node to visit */ + public void visit(ParentExpression node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + /** Visitor method to visit a CastExpression. + * + * @param node + * the node to visit */ + public void visit(CastExpression node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + /** Visitor method to visit a IsExpression. + * + * @param node + * the node to visit */ + public void visit(IsExpression node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + /** Visitor method to visit a FunctionCall. + * + * @param node + * the node to visit */ + public void visit(FunctionCall node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + /** Visitor method to visit a MemberAccess. + * + * @param node + * the node to visit */ + public void visit(MemberAccess node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + /** Visitor method to visit a VariableAccess. + * + * @param node + * the node to visit */ + public void visit(VariableAccess node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + // Literal + + /** Visitor method to visit a BooleanLiteral. + * + * @param node + * the node to visit */ + public void visit(BooleanLiteral node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + /** Visitor method to visit a FloatLiteral. + * + * @param node + * the node to visit */ + public void visit(FloatLiteral node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + /** Visitor method to visit a IntegerLiteral. + * + * @param node + * the node to visit */ + public void visit(IntegerLiteral node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + /** Visitor method to visit a StringLiteral. + * + * @param node + * the node to visit */ + public void visit(StringLiteral node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + /** Visitor method to visit a ArrayLiteral. + * + * @param node + * the node to visit */ + public void visit(ArrayLiteral node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + /** Visitor method to visit a CharacterLiteral. + * + * @param node + * the node to visit */ + public void visit(CharacterLiteral node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + // Statements + + /** Visitor method to visit a Assignment. + * + * @param node + * the node to visit */ + public void visit(Assignment node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + /** Visitor method to visit a BreakStatement. + * + * @param node + * the node to visit */ + public void visit(BreakStatement node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + /** Visitor method to visit a SkipStatement. + * + * @param node + * the node to visit */ + public void visit(SkipStatement node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + /** Visitor method to visit a ConditionalStatement. + * + * @param node + * the node to visit */ + public void visit(ConditionalStatement node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + /** Visitor method to visit a ContinueStatement. + * + * @param node + * the node to visit */ + public void visit(ContinueStatement node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + /** Visitor method to visit a ReturnStatement. + * + * @param node + * the node to visit */ + public void visit(ReturnStatement node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + /** Visitor method to visit a WhileLoop. + * + * @param node + * the node to visit */ + public void visit(WhileLoop node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + /** Visitor method to visit a TryStatement. + * + * @param node + * the node to visit */ + public void visit(TryStatement node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + // Other + + /** Visitor method to visit a Block. + * + * @param node + * the node to visit */ + public void visit(Block node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + /** Visitor method to visit a Package. + * + * @param node + * the node to visit */ + public void visit(Package node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + /** Visitor method to visit a Import. + * + * @param node + * the node to visit */ + public void visit(Import node) { + onEnterChildrenEachNode(node); + node.visitChildren(this); + onExitChildrenEachNode(node); + } + + protected void onEnterEachNode(ASTNode node) { + + } + + protected void onExitEachNode(ASTNode node) { + + } + + protected void onEnterChildrenEachNode(ASTNode node) { + + } + + protected void onExitChildrenEachNode(ASTNode node) { + + } + + public void setStopOnFirstError(boolean stopOnFirstError) { + this.stopOnFirstError = stopOnFirstError; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/visitor/CodeGenerationVisitor.java b/src/main/java/de/uni/bremen/monty/moco/visitor/CodeGenerationVisitor.java new file mode 100644 index 0000000..a957fc8 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/visitor/CodeGenerationVisitor.java @@ -0,0 +1,643 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.visitor; + +import de.uni.bremen.monty.moco.ast.ASTNode; +import de.uni.bremen.monty.moco.ast.Block; +import de.uni.bremen.monty.moco.ast.CoreClasses; +import de.uni.bremen.monty.moco.ast.Package; +import de.uni.bremen.monty.moco.ast.declaration.*; +import de.uni.bremen.monty.moco.ast.expression.*; +import de.uni.bremen.monty.moco.ast.expression.literal.*; +import de.uni.bremen.monty.moco.ast.statement.*; +import de.uni.bremen.monty.moco.codegeneration.CodeGenerator; +import de.uni.bremen.monty.moco.codegeneration.CodeWriter; +import de.uni.bremen.monty.moco.codegeneration.context.CodeContext; +import de.uni.bremen.monty.moco.codegeneration.context.ContextUtils; +import de.uni.bremen.monty.moco.codegeneration.identifier.LLVMIdentifier; +import de.uni.bremen.monty.moco.codegeneration.identifier.LLVMIdentifierFactory; +import de.uni.bremen.monty.moco.codegeneration.types.LLVMStructType; +import de.uni.bremen.monty.moco.codegeneration.types.LLVMType; +import de.uni.bremen.monty.moco.codegeneration.types.LLVMPointer; +import de.uni.bremen.monty.moco.codegeneration.types.LLVMTypeFactory; +import de.uni.bremen.monty.moco.codegeneration.types.TypeConverter; +import de.uni.bremen.monty.moco.util.Params; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Stack; + +import static de.uni.bremen.monty.moco.codegeneration.types.LLVMTypeFactory.pointer; + +/** The CodeGenerationVisitor has the following tasks: + * + *

+ *

    + *
  • Process the AST
  • + *
  • Delegates as much work as possible to the CodeGenerator
  • + *
  • Tell the CodeGenerator in which {@link CodeContext} to write
  • + *
  • Evaluated expression should be given Statements as Arguments, see {@link #stack}
  • + *
+ *

*/ +public class CodeGenerationVisitor extends BaseVisitor { + + private final LLVMIdentifierFactory llvmIdentifierFactory = new LLVMIdentifierFactory(); + private ContextUtils contextUtils = new ContextUtils(); + private final CodeGenerator codeGenerator; + private final CodeWriter codeWriter; + + /** Each Expression pushes it's evaluated value onto the Stack. The value is represented by a LLVMIdentifier where + * the evaluated value is stored at runtime. + * + * Statements or complex Expressions can pop those values from the stack, which they use as parameters for further + * calculation. + * + * e.g. a := 3 is an Assignment having a VariableAccess and IntLiteral as children. VariableAccess and IntLiteral + * are expressions, thus pushing their values on the stack. An Assignment on the other hand is an Statement and + * return nothing, so doesn't push sth. on the stack, but instead it needs two Arguments. Those are popped from the + * Stack and yield the the evaluated VariableAccess and IntLiteral. + * + * Of course this only works, if the Assignment first process the children and afterwards popping from the stack. */ + private Stack> stack = new Stack<>(); + + /** Only Expressions push to a Stack. So this is a Stack of Stacks so every Statement has its own stack. + * + * e.g. the FunctionCall as a statement would leave behind a non-empty stack. */ + private Stack>> stackOfStacks = new Stack<>(); + + public CodeGenerationVisitor(Params params) throws IOException { + TypeConverter typeConverter = new TypeConverter(llvmIdentifierFactory, contextUtils.constant()); + this.codeWriter = new CodeWriter(params); + this.codeGenerator = new CodeGenerator(typeConverter, llvmIdentifierFactory); + } + + private void openNewFunctionScope() { + contextUtils.addNewContext(); + llvmIdentifierFactory.openScope(); + } + + private void closeFunctionContext() { + contextUtils.active().close(); + contextUtils.closeContext(); + llvmIdentifierFactory.closeScope(); + } + + private List> buildLLVMParameter(ProcedureDeclaration node) { + List> llvmParameter = new ArrayList<>(); + + if (node.isMethod() || node.isInitializer()) { + LLVMType selfType = codeGenerator.mapToLLVMType(node.getDefiningClass()); + LLVMIdentifier selfReference = llvmIdentifierFactory.newLocal("self", selfType, false); + llvmParameter.add(selfReference); + } + + for (VariableDeclaration param : node.getParameter()) { + LLVMType llvmType = codeGenerator.mapToLLVMType(param.getType()); + llvmType = llvmType instanceof LLVMStructType ? pointer(llvmType) : llvmType; + boolean resolvable = llvmType instanceof LLVMStructType; + LLVMIdentifier e = + llvmIdentifierFactory.newLocal(param.getMangledIdentifier().getSymbol(), llvmType, resolvable); + + llvmParameter.add(e); + } + return llvmParameter; + } + + private void addFunction(ProcedureDeclaration node, TypeDeclaration returnType) { + List> llvmParameter = buildLLVMParameter(node); + String name = node.getMangledIdentifier().getSymbol(); + codeGenerator.addFunction(contextUtils.active(), returnType, llvmParameter, name); + } + + private void addNativeFunction(ProcedureDeclaration node, TypeDeclaration returnType) { + List> llvmParameter = buildLLVMParameter(node); + String name = node.getMangledIdentifier().getSymbol(); + codeGenerator.addNativeFunction(contextUtils.active(), returnType, llvmParameter, name); + } + + private boolean isNative(ASTNode node) { + while (node.getParentNode() != null) { + node = node.getParentNode(); + if (node instanceof Package) { + if (((Package) node).isNativePackage()) { + return true; + } + } + } + return false; + } + + protected void writeData() throws IOException { + codeWriter.write(contextUtils.getData()); + } + + @Override + protected void onEnterEachNode(ASTNode node) { + contextUtils.setNode(node); + } + + @Override + protected void onExitChildrenEachNode(ASTNode node) { + contextUtils.setNode(node); + } + + @Override + public void visit(Package node) { + contextUtils.setNode(node); + if (node.getParentNode() == null) { + openNewFunctionScope(); + codeGenerator.addMain(contextUtils.active()); + + super.visit(node); + + codeGenerator.returnMain(contextUtils.active()); + closeFunctionContext(); + + try { + writeData(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } else { + super.visit(node); + } + } + + @Override + public void visit(Block node) { + for (Declaration declaration : node.getDeclarations()) { + visitDoubleDispatched(declaration); + } + for (Statement statement : node.getStatements()) { + stackOfStacks.push(stack); + stack = new Stack<>(); + visitDoubleDispatched(statement); + stack = stackOfStacks.pop(); + } + } + + @Override + public void visit(Assignment node) { + super.visit(node); + LLVMIdentifier source = stack.pop(); + LLVMIdentifier target = stack.pop(); + codeGenerator.assign(contextUtils.active(), target, source); + } + + @Override + public void visit(ClassDeclaration node) { + // These are not boxed yet. So they cant inherit from object and cant have initializers. + List treatSpecial = + Arrays.asList(CoreClasses.stringType(), CoreClasses.arrayType(), CoreClasses.voidType()); + if (!treatSpecial.contains(node)) { + openNewFunctionScope(); + codeGenerator.buildConstructor(contextUtils.active(), node); + closeFunctionContext(); + } + super.visit(node); + } + + @Override + public void visit(VariableDeclaration node) { + super.visit(node); + if (!node.isAttribute()) { + if (node.getIsGlobal()) { + codeGenerator.declareGlobalVariable( + contextUtils.constant(), + node.getMangledIdentifier().getSymbol(), + node.getType()); + } else { + codeGenerator.declareLocalVariable( + contextUtils.active(), + node.getMangledIdentifier().getSymbol(), + node.getType()); + } + } + } + + @Override + public void visit(VariableAccess node) { + super.visit(node); + + VariableDeclaration varDeclaration = (VariableDeclaration) node.getDeclaration(); + + LLVMIdentifier llvmIdentifier; + if (varDeclaration.getIsGlobal()) { + llvmIdentifier = + codeGenerator.resolveGlobalVarName(node.getMangledIdentifier().getSymbol(), node.getType()); + } else if (varDeclaration.isAttribute()) { + LLVMIdentifier leftIdentifier = stack.pop(); + llvmIdentifier = + codeGenerator.accessMember( + contextUtils.active(), + (LLVMIdentifier>) leftIdentifier, + varDeclaration.getAttributeIndex(), + node.getType(), + !node.getLValue()); + } else { + llvmIdentifier = + codeGenerator.resolveLocalVarName( + node.getMangledIdentifier().getSymbol(), + node.getType(), + !varDeclaration.isParameter()); + } + stack.push(llvmIdentifier); + } + + @SuppressWarnings("unchecked") + @Override + public void visit(SelfExpression node) { + stack.push(codeGenerator.resolveLocalVarName("self", node.getType(), false)); + } + + @SuppressWarnings("unchecked") + @Override + public void visit(ParentExpression node) { + LLVMIdentifier self = codeGenerator.resolveLocalVarName("self", node.getSelfType(), false); + LLVMIdentifier result = + codeGenerator.castClass( + contextUtils.active(), + (LLVMIdentifier>) self, + node.getSelfType(), + (ClassDeclaration) node.getType(), + codeGenerator.createLabelPrefix("cast", node)); + stack.push((LLVMIdentifier) result); + } + + /** {@inheritDoc} */ + @Override + public void visit(CastExpression node) { + super.visit(node); + LLVMIdentifier object = stack.pop(); + LLVMIdentifier result = + codeGenerator.castClass( + contextUtils.active(), + (LLVMIdentifier>) object, + (ClassDeclaration) node.getExpression().getType(), + (ClassDeclaration) node.getType(), + codeGenerator.createLabelPrefix("cast", node)); + stack.push((LLVMIdentifier) result); + } + + /** {@inheritDoc} */ + @Override + public void visit(IsExpression node) { + super.visit(node); + LLVMIdentifier object = stack.pop(); + LLVMIdentifier result = + codeGenerator.isClass( + contextUtils.active(), + (LLVMIdentifier>) object, + (ClassDeclaration) node.getExpression().getType(), + (ClassDeclaration) node.getToType()); + LLVMIdentifier boxedResult = + codeGenerator.boxType(contextUtils.active(), (LLVMIdentifier) result, CoreClasses.boolType()); + stack.push(boxedResult); + } + + @Override + public void visit(MemberAccess node) { + super.visit(node); + // If right is VariableAccess, everything is done in visit(VariableAccess) + // If right is FunctionCall, everything is done in visit(FunctionCall) + } + + @SuppressWarnings("unchecked") + @Override + public void visit(StringLiteral node) { + super.visit(node); + + LLVMIdentifier addr = + codeGenerator.addConstantString(contextUtils.constant(), node.getValue()); + stack.push((LLVMIdentifier) addr); + } + + @SuppressWarnings("unchecked") + @Override + public void visit(CharacterLiteral node) { + super.visit(node); + LLVMIdentifier addr = codeGenerator.loadChar(node.getValue()); + // Boxing + CodeContext c = contextUtils.active(); + LLVMIdentifier box = codeGenerator.boxType(c, (LLVMIdentifier) addr, node.getType()); + stack.push(box); + } + + @SuppressWarnings("unchecked") + @Override + public void visit(IntegerLiteral node) { + super.visit(node); + + LLVMIdentifier addr = codeGenerator.loadInt(node.getValue()); + // Boxing + CodeContext c = contextUtils.active(); + LLVMIdentifier box = codeGenerator.boxType(c, (LLVMIdentifier) addr, node.getType()); + stack.push(box); + } + + @SuppressWarnings("unchecked") + @Override + public void visit(BooleanLiteral node) { + super.visit(node); + + LLVMIdentifier addr = codeGenerator.loadBool(node.getValue()); + // Boxing + CodeContext c = contextUtils.active(); + LLVMIdentifier box = codeGenerator.boxType(c, (LLVMIdentifier) addr, node.getType()); + stack.push(box); + } + + @SuppressWarnings("unchecked") + @Override + public void visit(FloatLiteral node) { + super.visit(node); + + LLVMIdentifier addr = codeGenerator.loadFloat(node.getValue()); + // Boxing + CodeContext c = contextUtils.active(); + LLVMIdentifier box = codeGenerator.boxType(c, (LLVMIdentifier) addr, node.getType()); + stack.push(box); + } + + @Override + public void visit(ArrayLiteral node) { + super.visit(node); + + ClassDeclaration type = (ClassDeclaration) node.getType(); + LLVMIdentifier> array = + codeGenerator.addArray(contextUtils.active(), node.getEntries().size(), type); + for (int i = node.getEntries().size() - 1; i >= 0; i--) { + codeGenerator.setArrayElement(contextUtils.active(), array, i, stack.pop()); + } + + stack.push((LLVMIdentifier) array); + } + + @Override + public void visit(ConditionalExpression node) { + + String ifPre = codeGenerator.createLabelPrefix("ifexpr", node); + String ifTrue = ifPre + ".true"; + String ifFalse = ifPre + ".false"; + String ifEnd = ifPre + ".end"; + + visitDoubleDispatched(node.getCondition()); + + LLVMIdentifier condition = stack.pop(); + codeGenerator.branch(contextUtils.active(), condition, ifTrue, ifFalse); + + contextUtils.active().label(ifTrue); + visitDoubleDispatched(node.getThenExpression()); + LLVMIdentifier thenExpr = stack.pop(); + contextUtils.active().branch(ifEnd); + + contextUtils.active().label(ifFalse); + visitDoubleDispatched(node.getElseExpression()); + LLVMIdentifier elseExpr = stack.pop(); + contextUtils.active().branch(ifEnd); + + contextUtils.active().label(ifEnd); + List> identifiers = new ArrayList<>(); + identifiers.add(thenExpr); + identifiers.add(elseExpr); + List labels = new ArrayList<>(); + labels.add(ifTrue); + labels.add(ifFalse); + stack.push(contextUtils.active().phi( + thenExpr.getType(), + thenExpr.needToBeResolved(), + identifiers, + llvmIdentifierFactory.newLocal(thenExpr.getType(), thenExpr.needToBeResolved()), + labels)); + } + + @SuppressWarnings("unchecked") + @Override + public void visit(FunctionCall node) { + super.visit(node); + + List expectedParameters = new ArrayList<>(); + for (VariableDeclaration varDeclaration : node.getDeclaration().getParameter()) { + expectedParameters.add(varDeclaration.getType()); + } + List> arguments = new ArrayList<>(node.getArguments().size()); + for (int i = 0; i < node.getArguments().size(); i++) { + arguments.add(stack.pop()); + } + Collections.reverse(arguments); + + ProcedureDeclaration declaration = node.getDeclaration(); + ClassDeclaration definingClass = declaration.getDefiningClass(); + + List treatSpecial = + Arrays.asList( + CoreClasses.intType(), + CoreClasses.boolType(), + CoreClasses.floatType(), + CoreClasses.charType()); + if (declaration.isInitializer() && treatSpecial.contains(definingClass)) { + // Instead of calling the initializer of this boxed type with a boxed value as arguments just push the + // argument on the stack and return. + stack.push((LLVMIdentifier) arguments.get(0)); + return; + } + + if (declaration.isMethod() || declaration.isInitializer()) { + expectedParameters.add(0, definingClass); + if (declaration.isMethod() + || (declaration.isInitializer() && (node.getParentNode() instanceof MemberAccess))) { + arguments.add(0, stack.pop()); + } else if (declaration.isInitializer()) { + LLVMIdentifier selfReference = + codeGenerator.callConstructor(contextUtils.active(), definingClass); + codeGenerator.callVoid( + contextUtils.active(), + definingClass.getDefaultInitializer().getMangledIdentifier().getSymbol(), + Arrays.> asList(selfReference), + Arrays. asList(definingClass)); + arguments.add(0, selfReference); + } + } + + if (declaration.isMethod() && !declaration.isInitializer()) { + if (declaration instanceof FunctionDeclaration) { + stack.push((LLVMIdentifier) codeGenerator.callMethod( + contextUtils.active(), + (FunctionDeclaration) declaration, + arguments, + expectedParameters)); + } else { + codeGenerator.callVoidMethod(contextUtils.active(), declaration, arguments, expectedParameters); + } + } else { + if (declaration instanceof FunctionDeclaration) { + stack.push((LLVMIdentifier) codeGenerator.call( + contextUtils.active(), + declaration.getMangledIdentifier().getSymbol(), + node.getType(), + arguments, + expectedParameters)); + } else { + if (declaration.isInitializer()) { + stack.push((LLVMIdentifier) arguments.get(0)); + } + codeGenerator.callVoid( + contextUtils.active(), + declaration.getMangledIdentifier().getSymbol(), + arguments, + expectedParameters); + } + } + } + + @Override + public void visit(FunctionDeclaration node) { + openNewFunctionScope(); + if (isNative(node)) { + addNativeFunction(node, node.getReturnType()); + } else { + addFunction(node, node.getReturnType()); + visitDoubleDispatched(node.getBody()); + } + closeFunctionContext(); + } + + @Override + public void visit(ProcedureDeclaration node) { + openNewFunctionScope(); + + if (isNative(node) && !node.isInitializer()) { + addNativeFunction(node, CoreClasses.voidType()); + } else { + addFunction(node, CoreClasses.voidType()); + + visitDoubleDispatched(node.getBody()); + if (node.isInitializer()) { + codeGenerator.returnValue( + contextUtils.active(), + (LLVMIdentifier) (LLVMIdentifier) llvmIdentifierFactory.voidId(), + CoreClasses.voidType()); + } + } + closeFunctionContext(); + } + + @Override + public void visit(ReturnStatement node) { + super.visit(node); + if (node.getParameter() != null) { + ASTNode parent = node; + while (!(parent instanceof FunctionDeclaration)) { + parent = parent.getParentNode(); + } + LLVMIdentifier returnValue = stack.pop(); + codeGenerator.returnValue( + contextUtils.active(), + returnValue, + ((FunctionDeclaration) parent).getReturnType()); + } else { + codeGenerator.returnValue( + contextUtils.active(), + (LLVMIdentifier) (LLVMIdentifier) llvmIdentifierFactory.voidId(), + CoreClasses.voidType()); + } + } + + @Override + public void visit(ConditionalStatement node) { + visitDoubleDispatched(node.getCondition()); + + String ifPre = codeGenerator.createLabelPrefix("if", node); + + String ifTrue = ifPre + ".true"; + String ifFalse = ifPre + ".false"; + String ifEnd = ifPre + ".end"; + + LLVMIdentifier condition = stack.pop(); + codeGenerator.branch(contextUtils.active(), condition, ifTrue, ifFalse); + + contextUtils.active().label(ifTrue); + visitDoubleDispatched(node.getThenBlock()); + contextUtils.active().branch(ifEnd); + + contextUtils.active().label(ifFalse); + visitDoubleDispatched(node.getElseBlock()); + contextUtils.active().branch(ifEnd); + + contextUtils.active().label(ifEnd); + } + + @Override + public void visit(WhileLoop node) { + + String whlPre = codeGenerator.createLabelPrefix("while", node); + String whileCond = whlPre + ".condition"; + String whileBlk = whlPre + ".block"; + String whileEnd = whlPre + ".end"; + + contextUtils.active().branch(whileCond); + contextUtils.active().label(whileCond); + visitDoubleDispatched(node.getCondition()); + + LLVMIdentifier condition = stack.pop(); + codeGenerator.branch(contextUtils.active(), condition, whileBlk, whileEnd); + + contextUtils.active().label(whileBlk); + visitDoubleDispatched(node.getBody()); + contextUtils.active().branch(whileCond); + contextUtils.active().label(whileEnd); + } + + @Override + public void visit(SkipStatement node) { + super.visit(node); + String whlPre = codeGenerator.getLabelPrefix(node.getLoop()); + contextUtils.active().branch(whlPre + ".condition"); + } + + @Override + public void visit(BreakStatement node) { + super.visit(node); + String whlPre = codeGenerator.getLabelPrefix(node.getLoop()); + contextUtils.active().branch(whlPre + ".end"); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/visitor/ControlFlowVisitor.java b/src/main/java/de/uni/bremen/monty/moco/visitor/ControlFlowVisitor.java new file mode 100644 index 0000000..8b3d3d4 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/visitor/ControlFlowVisitor.java @@ -0,0 +1,168 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.visitor; + +import de.uni.bremen.monty.moco.ast.ASTNode; +import de.uni.bremen.monty.moco.ast.Block; +import de.uni.bremen.monty.moco.ast.Package; +import de.uni.bremen.monty.moco.ast.declaration.Declaration; +import de.uni.bremen.monty.moco.ast.declaration.FunctionDeclaration; +import de.uni.bremen.monty.moco.ast.declaration.ProcedureDeclaration; +import de.uni.bremen.monty.moco.ast.statement.BreakStatement; +import de.uni.bremen.monty.moco.ast.statement.ConditionalStatement; +import de.uni.bremen.monty.moco.ast.statement.ContinueStatement; +import de.uni.bremen.monty.moco.ast.statement.ReturnStatement; +import de.uni.bremen.monty.moco.ast.statement.SkipStatement; +import de.uni.bremen.monty.moco.ast.statement.Statement; +import de.uni.bremen.monty.moco.ast.statement.WhileLoop; +import de.uni.bremen.monty.moco.exception.InvalidControlFlowException; + +/** This visitor must traverse the entire AST to validate the intended AST-structure. */ +public class ControlFlowVisitor extends BaseVisitor { + + /** Set to `true` if the current statement-list needs to contain a ReturnStatement */ + private boolean needsReturnStatement; + + @Override + public void visit(Package node) { + if (!node.isNativePackage()) { + super.visit(node); + } + } + + /** {@inheritDoc} */ + @Override + public void visit(FunctionDeclaration node) { + needsReturnStatement = true; + super.visit(node); + if (needsReturnStatement) { + throw new InvalidControlFlowException(node, "ReturnStatement needed."); + } + } + + /** {@inheritDoc} */ + @Override + public void visit(Block node) { + boolean needsReturnStatementCopy = needsReturnStatement; + for (Declaration declaration : node.getDeclarations()) { + visitDoubleDispatched(declaration); + } + needsReturnStatement = needsReturnStatementCopy; + for (Statement statement : node.getStatements()) { + visitDoubleDispatched(statement); + } + } + + /** {@inheritDoc} */ + @Override + public void visit(ConditionalStatement node) { + visitDoubleDispatched(node.getCondition()); + boolean needsReturnStatementCopy = needsReturnStatement; + visitDoubleDispatched(node.getThenBlock()); + boolean needsReturnStatementCopyThen = needsReturnStatement; + visitDoubleDispatched(node.getElseBlock()); + boolean needsReturnStatementCopyElse = needsReturnStatement; + + if (needsReturnStatementCopy && !needsReturnStatementCopyThen && !needsReturnStatementCopyElse) { + needsReturnStatement = false; + } else { + needsReturnStatement = needsReturnStatementCopy; + } + } + + /** {@inheritDoc} */ + @Override + public void visit(WhileLoop node) { + boolean needsReturnStatementCopy = needsReturnStatement; + super.visit(node); + needsReturnStatement = needsReturnStatementCopy; + } + + /** {@inheritDoc} */ + @Override + public void visit(ContinueStatement node) { + super.visit(node); + for (ASTNode currentNode = node; currentNode != null; currentNode = currentNode.getParentNode()) { + if (currentNode instanceof WhileLoop) { + return; + } + } + throw new InvalidControlFlowException(node, "Unable to find enclosing WhileLoop."); + } + + /** {@inheritDoc} */ + @Override + public void visit(BreakStatement node) { + super.visit(node); + for (ASTNode currentNode = node; currentNode != null; currentNode = currentNode.getParentNode()) { + if (currentNode instanceof WhileLoop) { + node.setLoop((WhileLoop) currentNode); + return; + } + } + throw new InvalidControlFlowException(node, "Unable to find enclosing While-Loop for BreakStatement."); + } + + /** {@inheritDoc} */ + @Override + public void visit(SkipStatement node) { + super.visit(node); + for (ASTNode currentNode = node; currentNode != null; currentNode = currentNode.getParentNode()) { + if (currentNode instanceof WhileLoop) { + node.setLoop((WhileLoop) currentNode); + return; + } + } + throw new InvalidControlFlowException(node, "Unable to find enclosing While-Loop for SkipStatement."); + } + + /** {@inheritDoc} */ + @Override + public void visit(ReturnStatement node) { + super.visit(node); + needsReturnStatement = false; + for (ASTNode currentNode = node; currentNode != null; currentNode = currentNode.getParentNode()) { + if (currentNode instanceof ProcedureDeclaration) { + return; + } + } + + throw new InvalidControlFlowException(node, "Unable to find enclosing Function-/ProcedureDeclaration."); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/visitor/DeclarationVisitor.java b/src/main/java/de/uni/bremen/monty/moco/visitor/DeclarationVisitor.java new file mode 100644 index 0000000..05f3bb2 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/visitor/DeclarationVisitor.java @@ -0,0 +1,204 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.visitor; + +import de.uni.bremen.monty.moco.ast.*; +import de.uni.bremen.monty.moco.ast.statement.*; +import de.uni.bremen.monty.moco.ast.expression.*; +import de.uni.bremen.monty.moco.ast.Package; +import de.uni.bremen.monty.moco.ast.declaration.*; +import de.uni.bremen.monty.moco.exception.InvalidPlaceToDeclareException; + +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; + +/** This visitor must traverse the entire AST, set up scopes and define declarations. + *

+ * For every node that opens a new scope this scope must be created and assigned: + * + *

+ * currentScope = node.setScope(new Scope(currentScope));
+ * 
+ * + * For every other node the associated scope must be set: + * + *
+ * node.setScope(currentScope);
+ * 
+ * + * Every declaration must be defined using the currentScope. */ +public class DeclarationVisitor extends BaseVisitor { + + /** The current scope for the ast node. */ + private Scope currentScope = new Scope(null); + + // Declaration + + /** {@inheritDoc} */ + @Override + public void visit(ModuleDeclaration node) { + if (!(node.getParentNode() instanceof Package)) { + throw new InvalidPlaceToDeclareException(node, "A module must be the child of an package. Here: " + + getNodeInformation(node) + " parent: " + getNodeInformation(node.getParentNode())); + } + super.visit(node); + } + + /** {@inheritDoc} */ + @Override + public void visit(ClassDeclaration node) { + if (!(node.getParentNode().getParentNode() instanceof ModuleDeclaration)) { + throw new InvalidPlaceToDeclareException(node, "A class may only be declared in a module."); + } + Block classBlock = node.getBlock(); + + currentScope.define(node); + currentScope = new ClassScope(currentScope); + + // These are not boxed yet. So they cant inherit from object and cant have initializers. + List treatSpecial = + Arrays.asList(CoreClasses.stringType(), CoreClasses.arrayType(), CoreClasses.voidType()); + + if (!treatSpecial.contains(node)) { + if (node != CoreClasses.objectType() && node.getSuperClassIdentifiers().isEmpty()) { + node.getSuperClassIdentifiers().add(new ResolvableIdentifier("Object")); + } + + ProcedureDeclaration defaultInitializer = buildDefaultInitializer(node); + node.setDefaultInitializer(defaultInitializer); + classBlock.addDeclaration(defaultInitializer); + // The default initializer contains these statements so they should no longer be inside the class-block. + classBlock.getStatements().clear(); + } + + super.visit(node); + + node.setScope(classBlock.getScope()); + currentScope = currentScope.getParentScope(); + } + + /** {@inheritDoc} */ + @Override + public void visit(FunctionDeclaration node) { + currentScope.define(node); + currentScope = new Scope(currentScope); + super.visit(node); + node.setScope(node.getBody().getScope()); + currentScope = currentScope.getParentScope(); + } + + /** {@inheritDoc} */ + @Override + public void visit(ProcedureDeclaration node) { + currentScope.define(node); + currentScope = new Scope(currentScope); + super.visit(node); + node.setScope(node.getBody().getScope()); + currentScope = currentScope.getParentScope(); + } + + /** {@inheritDoc} */ + @Override + public void visit(VariableDeclaration node) { + // the parent is the Block of the ModuleDeclaration + if (node.getParentNode().getParentNode() instanceof ModuleDeclaration) { + node.setIsGlobal(true); + } + currentScope.define(node.getIdentifier(), node); + super.visit(node); + } + + // Other + + /** {@inheritDoc} */ + @Override + public void visit(Block node) { + boolean backToParentScope = false; + + if (node.getParentNode() instanceof ClassDeclaration) { + currentScope = new ClassScope(currentScope); + backToParentScope = true; + } else if (!(node.getParentNode() instanceof ModuleDeclaration)) { + currentScope = new Scope(currentScope); + backToParentScope = true; + } + + super.visit(node); + + if (backToParentScope) { + currentScope = currentScope.getParentScope(); + } + } + + @Override + protected void onEnterChildrenEachNode(ASTNode node) { + node.setScope(currentScope); + } + + private ProcedureDeclaration buildDefaultInitializer(ClassDeclaration node) { + + ProcedureDeclaration initializer = + new ProcedureDeclaration(node.getPosition(), new Identifier(node.getIdentifier().getSymbol() + + "_definit"), new Block(node.getPosition()), new ArrayList(), + ProcedureDeclaration.DeclarationType.INITIALIZER); + initializer.setParentNode(node.getBlock()); + Block initializerBlock = initializer.getBody(); + initializerBlock.setParentNode(initializer); + + for (ResolvableIdentifier superclass : node.getSuperClassIdentifiers()) { + SelfExpression self = new SelfExpression(node.getPosition()); + FunctionCall call = + new FunctionCall(node.getPosition(), new ResolvableIdentifier(superclass.getSymbol() + "_definit"), + new ArrayList()); + MemberAccess defaultInitializerCall = new MemberAccess(node.getPosition(), self, call); + + self.setParentNode(defaultInitializerCall); + call.setParentNode(defaultInitializerCall); + defaultInitializerCall.setParentNode(initializerBlock); + initializerBlock.addStatement(defaultInitializerCall); + } + + for (Statement stm : node.getBlock().getStatements()) { + initializerBlock.addStatement(stm); + } + + return initializer; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/visitor/NameManglingVisitor.java b/src/main/java/de/uni/bremen/monty/moco/visitor/NameManglingVisitor.java new file mode 100644 index 0000000..1afb6ec --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/visitor/NameManglingVisitor.java @@ -0,0 +1,308 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ + +package de.uni.bremen.monty.moco.visitor; + +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.Stack; +import java.util.concurrent.atomic.AtomicInteger; + +import de.uni.bremen.monty.moco.ast.ASTNode; +import de.uni.bremen.monty.moco.ast.CoreClasses; +import de.uni.bremen.monty.moco.ast.Identifier; +import de.uni.bremen.monty.moco.ast.declaration.ClassDeclaration; +import de.uni.bremen.monty.moco.ast.declaration.FunctionDeclaration; +import de.uni.bremen.monty.moco.ast.declaration.ModuleDeclaration; +import de.uni.bremen.monty.moco.ast.declaration.ProcedureDeclaration; +import de.uni.bremen.monty.moco.ast.declaration.TypeDeclaration; +import de.uni.bremen.monty.moco.ast.declaration.VariableDeclaration; +import de.uni.bremen.monty.moco.ast.expression.VariableAccess; +import de.uni.bremen.monty.moco.ast.statement.ConditionalStatement; +import de.uni.bremen.monty.moco.ast.statement.WhileLoop; + +enum Mangled { + MODULE, CLASS, FUNC, PROC, BLOCK, VAR, TYPE, IF, ELSE, WHILE +} + +/** The NameManglingVisitor uses the following pattern to mangle the names: + * + * _ : '.'; + * + * $ : '$'; + * + * + * module : 'module'_name; + * + * class : 'class'_name; + * + * func : 'func'_name$type($type)*; + * + * proc : 'proc'_name($type)*; + * + * var : 'var'_name$type; + * + * type : 'type'_module(_class)?((_block|_proc|_func)*(_proc|_func))?; + * + * block : 'block'_(IF|TRY|WHILE|HANDLE|ELSE)_number; + * + * mangled : packet_module(_class)?((_block|_proc|_func)*(_proc|_func|_var))?; * */ +public class NameManglingVisitor extends BaseVisitor { + + /** Various stacks for interlaced and nested prefixes. */ + private Stack numbers; + private Stack moduleNames; + private Stack classNames; + private Stack> parentScopes; + + /** Used for mapping prefixes in the pattern. */ + private EnumMap nameManglingPrefixes; + + /** Constructor. */ + public NameManglingVisitor() { + numbers = new Stack<>(); + moduleNames = new Stack<>(); + classNames = new Stack<>(); + parentScopes = new Stack<>(); + + initNameManglingPrefixes(); + manglePredefinedTypes(); + } + + /** Initialize the mapping of prefixes. */ + private void initNameManglingPrefixes() { + nameManglingPrefixes = new EnumMap<>(Mangled.class); + + nameManglingPrefixes.put(Mangled.MODULE, "M."); + nameManglingPrefixes.put(Mangled.CLASS, ".C."); + nameManglingPrefixes.put(Mangled.FUNC, ".F."); + nameManglingPrefixes.put(Mangled.PROC, ".P."); + nameManglingPrefixes.put(Mangled.BLOCK, ".B."); + nameManglingPrefixes.put(Mangled.VAR, ".V."); + nameManglingPrefixes.put(Mangled.TYPE, "$"); + nameManglingPrefixes.put(Mangled.IF, "IF."); + nameManglingPrefixes.put(Mangled.ELSE, "ELSE."); + nameManglingPrefixes.put(Mangled.WHILE, "WHILE."); + } + + /** This function mangles the base types. Current module for base types is "std". */ + private void manglePredefinedTypes() { + final String prefix = + nameManglingPrefixes.get(Mangled.MODULE) + "std" + nameManglingPrefixes.get(Mangled.CLASS); + + CoreClasses.stringType().setMangledIdentifier(new Identifier(prefix + "String")); + CoreClasses.arrayType().setMangledIdentifier(new Identifier(prefix + "Array")); + } + + @Override + public void visit(ModuleDeclaration node) { + if (node.getMangledIdentifier() == null) { + numbers.push(new AtomicInteger(-1)); + parentScopes.push(new ArrayList()); + + String moduleName = escapeForLLVM(node.getIdentifier()); + moduleName = nameManglingPrefixes.get(Mangled.MODULE) + moduleName; + + moduleNames.push(moduleName); + node.setMangledIdentifier(new Identifier(moduleName)); + super.visit(node); + + numbers.pop(); + moduleNames.pop(); + parentScopes.pop(); + } + } + + @Override + public void visit(ClassDeclaration node) { + if (node.getMangledIdentifier() == null) { + final String className = nameManglingPrefixes.get(Mangled.CLASS) + escapeForLLVM(node.getIdentifier()); + + classNames.push(className); + node.setMangledIdentifier(new Identifier(moduleNames.peek() + className)); + super.visit(node); + classNames.pop(); + } + } + + @Override + public void visit(FunctionDeclaration node) { + if (node.getMangledIdentifier() == null) { + String funcName = nameManglingPrefixes.get(Mangled.FUNC) + escapeForLLVM(node.getIdentifier()); + funcName += nameManglingPrefixes.get(Mangled.TYPE) + mangleTypeDeclaration(node.getReturnType()); + + mangleProcedureDeclaration(node, funcName); + } + } + + @Override + public void visit(ProcedureDeclaration node) { + if (node.getMangledIdentifier() == null) { + final String procName = nameManglingPrefixes.get(Mangled.PROC) + escapeForLLVM(node.getIdentifier()); + + mangleProcedureDeclaration(node, procName); + } + } + + @Override + public void visit(VariableDeclaration node) { + if (node.getMangledIdentifier() == null) { + String varName = + nameManglingPrefixes.get(Mangled.VAR) + escapeForLLVM(node.getIdentifier()) + + nameManglingPrefixes.get(Mangled.TYPE) + mangleTypeDeclaration(node.getType()); + + final String wholeName = buildNameHelper() + varName; + node.setMangledIdentifier(new Identifier(wholeName)); + } + } + + @Override + public void visit(VariableAccess node) { + if (node.getMangledIdentifier() == null) { + visitDoubleDispatched(node.getDeclaration()); + } + } + + @Override + public void visit(ConditionalStatement node) { + AtomicInteger number = numbers.peek(); + number.incrementAndGet(); + String blockName = nameManglingPrefixes.get(Mangled.BLOCK) + nameManglingPrefixes.get(Mangled.IF) + number; + visitDoubleDispatched(node.getCondition()); + parentScopes.peek().add(blockName); + + visitDoubleDispatched(node.getThenBlock()); + parentScopes.peek().remove(blockName); + number.incrementAndGet(); + blockName = nameManglingPrefixes.get(Mangled.BLOCK) + nameManglingPrefixes.get(Mangled.ELSE) + number; + + visitDoubleDispatched(node.getElseBlock()); + parentScopes.peek().remove(blockName); + } + + @Override + public void visit(WhileLoop node) { + final AtomicInteger number = numbers.peek(); + number.incrementAndGet(); + final String whileName = + nameManglingPrefixes.get(Mangled.BLOCK) + nameManglingPrefixes.get(Mangled.WHILE) + number; + parentScopes.peek().add(whileName); + super.visit(node); + parentScopes.peek().remove(whileName); + } + + /** If a TypeDeclaration is not mangled yet, it has to be in some other ModuleDeclaration. The other + * ModuleDeclaration must be mangled first. + * + * @param node + * TypeDeclaration to mangle + * @return mangled Identifier */ + private String mangleTypeDeclaration(TypeDeclaration node) { + ASTNode tmp = node; + if (node.getMangledIdentifier() == null) { + while (!(tmp instanceof ModuleDeclaration)) { + tmp = tmp.getParentNode(); + } + visitDoubleDispatched(tmp); + visitDoubleDispatched(node); + } + return node.getMangledIdentifier().getSymbol(); + } + + /** This function mangles the parameters of FunctionDeclaration and ProcedureDeclaration. + * + * @param node + * FunctionDeclaration or ProcedureDeclaration to mangle + * @param procName + * some prefix to build the full mangled name */ + private void mangleProcedureDeclaration(ProcedureDeclaration node, String procName) { + for (final VariableDeclaration variableDeclaration : node.getParameter()) { + if (variableDeclaration.getIdentifier().getSymbol().equals("self")) { + variableDeclaration.setMangledIdentifier(new Identifier("self")); + } else { + procName += + nameManglingPrefixes.get(Mangled.TYPE) + mangleTypeDeclaration(variableDeclaration.getType()); + visitDoubleDispatched(variableDeclaration); + } + } + + parentScopes.peek().add(procName); + final String wholeName = buildNameHelper(); + + node.setMangledIdentifier(new Identifier(wholeName)); + visitDoubleDispatched(node.getBody()); + parentScopes.peek().remove(procName); + } + + /** Builds the name with module, class and parentScopes. + * + * @return prefix of mangled name */ + private String buildNameHelper() { + final StringBuilder wholeName = new StringBuilder(); + wholeName.append(moduleNames.peek()); + + if (!classNames.isEmpty()) { + wholeName.append(classNames.peek()); + } + + for (final String prevScope : parentScopes.peek()) { + wholeName.append(prevScope); + } + + return wholeName.toString(); + } + + private String escapeForLLVM(Identifier identifier) { + String string = identifier.getSymbol(); + string = string.replaceAll("\\[\\]", "_array_access"); + string = string.replaceAll("%", "_rem"); + string = string.replaceAll("\\*", "_mult"); + string = string.replaceAll("/", "_div"); + string = string.replaceAll("\\+", "_plus"); + string = string.replaceAll("-", "_minus"); + string = string.replaceAll("<=", "_lesser_equal"); + string = string.replaceAll(">=", "_greater_equal"); + string = string.replaceAll("!=", "_not_equal"); + string = string.replaceAll("=", "_equal"); + string = string.replaceAll("<", "_lesser"); + string = string.replaceAll(">", "_greater"); + string = string.replaceAll("%", "_rem"); + return string; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/visitor/PrintVisitor.java b/src/main/java/de/uni/bremen/monty/moco/visitor/PrintVisitor.java new file mode 100644 index 0000000..3f82644 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/visitor/PrintVisitor.java @@ -0,0 +1,136 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.visitor; + +import de.uni.bremen.monty.moco.ast.ASTNode; +import de.uni.bremen.monty.moco.ast.declaration.VariableDeclaration; +import de.uni.bremen.monty.moco.ast.expression.VariableAccess; +import de.uni.bremen.monty.moco.ast.expression.literal.BooleanLiteral; +import de.uni.bremen.monty.moco.ast.expression.literal.FloatLiteral; +import de.uni.bremen.monty.moco.ast.expression.literal.IntegerLiteral; +import de.uni.bremen.monty.moco.ast.expression.literal.StringLiteral; +import de.uni.bremen.monty.moco.ast.statement.Assignment; + +/** This visitor traverses the AST and prints useful information to stdout. */ +public class PrintVisitor extends BaseVisitor { + + /** Current level of indentation for printing. */ + private int indentation; + + /** Print the indented. + * + * @param string + * the string to print */ + private void printIndent(String string) { + String indent = new String(new char[indentation]).replace('\0', ' '); + System.err.println(indent + string); + } + + /** {@inheritDoc} */ + @Override + public void visit(VariableDeclaration node) { + printIndent("Symbol: " + node.getIdentifier()); + printIndent("TypeSymbol: " + node.getTypeIdentifier()); + } + + /** {@inheritDoc} */ + @Override + public void visit(VariableAccess node) { + if (node.getType() == null) { + printIndent("Type: null"); + } else { + printIndent("Type: " + node.getType().toString()); + } + printIndent("identifier: " + node.getIdentifier()); + printIndent("L-value: " + node.getLValue()); + } + + // Literal + + /** {@inheritDoc} */ + @Override + public void visit(BooleanLiteral node) { + printIndent("Value: " + node.getValue()); + } + + /** {@inheritDoc} */ + @Override + public void visit(FloatLiteral node) { + printIndent("Value: " + node.getValue()); + } + + /** {@inheritDoc} */ + @Override + public void visit(IntegerLiteral node) { + printIndent("Value: " + node.getValue()); + } + + /** {@inheritDoc} */ + @Override + public void visit(StringLiteral node) { + printIndent("Value: " + node.getValue()); + } + + // Statement + + /** {@inheritDoc} */ + @Override + public void visit(Assignment node) { + printIndent("Left:"); + indentation++; + visitDoubleDispatched(node.getLeft()); + indentation--; + printIndent("Right:"); + indentation++; + visitDoubleDispatched(node.getRight()); + indentation--; + } + + @Override + protected void onEnterEachNode(ASTNode node) { + printIndent(node.getClass().getSimpleName() + "(" + node.getPosition() + "):"); + printIndent("Scope: " + node.getScope()); + indentation++; + } + + @Override + protected void onExitEachNode(ASTNode node) { + indentation--; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/visitor/ResolveVisitor.java b/src/main/java/de/uni/bremen/monty/moco/visitor/ResolveVisitor.java new file mode 100644 index 0000000..7f5703c --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/visitor/ResolveVisitor.java @@ -0,0 +1,356 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.visitor; + +import de.uni.bremen.monty.moco.ast.*; +import de.uni.bremen.monty.moco.ast.declaration.*; +import de.uni.bremen.monty.moco.ast.expression.*; +import de.uni.bremen.monty.moco.ast.expression.literal.*; +import de.uni.bremen.monty.moco.exception.UnknownIdentifierException; +import de.uni.bremen.monty.moco.exception.UnknownTypeException; + +import java.util.List; +import java.util.Arrays; +import java.util.ArrayList; + +/** This visitor must traverse the entire AST and resolve variables and types. */ +public class ResolveVisitor extends VisitOnceVisitor { + + /** Constructor. */ + public ResolveVisitor() { + super(); + } + + /** {@inheritDoc} */ + @Override + public void visit(ClassDeclaration node) { + ClassScope scope = (ClassScope) node.getScope(); + List superClasses = node.getSuperClassDeclarations(); + for (ResolvableIdentifier identifier : node.getSuperClassIdentifiers()) { + TypeDeclaration type = scope.resolveType(identifier); + superClasses.add(type); + if (type instanceof ClassDeclaration) { + scope.addParentClassScope((ClassScope) type.getScope()); + } + } + super.visit(node); + + int attributeIndex = 1; + List virtualMethodTable = node.getVirtualMethodTable(); + // This can only deal with single inheritance! + if (!superClasses.isEmpty()) { + TypeDeclaration type = superClasses.get(0); + if (type instanceof ClassDeclaration) { + ClassDeclaration clazz = (ClassDeclaration) type; + attributeIndex = clazz.getLastAttributeIndex(); + virtualMethodTable.addAll(clazz.getVirtualMethodTable()); + } + } + + // Make room for the ctable pointer + int vmtIndex = virtualMethodTable.size() + 1; + + for (Declaration decl : node.getBlock().getDeclarations()) { + if (decl instanceof VariableDeclaration) { + VariableDeclaration varDecl = (VariableDeclaration) decl; + varDecl.setAttributeIndex(attributeIndex++); + } else if (decl instanceof ProcedureDeclaration) { + ProcedureDeclaration procDecl = (ProcedureDeclaration) decl; + if (!procDecl.isInitializer()) { + boolean foundEntry = false; + for (int i = 0; !foundEntry && i < virtualMethodTable.size(); i++) { + ProcedureDeclaration vmtEntry = virtualMethodTable.get(i); + if (procDecl.matchesType(vmtEntry)) { + virtualMethodTable.set(i, procDecl); + procDecl.setVMTIndex(vmtEntry.getVMTIndex()); + foundEntry = true; + } + } + if (!foundEntry) { + virtualMethodTable.add(procDecl); + procDecl.setVMTIndex(vmtIndex++); + } + } + } + } + node.setLastAttributeIndex(attributeIndex); + } + + /** {@inheritDoc} */ + @Override + public void visit(VariableDeclaration node) { + super.visit(node); + Scope scope = node.getScope(); + node.setType(scope.resolveType(node.getTypeIdentifier())); + } + + /** {@inheritDoc} */ + @Override + public void visit(VariableAccess node) { + super.visit(node); + + Scope scope = node.getScope(); + Declaration declaration = scope.resolve(node.getIdentifier()); + + if (declaration instanceof VariableDeclaration) { + VariableDeclaration variable = (VariableDeclaration) declaration; + node.setDeclaration(variable); + visitDoubleDispatched(variable); + node.setType(variable.getType()); + if (!(scope instanceof ClassScope) && findEnclosingClass(node) == CoreClasses.voidType()) { + if (node.getDeclaration() == null + || node.getDeclaration().getPosition().getLineNumber() > node.getPosition().getLineNumber()) { + throw new UnknownIdentifierException(node.getIdentifier()); + } + } + } else if (declaration instanceof TypeDeclaration) { + TypeDeclaration type = (TypeDeclaration) declaration; + node.setDeclaration(declaration); + node.setType(type); + } + } + + /** {@inheritDoc} */ + @Override + public void visit(SelfExpression node) { + super.visit(node); + node.setType(findEnclosingClass(node)); + } + + /** {@inheritDoc} */ + @Override + public void visit(ParentExpression node) { + super.visit(node); + node.setType(node.getScope().resolveType(node.getParentIdentifier())); + node.setSelfType(findEnclosingClass(node)); + } + + /** {@inheritDoc} */ + @Override + public void visit(CastExpression node) { + super.visit(node); + node.setType(node.getScope().resolveType(node.getCastIdentifier())); + } + + /** {@inheritDoc} */ + @Override + public void visit(IsExpression node) { + super.visit(node); + node.setToType(node.getScope().resolveType(node.getIsIdentifier())); + node.setType(CoreClasses.boolType()); + } + + /** {@inheritDoc} */ + @Override + public void visit(MemberAccess node) { + visitDoubleDispatched(node.getLeft()); + if (node.getLeft().getType() instanceof ClassDeclaration) { + node.getRight().setScope(node.getLeft().getType().getScope()); + } + visitDoubleDispatched(node.getRight()); + node.setType(node.getRight().getType()); + } + + /** {@inheritDoc} */ + @Override + public void visit(ConditionalExpression node) { + super.visit(node); + node.setType(node.getThenExpression().getType()); + } + + /** {@inheritDoc} */ + @Override + public void visit(IntegerLiteral node) { + node.setType(CoreClasses.intType()); + super.visit(node); + } + + /** {@inheritDoc} */ + @Override + public void visit(FloatLiteral node) { + node.setType(CoreClasses.floatType()); + super.visit(node); + } + + /** {@inheritDoc} */ + @Override + public void visit(CharacterLiteral node) { + node.setType(CoreClasses.charType()); + super.visit(node); + } + + /** {@inheritDoc} */ + @Override + public void visit(BooleanLiteral node) { + node.setType(CoreClasses.boolType()); + super.visit(node); + } + + /** {@inheritDoc} */ + @Override + public void visit(ArrayLiteral node) { + node.setType(CoreClasses.arrayType()); + super.visit(node); + } + + /** {@inheritDoc} */ + @Override + public void visit(FunctionDeclaration node) { + Scope scope = node.getScope(); + node.setReturnType(scope.resolveType(node.getReturnTypeIdentifier())); + super.visit(node); + } + + /** {@inheritDoc} */ + @Override + public void visit(ProcedureDeclaration node) { + if (node.isMethod() && node.getIdentifier().getSymbol().equals("initializer")) { + node.setDeclarationType(ProcedureDeclaration.DeclarationType.INITIALIZER); + } + super.visit(node); + } + + /** {@inheritDoc} */ + @Override + public void visit(FunctionCall node) { + super.visit(node); + + Scope scope = node.getScope(); + TypeDeclaration declaration = null; + + try { + declaration = scope.resolveType(node.getIdentifier()); + } catch (UnknownTypeException ute) { + } + + if (declaration != null && declaration instanceof ClassDeclaration) { + ClassDeclaration classDecl = (ClassDeclaration) declaration; + node.setType(declaration); + ProcedureDeclaration initializer = findMatchingInitializer(node, classDecl); + node.setDeclaration((initializer != null) ? initializer : classDecl.getDefaultInitializer()); + } else { + ProcedureDeclaration procedure = findMatchingProcedure(node, scope.resolveProcedure(node.getIdentifier())); + node.setDeclaration(procedure); + if (procedure instanceof FunctionDeclaration) { + FunctionDeclaration function = (FunctionDeclaration) procedure; + visitDoubleDispatched(function); + node.setType(function.getReturnType()); + } else { + node.setType(CoreClasses.voidType()); + } + } + } + + /** Find an enclosing class of this node. + * + * If the search is not sucessfull this method returns CoreClasses.voidType(). */ + private ClassDeclaration findEnclosingClass(ASTNode node) { + for (ASTNode parent = node; parent != null; parent = parent.getParentNode()) { + if (parent instanceof ClassDeclaration) { + return (ClassDeclaration) parent; + } + } + return CoreClasses.voidType(); + } + + /** Searches the given class declaration in order to find a initializer declaration that matches the signature of the + * given initializer node. + * + * @param node + * a function call node representing a initializer + * @param classDeclaration + * the class declaration searched for a matching initializer. + * @return the matching initializer if one is found for the given function call or null otherwise */ + private ProcedureDeclaration findMatchingInitializer(FunctionCall node, ClassDeclaration classDeclaration) { + + List procedures = new ArrayList<>(); + + // iterate through the declarations of the given class + for (Declaration declaration : classDeclaration.getBlock().getDeclarations()) { + // find a matching declaration + if ("initializer".equals(declaration.getIdentifier().getSymbol())) { + // and verify that it is a procedure... + if (declaration instanceof ProcedureDeclaration) { + // and not a function + if (!(declaration instanceof FunctionDeclaration)) { + procedures.add((ProcedureDeclaration) declaration); + } + } + } + } + + if (procedures.isEmpty()) { + return null; + } else { + return findMatchingProcedure(node, procedures); + } + } + + /** Searches the given list of procedures in order to find one that matches the signature of the given function call. + * + * @param node + * a function call node representing the function call + * @param procedures + * the possible procedure declarations for this call + * @return the matching declaration if one is found for the given function call or the first in the list otherwise */ + private ProcedureDeclaration findMatchingProcedure(FunctionCall node, List procedures) { + + List callParams = node.getArguments(); + for (ProcedureDeclaration procedure : procedures) { + List procParams = procedure.getParameter(); + + if (callParams.size() == procParams.size()) { + boolean allParamsMatch = true; + for (int i = 0; i < callParams.size(); i++) { + Expression callParam = callParams.get(i); + VariableDeclaration procParam = procParams.get(i); + visit(procParam); + if (!callParam.getType().matchesType(procParam.getType())) { + allParamsMatch = false; + break; + } + } + if (allParamsMatch) { + return procedure; + } + } + } + return procedures.get(0); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/visitor/SetParentVisitor.java b/src/main/java/de/uni/bremen/monty/moco/visitor/SetParentVisitor.java new file mode 100644 index 0000000..fe5c180 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/visitor/SetParentVisitor.java @@ -0,0 +1,59 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.visitor; + +import de.uni.bremen.monty.moco.ast.ASTNode; + +/** This visitor traverses the AST and sets the parent for every AST-Node */ +public class SetParentVisitor extends BaseVisitor { + + /** The current parent for the ast node. */ + private ASTNode currentParent; + + @Override + protected void onEnterChildrenEachNode(ASTNode node) { + node.setParentNode(currentParent); + currentParent = node; + } + + @Override + protected void onExitChildrenEachNode(ASTNode node) { + currentParent = node.getParentNode(); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/visitor/TypeCheckVisitor.java b/src/main/java/de/uni/bremen/monty/moco/visitor/TypeCheckVisitor.java new file mode 100644 index 0000000..98d541a --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/visitor/TypeCheckVisitor.java @@ -0,0 +1,278 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.visitor; + +import java.util.List; +import de.uni.bremen.monty.moco.ast.ASTNode; +import de.uni.bremen.monty.moco.ast.CoreClasses; +import de.uni.bremen.monty.moco.ast.declaration.*; +import de.uni.bremen.monty.moco.ast.expression.*; +import de.uni.bremen.monty.moco.ast.expression.literal.*; +import de.uni.bremen.monty.moco.ast.statement.Assignment; +import de.uni.bremen.monty.moco.ast.statement.ConditionalStatement; +import de.uni.bremen.monty.moco.ast.statement.ReturnStatement; +import de.uni.bremen.monty.moco.exception.*; + +/** This visitor must traverse the entire AST and perform type-safety checks. + * + * This visitor does neither resolve nor set a type. It just checks. */ +public class TypeCheckVisitor extends BaseVisitor { + + /** {@inheritDoc} */ + @Override + public void visit(ClassDeclaration node) { + for (TypeDeclaration type : node.getSuperClassDeclarations()) { + if (!(type instanceof ClassDeclaration)) { + throw new TypeMismatchException(node, String.format("Declaration of superclass is not a class.")); + } + } + super.visit(node); + } + + /** {@inheritDoc} */ + @Override + public void visit(VariableAccess node) { + super.visit(node); + Declaration declaration = node.getDeclaration(); + if (!(declaration instanceof VariableDeclaration) && !(declaration instanceof TypeDeclaration)) { + throw new TypeMismatchException(node, String.format("%s does not resolve to a type.", node.getIdentifier())); + } + } + + /** {@inheritDoc} */ + @Override + public void visit(SelfExpression node) { + super.visit(node); + if (node.getType() == CoreClasses.voidType()) { + throw new TypeMismatchException(node, "No enclosing class found."); + } + } + + /** {@inheritDoc} */ + @Override + public void visit(ParentExpression node) { + super.visit(node); + if (node.getSelfType() == CoreClasses.voidType()) { + throw new TypeMismatchException(node, "No enclosing class found."); + } + if (!node.getSelfType().getSuperClassDeclarations().contains(node.getType())) { + throw new TypeMismatchException(node, "Class not a direct parent class"); + } + } + + /** {@inheritDoc} */ + @Override + public void visit(CastExpression node) { + super.visit(node); + if (!(node.getExpression().getType() instanceof ClassDeclaration)) { + throw new TypeMismatchException(node, "It is not possible to cast something different than a class."); + } + if (!node.getType().matchesType(node.getExpression().getType())) { + throw new TypeMismatchException(node, "Impossible cast"); + } + } + + /** {@inheritDoc} */ + @Override + public void visit(IsExpression node) { + super.visit(node); + if (!(node.getExpression().getType() instanceof ClassDeclaration)) { + throw new TypeMismatchException(node, + "It is not possible to check something different than an instance of a class."); + } + } + + /** {@inheritDoc} */ + @Override + public void visit(MemberAccess node) { + super.visit(node); + if (!(node.getLeft().getType() instanceof ClassDeclaration)) { + throw new TypeMismatchException(node, "Left part is not an instance of a class declaration."); + } else if (node.getLeft() instanceof VariableAccess) { + VariableAccess varAcc = (VariableAccess) node.getLeft(); + if (varAcc.getDeclaration() instanceof ClassDeclaration) { + throw new TypeMismatchException(node, String.format( + "Invalid left part %s on member access", + node.getLeft().getClass().getSimpleName())); + } + } else if (!(node.getRight() instanceof FunctionCall) && !(node.getRight() instanceof VariableAccess) + && !(node.getRight() instanceof MemberAccess)) { + throw new TypeMismatchException(node, String.format( + "Invalid right part %s on member access.", + node.getLeft().getClass().getSimpleName())); + } + } + + /** {@inheritDoc} */ + @Override + public void visit(Assignment node) { + super.visit(node); + if (!node.getRight().getType().matchesType(node.getLeft().getType())) { + throw new TypeMismatchException(node, String.format( + "%s does not match %s", + node.getRight().getType().getIdentifier().getSymbol(), + node.getLeft().getType().getIdentifier().getSymbol())); + } + if (node.getLeft() instanceof VariableAccess) { + ((VariableAccess) node.getLeft()).setLValue(); + } else if (node.getLeft() instanceof MemberAccess) { + MemberAccess ma = (MemberAccess) node.getLeft(); + if (ma.getRight() instanceof VariableAccess) { + ((VariableAccess) ma.getRight()).setLValue(); + } + } else { + throw new InvalidExpressionException(node, "Left side is no variable"); + } + } + + /** {@inheritDoc} */ + @Override + public void visit(ConditionalExpression node) { + super.visit(node); + if (!node.getThenExpression().getType().matchesType(node.getElseExpression().getType())) { + throw new TypeMismatchException(node, String.format( + "%s does not match %s", + node.getThenExpression().getType().getIdentifier().getSymbol(), + node.getElseExpression().getType().getIdentifier().getSymbol())); + } else if (!node.getCondition().getType().matchesType(CoreClasses.boolType())) { + throw new TypeMismatchException(node, String.format( + "%s is not a bool type.", + node.getThenExpression().getType().getIdentifier().getSymbol())); + } + } + + /** {@inheritDoc} */ + @Override + public void visit(ArrayLiteral node) { + super.visit(node); + for (Expression entry : node.getEntries()) { + if (!entry.getType().matchesType(CoreClasses.intType())) { + throw new TypeMismatchException(node, "Array entries must be Int"); + } + } + } + + /** {@inheritDoc} */ + @Override + public void visit(ConditionalStatement node) { + super.visit(node); + if (!node.getCondition().getType().matchesType(CoreClasses.boolType())) { + throw new TypeMismatchException(node, + String.format("%s is not a bool type.", node.getCondition().getType())); + } + } + + /** {@inheritDoc} */ + @Override + public void visit(FunctionDeclaration node) { + super.visit(node); + if (!(node.getReturnType() instanceof ClassDeclaration)) { + throw new TypeMismatchException(node, "Must return a class type."); + } + } + + /** {@inheritDoc} */ + @Override + public void visit(FunctionCall node) { + super.visit(node); + TypeDeclaration declaration = node.getDeclaration(); + + // FunctionDeclaration extends ProcedureDeclaration + if (!(declaration instanceof ProcedureDeclaration)) { + throw new TypeMismatchException(node, String.format("%s is not a callable.", node.getIdentifier())); + } + + ProcedureDeclaration procedure = (ProcedureDeclaration) declaration; + if (declaration instanceof FunctionDeclaration) { + FunctionDeclaration function = (FunctionDeclaration) declaration; + if (function.isInitializer()) { + throw new TypeMismatchException(node, "Contructor of has to be a procedure."); + } + if (!node.getType().matchesType(function.getReturnType())) { + throw new TypeMismatchException(node, "Returntype of function call does not match declaration."); + } + } else { + if (!procedure.isInitializer() && node.getType() != CoreClasses.voidType()) { + throw new TypeMismatchException(node, "Function call of procedure must not return anything."); + } + } + + boolean callMatchesDeclaration = true; + + List callParams = node.getArguments(); + List declParams = procedure.getParameter(); + if (callParams.size() == declParams.size()) { + for (int i = 0; i < callParams.size(); i++) { + Expression callParam = callParams.get(i); + VariableDeclaration declParam = declParams.get(i); + if (!callParam.getType().matchesType(declParam.getType())) { + callMatchesDeclaration = false; + break; + } + } + } else { + callMatchesDeclaration = false; + } + + if (!callMatchesDeclaration) { + throw new TypeMismatchException(node, "Arguments of function call do not match declaration."); + } + } + + /** {@inheritDoc} */ + @Override + public void visit(ReturnStatement node) { + super.visit(node); + ASTNode parent = node; + while (!(parent instanceof ProcedureDeclaration)) { + parent = parent.getParentNode(); + } + + if (parent instanceof FunctionDeclaration) { + FunctionDeclaration func = (FunctionDeclaration) parent; + if (!(node.getParameter().getType().matchesType(func.getReturnType()))) { + throw new TypeMismatchException(node, String.format( + "Expected to return %s:", + func.getReturnType().getIdentifier())); + } + } else if (node.getParameter() != null) { + throw new TypeMismatchException(node, "Expected to return void."); + } + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/visitor/VisitOnceVisitor.java b/src/main/java/de/uni/bremen/monty/moco/visitor/VisitOnceVisitor.java new file mode 100644 index 0000000..577668a --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/visitor/VisitOnceVisitor.java @@ -0,0 +1,321 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ + +package de.uni.bremen.monty.moco.visitor; + +import de.uni.bremen.monty.moco.ast.ASTNode; +import de.uni.bremen.monty.moco.ast.Block; +import de.uni.bremen.monty.moco.ast.Import; +import de.uni.bremen.monty.moco.ast.Package; +import de.uni.bremen.monty.moco.ast.declaration.*; +import de.uni.bremen.monty.moco.ast.expression.*; +import de.uni.bremen.monty.moco.ast.expression.literal.*; +import de.uni.bremen.monty.moco.ast.statement.*; + +import java.util.HashMap; +import java.util.Map; + +public class VisitOnceVisitor extends BaseVisitor { + + private Map visited = new HashMap<>(); + + @Override + public void visit(ModuleDeclaration node) { + if (shouldVisit(node)) { + return; + } + super.visit(node); + this.visited.put(node, true); + } + + @Override + public void visit(ArrayLiteral node) { + if (shouldVisit(node)) { + return; + } + super.visit(node); + this.visited.put(node, true); + } + + @Override + public void visit(Package node) { + if (shouldVisit(node)) { + return; + } + super.visit(node); + this.visited.put(node, true); + } + + @Override + public void visit(ClassDeclaration node) { + if (shouldVisit(node)) { + return; + } + super.visit(node); + this.visited.put(node, true); + } + + @Override + public void visit(FunctionDeclaration node) { + if (shouldVisit(node)) { + return; + } + super.visit(node); + this.visited.put(node, true); + } + + @Override + public void visit(ProcedureDeclaration node) { + if (shouldVisit(node)) { + return; + } + super.visit(node); + this.visited.put(node, true); + } + + @Override + public void visit(VariableDeclaration node) { + if (shouldVisit(node)) { + return; + } + super.visit(node); + this.visited.put(node, true); + } + + @Override + public void visit(ConditionalExpression node) { + if (shouldVisit(node)) { + return; + } + super.visit(node); + this.visited.put(node, true); + } + + @Override + public void visit(SelfExpression node) { + if (shouldVisit(node)) { + return; + } + super.visit(node); + this.visited.put(node, true); + } + + @Override + public void visit(CastExpression node) { + if (shouldVisit(node)) { + return; + } + super.visit(node); + this.visited.put(node, true); + } + + @Override + public void visit(IsExpression node) { + if (shouldVisit(node)) { + return; + } + super.visit(node); + this.visited.put(node, true); + } + + public void visit(ParentExpression node) { + if (shouldVisit(node)) { + return; + } + super.visit(node); + this.visited.put(node, true); + } + + @Override + public void visit(FunctionCall node) { + if (shouldVisit(node)) { + return; + } + super.visit(node); + this.visited.put(node, true); + } + + @Override + public void visit(MemberAccess node) { + if (shouldVisit(node)) { + return; + } + super.visit(node); + this.visited.put(node, true); + } + + @Override + public void visit(VariableAccess node) { + if (shouldVisit(node)) { + return; + } + super.visit(node); + this.visited.put(node, true); + } + + @Override + public void visit(BooleanLiteral node) { + if (shouldVisit(node)) { + return; + } + super.visit(node); + this.visited.put(node, true); + } + + @Override + public void visit(FloatLiteral node) { + if (shouldVisit(node)) { + return; + } + super.visit(node); + this.visited.put(node, true); + } + + @Override + public void visit(IntegerLiteral node) { + if (shouldVisit(node)) { + return; + } + super.visit(node); + this.visited.put(node, true); + } + + @Override + public void visit(StringLiteral node) { + if (shouldVisit(node)) { + return; + } + super.visit(node); + this.visited.put(node, true); + } + + @Override + public void visit(Assignment node) { + if (shouldVisit(node)) { + return; + } + super.visit(node); + this.visited.put(node, true); + } + + @Override + public void visit(BreakStatement node) { + if (shouldVisit(node)) { + return; + } + super.visit(node); + this.visited.put(node, true); + } + + @Override + public void visit(SkipStatement node) { + if (shouldVisit(node)) { + return; + } + super.visit(node); + this.visited.put(node, true); + } + + @Override + public void visit(ConditionalStatement node) { + if (shouldVisit(node)) { + return; + } + super.visit(node); + this.visited.put(node, true); + } + + @Override + public void visit(ContinueStatement node) { + if (shouldVisit(node)) { + return; + } + super.visit(node); + this.visited.put(node, true); + } + + @Override + public void visit(ReturnStatement node) { + if (shouldVisit(node)) { + return; + } + super.visit(node); + this.visited.put(node, true); + } + + @Override + public void visit(WhileLoop node) { + if (shouldVisit(node)) { + return; + } + super.visit(node); + this.visited.put(node, true); + } + + @Override + public void visit(Block node) { + if (shouldVisit(node)) { + return; + } + super.visit(node); + this.visited.put(node, true); + } + + @Override + public void visit(Import node) { + if (shouldVisit(node)) { + return; + } + super.visit(node); + this.visited.put(node, true); + } + + private boolean shouldVisit(ASTNode node) { + Boolean visited1 = this.visited.get(node); + if (visited1 != null) { + if (!visited1) { + throw new RuntimeException("Cyclic dependency detected."); + } + return true; + } + this.visited.put(node, false); + return false; + } + +} diff --git a/src/main/resources/ast.png b/src/main/resources/ast.png new file mode 100644 index 0000000000000000000000000000000000000000..90fcafcc659e3ce2a13276fa9ab52658677feb21 GIT binary patch literal 135714 zcmb4r1z40@*EWcPN*zH(+8`vPyA`Qn=#myCq`T7qq@_CqW@r%UR#0$A8A=*SX&Jg^ z{ypgNyzlqD-~WHV*SX}#JhOA{weGdzF}5~&$sle4jq$&yczg=|c#r?8vqCTCo3O5SMp@iLIu%%a zLf*v6-O8UyFH!PxxQuP?p`c#jZiW4(Q`^6iEFRO@7Bu@iF*d05~%o{4;-H{|Dz{?Aec22JDXju1nY- zH=)>3{{7KkOt{#8y;8vbjblQF{aY&OJod-$kN*An|J2mKKmT8wdYo)j7IjY5!m!>Y zq=OsVu@te8KibF5&CAhILPpKCG$w|uH$y!2&6^L>l-QwU;kV8Y6(!nF@~B?bT4Lqp zy(c7e(4EXH7Ke)+o7GL|_3K9Up4+V0FZ1xaVtWLwMg$^Wya*GtGkANquvbe~mK8gj zRtD9lCaBK%;?)rj4Qy+7!~?PGU_zE(&Xt^*sb-Y%v>Fx0Nh|;5G;@HWMI`yog6~nb z4I~e?byY^o0+z>24weWk0{?ZUZ4?rsSOH}dyJMj{^EqOPa6d1OZZKX!L0SN&!NDUM zn4P~;Tv^G0T_iA#_SX4@u6i=*dU$WH1*dp&1!vt(-XM>XLY@Hw9@Jte)9P#1ec$Fo z&3grvl@I@X$<)pc;#l5W>vS2JaNc}Vfn!(c9w9#Ylq{(ei5|J}fCjUp;T@G4lX2~#3v{$1 zmG%?0j%7yvVzfR|%Y6+rg3gOVq77~_JJ&f*f_cd;LAV^?jo2 zEe*CK%`BN9gZ(>6ZiT7HH#aG+xiau>uNCW(8+pR=keiDF1uB_|z*N&xsBQ~)9^K|O zuiaZe&Pz&~Q;&?~>`N0KKAKH&o!8T=uGAVMr0_$JSvTFeb2{%OdGa&eaSpAWe0q4g znK{|wFYV^`%7|XXy!&UABwaR%$LhVM+S&k7lA@S#nV~+2QUoJ7rC3{Mhnib-EG)@T zk4)qw>yty`y@n8n!L_$t2Wp#z5=xTug)P+A2gB8?(MmK%-dtJO&%)HAXp8v9!7K$*$@6ugH4u<^S-?$$+Awkg$wql>;!!mHj-{P zjb?F`(wsLL;D)yq&bz7YR;X({#rl!In4VJ+#_A?>CpzbZTW^JQM>sO3a>hZ3sRbw3 zk9{HIwWc4k=aN%G$Xxlv;pr=I7`i=zzOP$I10fSmpeQY{xdLhHrFk}r)V5UQ^4{r} z%Y8)@>(5ppDR)xcymIh9LW!4AvdhI)Y6B+k+8A%5<r%`yH+?a zMLuWt8)QemGm)-%xxSuBB2uSl*;TBZzE;dxx}3>t(K>G5Qd-&IRxU~H_rV3zvk_Gv zX)sqawM|Zbj>9~-t0kfI3-VoIJvd;+ar4{%3@UubS(u_NoK2Y5Y505hW;U@zIitBE zM+`0x6dbDvxZDaX5iR80KCPi~uJ6?m8iuhx8JaXDt!m@_D7O|fk+FfLsrjo{X;Y%!dqUKy=5kRdSq7DlKl159 zN*V8nAJk&1_oq%P;!o8mYzE*9LA%CzdFe5@c=$s4^{xp)T0`sED;A8*nRotJ7CcYJ z+#>MViu_4n-|732G(jHXzWp;!BJRObJH}-fdH`g9DK3a9^gn+t+o4>11 z&bZEJIXgX8Wj)Y%7)xgi)fQ=S$Q&%z)flL&ACyY$_qUy_4~*k89XOg@X@HJbTJH9W z+S7<0y%b^Mz2ot{)zYwGOcH(Yl!U}^_}ItH%zyBL|F_0Q#l*-6Dt@n{h zJ*!6xVWSHfc`w-?&!M65V5dIks?1OwME)Z4pAO&*1bJ{8I0!mJfrKW1T0zX`X2s=7 zV;`^oiyi`EDhR-XkCLDeA}Hh_Bs*V3XUp-{KaYQU74V7h7!2R}8ohhUKmMChGUuI? zikfD6(ZmGwPmq}3T^$i7kuuaYFo6DQ8iZ?X#0HVdRT4VI-jd?)rhoLj&axp7Vn*ZA zLRKd&BK+(u!nZO=CGpWS5!Y)hd*?0C8$Y5#+vppaIuWJJ6Y&?Sj~j0r2<-k}Ni^hs`T-DF`YhzvrAxVQWc!Buymi@}&TOH10UCMf^a&CJHl7C*RS z6ww#Lam_gs)W;HCTTWYX)R#LgCn&{q|7YlF{lv^nN&Bfr$JqYpD&AwHh@UdxmcoKbDhKB zTY(0%zW#WBj$C3~+{tlG8DolXwe5s`V~S0wZbkdlRI@@XQAGd;=h_j)c^O_-qwmeE zTH-_C$Ck_5)<_YZaHj+lzc8qUz zxt|Y8RmPP15}z2kx{D(6MxPw|9_^G@etC6?{5q#mapmdB2|m${ETSJHWyZs{$e%xd z=FcnpZGEQb{M6muJ!0%{xL(84zvib`mkdwWzAh-iRK*1~s&g{in5g4yIeEWJjVv{6 zm~3!YG=Qq8V0H#n;(I-}7ZGoJ8OOEJ-8j z*H~PE1Ujg@4w79wRN5}NAblXbz;}g{c|HK!!9c|wMk5&m6d$110O%$ zx^?TmrE$FrVrmL)*Ot3w^*%W^Hm6ciQE_Ob8A_p`q_qC6d=6}9?)u6~z3;J`nUsM+ z8qZAufojD>j`#@$$^zx^kPx-w5-49oru#M4Vs<+psFhZdrh;l5)a*3K<;T~La-9C# zDae@c*p4tr2k0xzh*cQ`wNU@y{a7o9pSzy&Eah&v3SR8eK-ARUmpf5kWKf%vK?-w2 ztip=ireEIJj#ndgHYOVqBfa-Gs{EvH-@c7cOf~r4tjlh){&dwC!{ePlbS$si`0m|1-3oJHy*|+(eZ! z{?xmgWb=bM`Qetm$1xV`Fc=IX%FMhJ+1JWeK}kh*)X7%%C3a0MN45ZOkRm1bZL_AC zC38>ngKN~(MSIhZ+2$I~MJ2(Z5Dug9*4*3T;!R+>WKP8se+8b;eMvyt`PgjWh%NTX zw|6GS{-?WOB0;3|rBkA*0=D%|3!MP#E*Q_{SOIf6xl+pZFUMoP2kA2jzak@-M}1(kJTsVtHpZ3Cd#yZ@ zRtf*0A#E%>v|RDJxiJXc8s>?NO6A$ zr{O>a$BMPig`4)1+KF+lFExCFa&3>-Pz72@-DCT~p(343-@Vb|V)j-BEb;|$Thl$M zxQLXzMiO6Rdk7$f-;ox?$v>g;ETaa$2YvkNX68F->ff-UxU00xhM zU!7%%i>>oLsG>uQ8W??2YPENvX8ZkpwrJ7Z*q8XfdwHd>ZGy}ajc<0>LvIDbzE3B} z6vqI>1K&($rEr}1-CY2e=OlvyzS&xaCfSjaZfy-bR|9}h8j-<7Nikxp%}l!gpU^xA zLi0qPD@UPtmZ+L;AvksG<29I{ZKOHb*;aeZ+7-(2?25lJO*U6DJz6>=Q@`L90#nlB zk7~voCAW+7+~l;;hzLdy)H4-IYDv7l08+r{w6sQ31Q|7TYK2ALa0ZtyO z|KIVLQ##o<=zkH9;pan!OZ1l(7dr#WnvV*VQU&hmRo(!x!z;FDgTYDwsy&pRf7pM7 z>f)UC-V|TeU}a@p>`5Ide=4Vt0sf@8l97{39?am??V0za5Yvf0nw0M8D;zb^_Cu8! zHVAm4=JV`ggN~ZYhW!`+h8z@3yZVNZ7Zj9AV32fg8e3^OcqZ#d&fAT$TV_kWlf-myL97qk&)9UmoZ{-X>>)K5FzRNA7KJ zQ*%8I;K?#>@zbqQXaj$al(X^MOtmIMQs_(K;;tg{hx6F=D!(8Q3bGJP9E%3u>dALf ze<8mU4_)0+VC-h39pRKu_bi4wxhiUOW{W1$y2p+DPhH*J_d8Fz|HfXNP&8LP!?R|` zIwF5ghf`CfJio9o%Nz2FiW-8nG&E#nWN~{i#l*Gs^-X~@Y#=Nw3~8vW+zDaMcvmTJ zWo6Y7NefKimaUG?2rwo#yxG~=INb8`a!?s6Z;s6$1=ir6y(p)MG|Z8WC{|e>t14P1 z3^1S0&^wES7QaT=<+d@Q+hpjpzOw!v&8za;2J5+!tF2>heJEjY$k5|xnf)-5=2D#-gaCd8S9Ng{^|@sp_~@f zE%_{wpTH`bx0%LIguu(7)pnC(M^|+rtA!>CUn7 zHyg$ue)yL|_CE!>Dmr`yydS$>1J;_oY#IoSB_vWEmL41H+~LgfA0nMUh;#=}Et%B- zz(sF9?0KP>z)mUV@otx8vfi}<)tPHB2UkihHK=piUQ{|9LG~5GOj0sWIvaTuey*dxW@8ffB!N*Ciz!x+I{5g&dFKkcY5@>qoeDnzrUZ}cPAP-UGHkWtQow!JYWGJ z9U~*7NczU4`*cYR7Yhw7?eX6F>gHw{$&cxl7N`1jzQF+``#OV_7<3Agp3nYBO)WYm z=C;CnnXv28(b2%_j2gco5G?%sLuH z4v}_OR>tNNo1i2%AMP5$*T<@kfpc4sJB^e~6SSL1;F^zR-#+6xZNjNgMLUe5#mbw8-%a6=GN-EEjYcYu`5#Stp8XbA&so| zbvqnnT`oQqTmf*lPvY1{Tl>0j?#8V0@8ovH>UU5|a~>+xN>Sdh-uPWb#MX0vjRqTU ze)R$34L0O}U?w(i!UJ}eLW=e(HTB<4JpAP31c3B5oE11oE$M|E0)lyd6>GnAbtx9S zs;&K0qOa1Ib~s>NR-#|MCVx3V?UO zbb7nbpBWd4u#63sdn_fT=jnNYfB-xLW`&84efq8Z&hXIgo0n}?m)_Vn*SRhuXWqOi z4h_|(p#cwpxOoz6WDHURkcYIP-37X!mQvy?!s>Tcp@gNtF=BGApO$=ih~| z=wG;S!54G7kN@(mx&KLL7u&gW$OH~zzwMq9rBn`I^x-BPx;0*YM}WEG!^;cc%c|pT z^CkM9HGSDG#TMz5ad2>yqUnWSem^RIDnc41#hj-^cGG)*FB-di*yYB*0k#Nz zP}r=+AFOaGG?+B6J7s~hU+r9O&K$m_V$^v>x~t%^fO;w>`-v}kEBce%P;JeL`o8@X zNWjjnQWDSS&BLXZSe)hgN<`ZouA4VY8XI2_VEKa?6Hpu|T~OaGDGpXZJdZgAqi-Ik zXGUa-x_zpzr*m?6bPpHRBUsaU8>|YM(%}Mj_vos*bdB8l)fXrhXlmaaOXhL<05s4I4_q!U{b5s?1r& ztEMJ=QjG`NB=t;Uzt_X3|DBQ|@q*EWN3(-JWcj{fGAKZ4fO3UmMZSnyLaV8&s_b|* z8-oIb-?n}b$rk!=dvDgrXUfaOlsJtw!z{W$g_pN_D*r>#zFWDt02J+Uk2MZ?sF~c? zUfUu~Lt+@>FJD5ab4G-AZlOeYO}}s`M8({aix_KhoD)`vKhegHa+eQ!odRaXx)kcC z@OUp{UVVCyr-G3JfkO#T{x;)Z^~_{@Z~XL0b`Lu`08(06ID937N_?zzQe%^p4%GIa zQ%z?Qlowkj8C2f=A|%VoZ#U8RpG~a=0eZtRL46u3LZpmQq@MPDc_EGLLRiw(TS#8_Afa*jIeh9GZE)zJ_vTa+l)_&MX5<=Q9GmEViwBj|aJ&OBPr4A6 z0m$p@62jUB6~9%BWlWsau+4HDiyzqQsU_wHtU-8OY%?{v{{r4j(m9r_`kt*o(`rz& zM!2Yk#dagLUIZ5AEYUTWSHDyQzsz*@lLamIL)L?50sB zxC`4Yc00PctuwUVGdLiHZA1JT$I}qBq7t@G2W&pQ-mj?0jzdoKK7k~C?mMcpb%Q=)drCZ^JF4DdNP0Y`L9W%C`D zD`8J{MadN7ozPw5dh?11lx2}jC9#P~gtd1Z}Ajdg!)N&g#;nR7eQNV6~I zD!H#gXaCkhGH(a#shu;^?(#Nrv?3Uk6d7)^q!Uv3{Nf5ua<|)BntAOersL3klJv}B zpW07aWCn}0sZ*4CBp&H$^BTIr%@p-lHL&yQ-So$-`Arj#>R$0O{E@`nCW-a{6D#NG zUh64$Au|@e(kO^QE@?Pw*tj99%yR8h~ zx0Kw5%8d>dj{-j7R-V85*p?$M?b;ZdZL(S8YlA>9!xTfFhO%NF(9?r&YP78A> z$Q!Tm?_5Ja!U8D84psb5pXqeQD3?u?QuqYCuR)R~-rX`de5lQ4f}(4-#Zr?}O&4PU z{lHgs@NlucHl~LH0t<>r-Pk*ofY}=GJnr9u_B>SJffuoy)+OE^>iNY#LUQPePMwoZGR2)AwOByx1M=Py3 z#}7Ni$w;GlS!UlFPALaM*E5N)RWZ{7fKJ58nhHcH3S013-Gj88K+!=5WCcTSb=%te zG$jM%mg8b@^|N;XHDU0%;$^S zlBZ>;eV!iEH?FXmsNZ4kP&G38SjKT?$b&(Mwc-J|D}w~uxn+%iiFo>R z+_STS^D4+| zjg;<1NurZpN+<407_*#u8P0UjlO{x$=#BQeQkNM8wqOz{j1GMN5F~ z7TpKJ1E+fH>edi9S{v8_P{d^aQcy-|WtIubxrsi;TqA}#|%6&~WH6ss?1CW3J zerk0@(Qe`{Y(+~(Ru-@=AB3Rhra$ba*t0>4I%SLCS7K=%I7cxh`cHy#mbt3sAuWW#P?(V0P$}JIfWq_g3|cbe)JU^0U*^Czb7G<% zGe7$|%wn3!6PZP*EXgHkyRTUg{&GX-w)+HoOJ|dO()oa3PADA4Xvo&`5c|ziQ?TCP zn;^aFfyAUq_}2H;7+>#L;~>UVvp{cDpuf0D@24x=&D)A?&Cxusyx^xo z-_3P#P2O8c=VV(Bz(LluwY3GB$RFk^Xn1^gICVI=vKYqfyvLY`j?;txq6$Yt_Ki`G z{W9?iZB_2B#=Gmv{hFDHJTa?8&8b)CEyHh9CT&56Vbh2EDpUK$k`;V|8YNI%;qA6*#F-A)F@bFe zHS^#-%#n?%w%#9{`G}{SF5;jgs(Q#)U*lS6H9BSts-<8KySJh6&2%*?3RE!1zJ2rX z^0G2d7x&&<&dc0Gp@2mP>~bZiP`Ouesc9TPsX$ZezGK#X@N~5LM11H~>5BWlB{&A6SKjTH?!ArC z(d=0rtm|xwdkD&pod22UnNw}?JADsoRl&i*NKQ350bYCW)7_ED$;o&$U{xMamhG?| zTC~2p6h^_Rjel@>NPL4UtNFzAMibBBLZY#Vh=|qEJ=%7V@`HL0EH_vFY9^0a=vFZv z0f{`-{_ZY+lL*#efj6=F7*CjTBy!i<;sK&GSG_<@V{);03SJqZh|eyX3`+((JJ%6q z)Ue2A=G?JYl_N)by4#{;Z@*|Dws|z23077eLiN62$G9^Dy)$4^UEKroZ|)#+Z5;b* zQy6j5SS#$z9AX4#kAXyAMNULojZ6VLYuawLA=yil51ygX>{$Q>c==;#O${Y45v8l0DUt^A?T@G(x} zIX^~BE*$Q*_H7GT5z@`ob+Xyl`}9(5d!CZ)!-wEx!`i-8S?i4Q8QLy%#)Co`DIp=R zH&*2I^%Wv6E{W~1JmqNi(PHE$byyk(wO4(B6@x6&b^$ow@%_uimg&<{eZQ%)uD!L< zJACs2F06^YN#Dn6HZz}OpTcNpjWdLui;jCmsRBsAG=44R_~1@ zr8ph6wUE#VZrGbMXNVs=cO_I0=hgNk59akL@~9sHq&{4{eLOAMFzxQ^rv1u@;+KpC zEk*ltSije?ykk?SdyTllkyxdlGX^4>vxQrlz0k@K;B|#*z)gwg zd~N*sUX3oZgNEl4U5O?ZSwHc_5RJ>n^K{BJc2bkfuO zU$dzTMy!TC9mSp_c1-gjd?0AItL9{8eQiQ+J??!?jp(&X70XPqx;%|M5{N!k`{{~D z)!R``>dAU>awo4AWMq`+)W_2F(U4?H6Of=;`E~-SO5rZ zYr`d}qdH8yyu1x=>-9FHJXj~n1Z84Q?`yhRQ1F?VN3cEKrdgGh-)6$4W^?~6Aq$JN zuwv?*dw0^X+QHu^zVtJAiN?*w80H4yw>$BW^~y&AE-z(Wr=y6t2R`;DZudt{l>DXT zIR74HG4dmgGn=@v`Er^6=+M^D#RmcRu9MbH7_y|x81U{zrWmmx*3f|?{YyC z;^P6;xVtv0F<`&U#qp=WxRZteS_Dv~is)|2MHvaFH=~ zckjeIb9dJcOre)!pG&f?ljDktxW3mIL#iI*sjO*sDApoZU&OiX9JX1tjQv1&g#m*hn2)dT`q~;`?X=2Tb7w)7{l`FFAE5vFOpr*EMj$6h6Ly|= zKtvmqKM6F~R#xua^xJQ^KzJSO#texG5BJIww|saE?`?D1-V=_o8FKw6)$_M0Z?^G~ zFF1a4;jeN=<*EU4ME%ofW-iU~P704_B~sEgRB^hw>>)@BVsKXu5{-`9!YMOh3`9VZ?F1R$qBE|~Z?^1Cx*t=Levv1Y@b&6j(|u}dlR~>SZsXfo>|cu> z$uzns+_d!Iq`yysy09)=z*etx|BzLQo&gV^$Yat)rI^%u6e(L;j>0b9XpSB;>zz3o zuzJ3i{>Kt4saM%>vF`TaQs(v?Y6i?zikyj@{LXvcmrASh1}95?qt?CD&0#G4aiAW{ z^T8$I6CGQ6eH>0=zqDSB)h$NiQO%>>0%i%chwApCO0|`l=!k8j$Q0%qDUcf+gN(AK z!uoh2h7#Dp7bvM-?c;w-78HkYI~$;klTF)^+vRss2h+>>7!B!#EN7WPg*kfir$c6L zT{gXdr`s~J9B^tXlBaP{L9CH9J7j*tDyVc5NM4)kR>)N;Ysz{tfT@aKj-53hjqkcY zRbRrvvWlN~M5HjjH@cuvl)HU@6ZsEU>1P1kimI;(&vzU1BZUfAApyI^K1$<^USr=< z58KN7Aa=5(`<0iULBr*v3M?jKgARA&)}K=16ls^tT405-LzGP99Ix{7E<7qEEXW%U zX6zA<5!hYYp_H_!rysH>QjAe%)3^({*CYWjHYkz;Ujx87sx|N(-z0aa*IzIdVjx|- z34Hg*Rpdb&>U>9QnUHYMol4)*ES|bJ{qehymt_h6?Y#-;Is4yFSQvs+vh71oh2b?JT-Mil!Ju4a- zj)9h>Zt8R2 zK&TEoC;Obmzx`Z=Mufm0HUf|U2Q33QDM>7Vhv(%Wsu{on#62NoK^T68@O1A3hsYisy0>;&Ltcd zwfXkWdP@|8MjWG8EfRvf3gefS5-6%exDEqaP5D9J0Db-$gliIXS~O>VFa|lG*wxxp z_Sue5cz%2N^?gEkMEK|&Q#u3@up>U8MBcAs>^lT_r|b9h!s#W^KnVfyfAVA&5IZ;1 zL264a=HXyulp*2=7!)@*H?SC$5;osk0|f*Gusl$UKPHAz(G&`}{d0JD@whd1lQFpI zz~fd`(TaPyC@6&RD4LliE!*8S@?5yq^A03_K>Opm_DyZ?)4+fR`MJ#{fs~EHv0AtF zv3W#nX1x*sh9r+F%p;nbd;#_2wZB12PM)&^I3l1M$D#sY?X`XXI?q9SSC&ggrUo2$ zrU)mvv<8yv%_>D?5D_sBU@nQSseEE$VsVO?f0Gme&h-Ybd3eg}DWHu4;YO4MAbtZi zwf_BSe~dq76B8d6w-?6QoKN(q+2@ejzVYqA^5x5yfoO`w|A0SwEwU}#eGbF8vg6Y8 z?jOK>M#<_pVrtaLyW)dB=?KRp*EFGzR#Dxuv|P`=-fS}B)OG)*uTnc|Yi$LD^AKPw zFEx=#EcC{=7-6Rt%;hP$)w>o5y{1x%T*kg}p8Z-Y*XiB74(;r@E!a`-qXjcVfy2?;SUFx*`SLZ{L3 z@l@a18lG;X-3`)Jz|Mv#Kaq6Muew{_Z*wiDb_3cu-MG zg8}hJ40Ey#)N}yDt6+~njR|Vn^?PGfJsne#gBX^sdawNoQE3=Uglot6e0$J|5^a~& zcOGD)H`UhJmPzcKoH|~)K(|B=yBC!K&_Z=}b*HE>U@z5nzaIdEs78S;fZnMcOSrrH z!!}9`_1dMg#hiYlgot;FSO%CJU)%g*eoe0nec?|5Dtjv9f~{Lka|Ct`GYd?XiLS8a3Flj=BxNu|;1u!2c(IQFh-5XtLi|reuvT8ay|b3FEYJz?fQqN>n9D-vHBW|k zf2BU6;uEflbpU5p0Z*K2?n9CrZxVmP*$$$;uBRDF!am1bhi$tv7X}4tV4DToQegC# zFJ7FnEyZ!@1Le}*V=iKW;l9ClE)-=37G@>^>^di1D=ZX1&E_yI5;V?ZJOcm30VD=5L( zaFEi}O!4m4H~h~jInG`=4T=gqf!~N!8qn;IW&zhMxQ^u>cuv3mO%(43(}=j_0}Wi1 z_}(L+U|3KIgk@s2FsZFUp2 z+`uA4MMdje*|dwlb~p8n=Z|VtsTmnbIL;P9>(@8v+-q=M-2)22B9cIb3hz?N&Dq)8!t0+Yj14NEMQ>p~ z46kwP=t^P@Z{{u7-QzIwQ}q#l7t0#O{_i25<(L$IT~#TZr@u6)hjkoJlNy7!B{pt- zOA?pPjmZ;!)*GWLj}rFy`FOnAc2zZruVD#ZqkLOeO6tR>5OPtMA6cHf%1X3N^anGOem=W2C*ZZUP*3NM50xJ9B$Nlb4iCK}5*0$?57h}Ovy+W`O#(vND zpZ81T681-Lv1pt;dE#`~1HN4x%@yJW5YNnaqF5kXl#q~^%J*OF%cQ@aF#r9^GmE96 zqLKP4>pMh2t0$pY#n@SMo%KL`!9OUu;%&gjYDX)P#sjEB>QplzwIaPJKSyy5EMESD zYuB!Ur%5f6&R_NPgc%uGcmBF+#wO?D)s2kG0VfH_V%zc3B<{H%frOqkVDMs zma$Ka*Fqk&AijwsvIu#$JDQ&#O715dZT=j5i>pFcxL-GhSDOl;Ay_K=^B2s*sj8-d zAmGid1`;~xESQ!U)WiwQJBHb}G0|r~qT{EDG;a<`oJ{HD$?hv*a=A|jy`03yvYmge zB=60=0@C$Y2oWl(Yd|&T>gE<16$Km<*wmrU$F=Cw{b;aS-$p%qQWnZaD4d`;V&_dz zBONt^S+maLWqCBnz;#+sUaC4s_s7ipVs?2IrNxIjx1GBP#~&sY=a{HlUZtSm)T{gf z4mALlpk4kuOib?W;W;IGo+4o0?-}a>3IFt5mU1v+r->J$e2+!Esgix-SZ}TRjkH8& zq!33#e2NDiN<=zb0@OJj+a;dtdqMjeyg<1UQ<~!5hLpLV{7?CpTul+g+cXF)B`Buy$aGqbKl&du?f%|C0|#Kz8UT*uR>Qw9vmh>q@g zamD?8_S2msV)|=`O58N5 z@Ph0+8ld#>SO9i6bJ5D$TGVar(XNKnP#kbrXJPW`1K8VU3lu1rIxlvYS5(A?oCVWP z1mbXV)34_7$8#HHg_mPP0m{r)$&>(R+1tUL9E&B%^1Zx#-v-NNrKbZi*y?a;#9emw zC19uGCMdUz9YsS-KWvgiCYbp;eKI>p{^OMEUP}jef@25%BmMfljRov^IZ&NA%{K=G z@R3{$&?95=S338fL!NRZ^_iQIvW-sESy^y}%SBZI)rvtqUsB&Pt}6AJ>K8b-mGGZG z!+@vOt3uHTIUH|HZe6=pbLPu`b(|lELWM?9_X!Kz#%KyZZSNh2-#q;xQ73PQI zqn^7P>)XKR;J3L(UJ3wQ$}H2*$8quTzbrRJQ_XR8=40;tmu_R<*s1xg{N?3AK#+>B zby-Fx^IALzAdvO@;N#Y zR6hCqSPht%6gWnTiTFSO_8x2mh@B`D1U$J?nnokNIVAxC?b3*63)T?2iL;UhR-J}MyDy#k!&~f4;(!$Zjho$U9|A*KTWb^(JGXoE04%%6Ed~Zf zy4v|G;nKL+sqnJ^hu!)rQ@;weHnJH^EBfRxjSi=3^y5nf5O;s>D$S^3rEpRuHz@%f znQCtrugNmX!^#>AoO<>5E(UBPS$mz`>?p88gNO#;71(rwD6S_sLvaT2eUcf@ZjuoL zITsOaeFunSU!sqJehduR>asD@CG3P;Rg8?5JLA9iNn#B1l&8Y3UobPj?g+)vWNwC% zVTE=p)qgB7&cYQe=k{kioI>2+UndO#_IFP|J3UQ6p)iem?im!y(Q*C*UTdPlIcyY_ zmM`N>l0C@2H`Isy-8F!}ir&-L| zW$rRcq7gwmv85liZ-J$NGqBzG*9Y3IU!MkG-rNAEMJ*%_m=J?eLZXfX6enr+SHC#s znwk@+U8Oe`p`dL85U^gEf)&X>-~rdiK~j*O$-`ktH36U%o%pbqSJ3=Iyc0CQEArR4 za3=x-0xE$7a2y;Y9@7!v7#eAC2UULW#*EPoqLBp!Q(zhMqw^DWxIpyRaXw%2@5WC< zLlEgapUZ&r^*i+g>cs@$59qvpe>L9`!L{QLlVcD@(V9C51YmzpU{N7x0!T7}Tr(Hq8AC-L+r^D*72nv1WKv4VH&O3wH>do& z&3ijXt#!_L-~f36z2Z_qTHu92GN5H^S5PmQY?u=Us#9>(^m2g>VZCqAn$?)ga=zLz z9H>GOn+3Up$)*$2pHj z1`Tcz1S;6)K9qr^!+Jz^XJh@T#S*`}om6}a8!#Vs2?+s4#^~()dLxV8SM41g6ciNO zUoK(Y*FjWL(gY=MWVO`-(0y8VCHw%+07O?9>_W?l`U5ph!?N65LP-pe(LpYgCSm7@ zQv%elz=^aRE@~^plQW(8bX2sMHa=8cHF=-QfLZLh9h$x3#mLkSE)#(40LT4JvTo%w zHC5o6fQOm{jw(SSZwW*yeB$dsGHk&Jr6Q`kcI^VVJPUYxY;_f9(qWdc{igPTXg&!gE zuW$Vxx}vA&=SbRe6|wS9LQt##RdYL8oQ#R^G7K%sx*w3@20Jp6~lwvdsfd>RKR?1)m+o6bbxsis1 z0%oACri(`g=GgBG-u7zp?RETdxQ`JvpOBor zo&o8L=2}kGW2zD@FdhD0SuB>mRgAy*OuM;8J;7@5M?a{}649OPffo;Kc%~PQ0R=0& z%%sKVj!f+3Y3!aV8W~x}GAXhLDikbbVtOCf0$APHrJzGd9$_u}?VIuRq*w1&+xAO? zUZ1_G@O@)vCv7Vgr)2f%3*ThiO2 zGmD#z*^~LiLp`%8B`vbKOTr%a92&~5Im zIHI2iPrO#O@7dU%lM->E@B8CFXyIN5b~Q$Af^ z8{@Y}&$nLSYD4I7(G!mLjO`_UC?{t?urDP#NRWQ6!$9D>U$GcJ>L#OSYMJO zz<)CUU($-g!$LdNnk62#&co7bPa1E`dHEUd-&!K@qY^ilotS9$cRXUUOI4YTmNJCD zLePf5tdvd_%98WrOqr|1&AYh-YZM^fBT=BFn`x|pzq39r$~0ySq001^P^NtM7%M68 zX1qP?0CD~FUbmU3-VzSXq%^S8#XrHIvB4skAi>4K3oBgu?njWIGNAbKt2 z-_246wuDf&I<`5u1zt-+QE?|%e8t}XbR*N41yA|Hx(5FF3+wBH1uu~s!|Ta!29D$1 zd?vO?+}6Q#I=e4gpUGM?JmGVQSnuMsB)$5~5}##2#R=;fhrmvJUfTxp)d=gwTc?H2pUG%p=oJy)v9TtI zzSVZ1I!xeGeD{&=uRWOSamU}&Z!kx|(q5Muioo&$@8a{nEYv0h~0;9m?$ish_`^iGU+}}Jdhy(@wwfF5hRz3~v5qbHACEp%_ zZX!taHNl6%nT@3u&JsIxv| z5DhZ{)Dd4pantF*%6g2oj(wuJZV!`;me%KXSum`#6{7&shdba69aK6`yynkO5Bg_t z?uFdr{`-wN5QRs`oyHRsJ!U5_LlRx9PW!cHlP&rRL2fR$?Mfa5^Wsp$*moE9fm{?h z@Z#jOruo=Ta_#~z@}){9kfshl!oF+cL_j~2XO+GbvztfpKzXz7FaMp2z91{NVx`oC zRo`atu8}jPs?IULx1Hsqt^@(62zZS{@{S!cBE8E*6WSP4dl*q za%R8VI;=WdfyWFzk+xIw04R0H0tL(Ijs}n6`p8-x%w%JO98~|UMA-NlAMgCQRia;o zeXRyi6Ym_TYQ}3qp+dg`E0$vxzsJXWnrlfbL@#M)-1#E5uBi7~S%iQ*w!FOk;Sjus zgMBFG^FT*EiH;zn(&Ug!Xf~?`cR%pLAcjft2O;=Qmv<_0Dy}7xHHrv%qMpaKY%0*M zri!dT?o1iLzLleKG&Dl^+aYBG@7sn!x=XR{Rp(^X;tPKK;QDQmN3FRMyP7E*-|z~@ zGvAFle1D;k(o5hTaaGHnP2`B^pRw{U1zyYcU*p6IpLcz-z zG*G!w`!So%TQ?+Zo|z9mfB&T_wIzegV)pfo=|h;wv^?bl@d3Xyhl=7Ebf)L@_%;fE z(Lra}6%cJlbM%;lgSja8WuzIX8faxq#AU_;s{_s8)-43u7WP_94Yddr4gk3ec&$d0 z{j|i(k2iIn4d$zn-iCIzfIuj(tZek&G$bOT2UOmyRg#LyejA@s(EqAzYFIG{?zDRW z5glL}y}gfJSBFoJYdCKes$}UDKQghf7y)k*np+w`Vp(Ts-14uNeyAOl86IOsy(#kV zmb%y*6JIWM4#IhHdEngrt7r>ZUZ!oCr61w1>H3nl7^GCM?wX!gO1L>9E8eN}CM@S1 zRrW2)xeM8UkzXa}C%>xp@ZyyPlK;cmTZcutw%x-h7Am5GK?o`^loCU?qNu>oASx+c z(jhI1phyScdEaoNi7)f{a~Bs?*7S#oO5}$ zFJnSq#>6BoHuk=vB5BU8&sX#t+uLsuH5;!jjyIRSd(h?R=osn&l&Z{3c57>E09v8` zPf_v?V9$PiH^=h;fxjgT>HEHZ4e*OkPfvgHgwW~rshg3hl6BuY^30*tvvYGdUETRn3B@%@2~DHdt;aG=JF>rh)7tuRNEZ|-=fNHzh6B0! z{>9?$hoh0Si;T5Lu@>s)A(o%RnQ|_OOjnH?104xO&Q$br5gaPY%1k0sPdz;kBwj+} z5@jN*f-YaW1T)!+ATStl&{d#2i3tmXsj`9tz~2%Q5&*JkpOlo8)US`K4FXGz>gwu_ z)jSM_{Kn_XxHoTVdmj&yiyj5nhQ02O44P9o$#65dxw$J9Phbo+KwNT__c>>!Lt~Jg zlup#S+*~`mhE&IYypfhs=Wry6_;gQi#8T{{{xdGxO506A@(SVP63-#WD=jKf5$Q9% zg(l|aqA)<_@oY z%c@P`O+=B-sT>I9GCDcjKnoYGZDyvSs#;Bpe*gYG4DQ#~)@p8E8*iWU5wP{VNFEXp zaANym%$`y|nx)-KSMqhhKDix9Gvy8uf&l->Zzv!p-Bv!k6(og+tCk$gNUS+4aU&*e zp^Mk=y+rz~e*B!tkDDFQjMFa@zlN}?hd~9NQ|bHw)pGQq97buojxGR=&avqK4E7GI z(dPHf=jGfBao654oql1t$nC{#(&`KjR6?M6|)tluQx!51?3`86jVusdO zac|F==4vjb`Sg9i-dZzm4Ek*@qM7mWSn`k0pA#t>>FO%ozP;RyBtL$<#MNM4bbCSc zV5BS%8g<7Tu`sXEA-$chhI2LuJUrD_e~d;1Z->yy-q{%!7Y7;^Z91Pzpep6mugSOQ z-@9Ov4jR#jYbcq}z`(|yp35hngMPci5gRXKMBkKS6_faYRn2XXHp4GC-_VCLlB z!1iI3-bzH=PhpmBQGHS_v>qt|-X0|-S1Lg^g5SwnWRh`Fxp0WB_d%$%6;5^o7lPg^ZsD zun%Nz8vvnXzBxq^Zm+&^EN+jMv9V-@-y0QyiJ;rr(MWC{9y=>50J?Nl-WUr39dm7c zz3Exp+%5|UdU*E*b3aDz#pI%#8;o{;_QdYhUyn(j1 z5C$;Kc>o#L*4Fl=#LnfgPv~WXg8~o1mHn45U*@Yej6oqq$Vo{{w2Jks`D_nHi zDxZAVQ26jga6<#3m;GwXm1wW~w=clzP*7By?JM>tCB}aO{-IPR1l|o(S{uWmD-P{@ zO!{Ls?jseF2tIW8L8UmpYHhvU*3uHg6(&fnamjpxeLZQDmy%IC$1P4gRVmp2 ziVqg1Y3?ZFL==Pz1RdSJg9oF9oldVGB*3r9M<>v@3V##bY=N@MH%5Ff=bBPJS7?g9 zR8O5sh}nBtfnFG!OSG5c)j)5dc4fkWDmskr_3K||_Ea*^2j6WuLzoum!eq?4KX1ro zE+LIrka+h)LoT4-Tvk?);AU`5PT#Js^$a@P!5b$dBS$YRPUQVYsSHf6nq^)2W8K3& z8gldPGY%nB+>sbCFbz$Jj_#ZDU$!MJjYdj6wdpQE{6W4IYp1Pw2qGgJ=oJbOr{aiZ?$yF)IpM>kMBD zvra~INGV{Rs~^-T*L(PRpXo{bn=Q{m@hIo!Z7QlUrfhR%EUE36&@s@KZ+aCO>z0|N z_c$ft;VU_X3Zqcl$++0qPZ&;`Z6(b+FWnxLuGwQ8KV(`WqXk3L!@_5VN3qjH%T7zm zJwB97^*!|#4@k68H}2lOpsPTrHxF~ZYp~*i@fsa|Bk?qbvm4pJG~e_z6O64vHCA(zF}{6>^4qrMMa5Snl6)39 zeoYO%GsW6**Z6|TZ1!s(e*eC&aA8@}WmCm%?uFat?Dm%b!Bc&lOJ@{h>Y}&Jfr6c* zk8xhPe^!>h>lCTeS zC*uZY#0+l*1)sWt;Fd!WJ!i~`Kc6!CX}GFu6ik*1s_R_8_ZGCtOuZbwp7k||qQOSc z^^ShO#jPu3WMpT_$?>Wix|3G1z(*)Ngh{CA?d^qmer4q?@W6rw!_W_P><9!Dg0m*b zj+O5kQr0QXQxa+G14TYWUE3Rq+IIyD7-_B=*+zKMS&2Vw!#|&^+J}qRTDoD%^E#t| zCA|iePMg~s^~Q;=OCu$1}w6?PZisYl-q^S zxw@^cj1Vt7J*9k6zh91?G)T^+PPSzz^e~M4_4W0kJOLROGb`)Xx@e!bQfKPhw=E3~ znJFpH?BZyj7@l- za!X`yMr#yP2*;cgWmmmaSBLm&JNkCL5uaXFQ1ryC1vAsw-uOFA=`}nYm`_1&tJN6z zV&+Tv7o%fx1Dll9AEdu(WkEUAMYLHJZF@5Hu@s1yydqL`o#t+;2_N*Uj%#8SLK>Nyvz>lnq(DtU@d3De*c^v4NfHv^s~t*2mFoQ8MLAXN*CWr>q@{`L zzlVytxk6iFU|^uCO6iNfton|93D_t&98Onlw>cO|89FM8WW9Fn+Ex}BH8uFXz?zyJ z9E^uWwb#hl#bq#8B2xFO=C2atfge>2~n$?fq9FIHW*R6qWLPiM3HIZ z0h;Z6l;*bbkt0nBUubui{#O40e(7Vr_y{DNXY{4UI6jzWddn?()E1rGy~6Ha3(Z64 zn+?g7D=#)y4-xw`1`1UscvcOKvNo#rN80-}#B*^5eYP!BFDEijtnpmQW${PxaB;Eg zVNg7_6H45A|FbC&GcsaA%PA-zf%}48X2WLB(!Ldj`K)OWyZ3h(TTaLM~)n^D{1QN z*po5wU_U;pa$H6)J@qA-t-7i0&bQ_@g4R>;_P3sh$eY%3d*qdp5aZFbsx4D$->Y%L zmi>{U1jl*(`okk5kNvf;&4y@hr-+15cQ_)bdAj*s)=I~llIE1G!dBLuHpXSEL$ilX za|GX?In^e^8fH0I9c#8zOC!J^C0CU*M^nFd!<(t8Gv$4w8UKqzzTSa>1urFPgK!hp zMba3rxMef*x-~gR&g)?(hCXaX`V3MlXxa>-rPlb50ZHCxeX$a#n?mBnyHyQ#Kx{j2?8t*Hi4Ry4mSG z8U0B#L-BDu=56+G-7W`Gu>~*_J9?jFCZkBiM)Dw$fO&m;;!W9S5UrZGT#Q*WaC<|= z_>weA$TH>wGw0~~LfY-iI+N4WTeO4aXSiGPL}Z^~_)A|V1sW-+qNO)yd#BTrlAM+# z_bxQ|7Je4p*m@IAZjd6e_V#*#{nnF|zPHsN$Jr#lr?Xm^`=d`2!fw|7EpQZDH1aj2 zP@SEg7NbPl|F~EdNMF1(XQ|wI+2BO1yu5E37 z(|u4Ix%Od}-x533Ti3jnFNV{6fsKffga=BdD(@V1eA9fJ#{g;sSbL>jk3%It#AVjk zMLkHxVwb8l>kb_u&0eCR>5*FM>{N8!oP4k8;^2`KxEVCQIPPg)Tqra>F*=oMVv?OK zD0Xg?o+7PO5&B?INARrmbgqzhM?9PiHl` z^@b_=$_vSY;Y$~}n7vLc3{-@Jy>=$q_-c zl2);p-OBg=Q!KaTyo7~?#l^*etycDxst}TX4UjiKKRr^D@gA7!7M=(B?*m3)Z=ZLI z&dSC{ce3q`>dgspokt(Pe)$47YSh@)c5@RgL2>r%(D3k_KNg}hB_-v(_{LdOYA0RY z%iF=_4uY9Wd-m*^vPZx!AS5KjcSP*2dfAB+cIvg4%U048Oe^|~m-Tqv)Eed_0z9CI zxfQG;DHY6f^?bPk*_lx>eCeX2t=-+-ZKfum4*uCboEMb*4xg&Z{vpxmfy&jKI}xqc zWx4Gg$T^~gBtLiVO;Qr?SVX9g*!km&KYrv8!QD(uPBtxP_PvhxXm7t`VgildH0VC$ zS*U8|iPzl_5V~X|1`m+l!qPK0m8-7H{W9cm2S-O_@rdO9W!j9LT zs~oJT7#Yh|#gZf2oqp(}!ti=t*tA<3anU_n=Df$u%EPqBb(p+gm|er)a&!;o=+VW6 zh3b6g8)L&oUG?!C!f~|H?UrQ)n}YRTxb!$u-M|z!8#K7xfpZ;B)abx&CrwqUt9Sb? z-#L6!1pPw*61O&#GmBcAO|SMl!{GA$Tj-Oqm5J0ZKWKUc))I1tpPJ!)Hi3XQIWYlo zW~UqfSgng?RJ`=T8{gY0tq|%eaOwrl;X*^tE^Fo$f3%({Au*yBb_`N{Ub=4wJSmSy zc~k2?qjvVf|BE}JgqY?#zq&D>k0_CqxwR)WY_!J@$&j6PCBb<7>Jc$Y{8H<4uATnF zedl+62$ib%KRQ4m%%x(hZH>dwL|(sol}8sQcqi=vN8V`qM+(`5%up>gBVqWwF-<2Su(I(;K}V44&> zJaeRosg@?el8m5;CM7Ykz1DspgAv^NTI4sNdw1q$q`kj_Tr9uv>$QlCg!$8UYy|jA zC16uVa7YmnAXfwR0*R=xLlKFOpFA0-q9;2H^||ahqS+MGbd7H?iBVl_m@b=yUZS=N zc;`ZM{@KI8KxX8`qi84c){pK9I2}qPK%qK!5pH#t9^7Ho5AD65xF16mjl?kzFHfsb zQqTz{rGPbNBWB{E>5wML)7SPID&cNfoU>?;C)8U}l-_I}Rc17CFNdxxyNu5z({TN`H{nvGI9s}rtS>?&)!M2jAQVol+<6%Q~iesS5K@ezKQnH!));9aQOz} z&R7yror)^omh{S{DKE`EfJ`w$;ynCh68vSE(}KJ;r(Zoo3LXx0q*hD+=mPNR`+}*d zgR_NB(_fC=l_8^)PT3=!H^^@i0se_Fm++EDRBT8b$o%iRl)Ah2ckruar&QyVYSP6} z<#@S0W3x_1@{c5Om$IU@=XAK^^YiD{mYBH*U$9BaL^8`Uh^${?qocc4d;We`?zjoJ zPMLQ-ZnOEh_zS=A@QPGYI$udW1r4Tx4{KzyiY=pgQs&}S+1rg6$}aW5mCfP7aNhRW zQ)ZV$&Rhvb$%!rTiL;0NN8$m%E`SG+0zr5e#6F=-{KpAQww=Z$Q5jxlk_WzcQ-7n z4{n~-Ff&UBH{!Q%m)fIR8;&G|r1+iXM6QmCx_zP*ia37gSlYOJYb#CKxIS5$iW|0Q zDTNI!FW;9oo=n!~^5cs1QfsRA8{Bx%oSlqcUOn?g&9f`cIc|dACcjJo%qpLS+5q=!2^U9lP%FZ=Q;_(wY>92333Q4=nTr51* z>o9sqSd#M^lUiGsUc`6(D${4O1*x>?)2B}ZR*!n0pZ^eMP2S<1y}hi*4>bo#1l+nF zpO%*wQU!LG(vp(eC)?iwLq5|a>)kt6Ha3IN4rp)Bo(+5c?j6s19`n`$yFp1q2SA^% zXyYVV_|?A}$w^7QaErKe?;dk60hJA!F*Y?-a=dzoeBw!w9%F25|8|kJ9q)SVmO z(hbx%+7`N?X#MI&2qrrN@5E^sI;X zZFt%}ZY(B)_*#Ur;!?CBbpf3OdY;ZvlaLP3rslf;ZMM}?2Xpy zGzWKnz`-N9O^BRImY(vWoxBY~!^b>cGBz znbASul1qH_sP4qLFZ%B(gflH|{MGFhu}l9p+8E6up%FouBpq{dbOacyHC_D$yzBo_ z^d2ir-ID`mI|4Vq&S7)1V1Od~bFPu3nC|X=RYQY%oA3FvXPH@9vE0m?R_>|N14mW3 zz1CvP$#2EQV^z~_PF@l{Tba!#TEe-U z$W3K1vIn^uM|6}fB!gnYh#7$>udSUf$2KkXP1W&{iVY{r#a?oXrjxF`zJ7{k4kkW7 zGQJn>(3Qxm04FRJyz@k4+L#QZ`Km``;6gh@TUXTk)3SyAu$#7AkxY*g^j>&IhDF8#1>>O_a*iHDj<}yA5IV zXd@ioadNax?dB}K-1w44yskovo1ol>VM&Hh8SN-;xqx>_;O(VFGMoMLQ0 zdR(b}$4{Iy`s~NjJKg6Xg0edm8Dp(9@yy&#O|2W$`EGTG_GwM+*@0`>(1aowNm69k ztFJ>oiH2c3QiR{=2{6qljIPUkhdpA`zD=*<1zO~xMa@+kXItfgb$_#SE{z??fv)b> zRv!DA?hhXX;5Fi_v$OU{i3X1;d41Diauw-t>>dIP)hH6T0)wif>!LE;lOKh?rzzd^ zryf=sklTx&Xgr#`h%cZopeewReYe2e`K(7xWV`hqeC&C&R=!?#Mh40Ho`3s|cum9{ z1IQ8nS<1pU4fa8u%TkAi2bME65ZaQergu*|TRogbf%;1&p!_ zM<#PeNZg2mg;ehu*$J*!aGMc7fBfTE zDKY*P2{|oaicImVxUsb)SLrxv`*!t=;DU$*-&p_b``8t+ zub)3(WMP>Ur?J5!!*mx;=-H9cEeYkTIjn!o$+5QY=pgBJ`qBCPTy_K_PnZH>m|2B? zoCHsU1!(epe0&rX09hk?-vBv7!voc*1M*>LvUPP6U`h!CJ+7Mwul;|@fHgZywU?9i+F7<>Y-=KsUEuUBPRf*~ij- z$C>pJGbYAk!rIlF)_8ks6Y67LcJ}sn4^(AkNfi73sy5vUnK1zBadUB*8XIe$#vL9* zi4#h+IIjN>RQgz6c{aEKfP_B^dLb4V@Qxpc?ofb_FSGRg<;xFX@(Oqt)Cr(l9!weX zNpo3W2F}AANpMk-$Oq%lu&_Xf8{*PY~yvkd8Ni?~dx;iH8s_4S2@NjSlH;0LBeh7Rw zP#o5%x=O5V8GgLW%+#8GaX1&$<&~WEa*j6b(?k3ylzUiyL4l%mXDAqkB{#`g9*#3+ zE=^HMvR?gktsv5_NWg8@3uXKoAB+$xGvB9mm$|vQh1w#)SU)K#Y1i5PD|>sk z-VsG}Q`3lu2-N7%#KZ&`f-ERmm7gLHiH*ImEk{H`k_U+emHK0DPTm^L=+5=FsK^yR z&tQFNGq%dAaa@>wIKLxRgYWA4 zD#+U)<3h^M&dvtIxiizwGFCtf(bD>+YF@Ymk5P2eWzd)R)>TXxSU?x8j)ZTJ9>U)A z>XC^m{Xz!SW9edvsgD40u*}tm<^I~(uqR%2g450d`|tyZ9ve9&C`>C8M*bhrbJ_q? zTyAa<6C7Pq11B;vsouGhxddA?WGnUbl62f)q6(Qa2of z>9;Vsgh!rf#+A;wyaJ0@_bVkq;}JBJl-2L`fjVI$&R~E?o@2HD4SA0GA%5)|q2eo? z?i9_9opLnlPdS=chn3ej;K}uNKy6jyv$%T8D@JK*8>w5Xu!k$hK7an)eug!=Ml9}@ z%Si|6RS#6}Gmtlm(^4#K)HgrLZSBZq1_LSQG&cjyZ@0w{PDbA{3g$ z#%@&+fGtBDmE)KG);lmw0zk{5Zuw8Ci;FnMqUiQxMjhy7;22X2P9;Tq@FHA61lwE{bl(e?vdY3ty)2Xuq*urPp$t^;8!`pS1%vWLgejlS~57yP-7 zF{6!-QJ-#9w_1ntq9Hbxa36+B{J#Q-ug?{hZ(*JsW*hhiGi9v4DowM)0GP0-NZN$i`2f+})BJlpl@OB|sVX`j#@q zLJL8eS@f*SPB~$D0WICsO_XN0)2A~_bBqCcA3Wi-l3W4$y#ANS<3|9d}H zOpqkjea}{r#td(r$Kk>};RRgyLHag(iS%i$_{~&Jy$w%>Z2huNJAf~3x0049F*Tm~ zBZ;qY*x6qeyEaHH051HBRo!vAlY484TEsbYjSVv1_&5_Y^SuJQ%a8yRu?{Yn;&c^$DD6@h1Rtr5D1}Q6dI!cL^P_gq~tss zo4;G~_3PK$+uIu`f?W+1S`d~uUZ--woMW}vHG8Rkb9c?Phe(9Eex>tC)Sl<$wAD9~ zWb*|-$YaFBSe&Mw-mu{8M_M;}N_=3GcKj9CdN8KMqZF_6yKn|UTLkre2SsRq;25Hh z+EN}U{GeIrXgfnN6~f>!LN4ilES!DpK4fKWrx+BRaCTZ*S}&+7AuQ4w6?JfD>ib`D zj@ClD8-ONivZGR4$IKzsqx*I~{8Y33RD#U%%eX)Vk{EC?HF}e&K|Ujt)rH z!4TK3CDl{X+#F7J5+&xLxVP9U2SiBP+sgNL=uT1EX``;1J6P>hHQiM-dzkmzq_s@+ z&u0js6~@!ruJ((A{-U=xxK+55ZhN;SoN@V?RX=|G*ba;J;mi1ydLue^^N(}oa(VX~ z($=ARs6D79x`5lsq(g4J!Q1TeXb8*-))OAUo|>TQyPAXq=xg&+JYr{X_FvGNBI6Zq z+Jz7P#HrH`Xi@F`w_?3iM5?s;u%QV4Vi5G$1k3FL0TOdm$oGF%k&Xx%{I&=nj!A04Em zudI3Wwd683`8`>8;EysiD;4r*b?%La9T)@g^?W%UP|W!j?!H==AMJ@JQ!uK&{h88(5_57wi0^!Z$dQgY_ z%jSh|R>RW^V9eB`XCV4;w#S6QuF@*5-B6O)@WVOLjnVEi?1cy7!RlczzyNSQ(evwK ztT35OJaYlP*xuEpDldP6oIC|;F|b9i4Zz*sg9KO;|Dw)HU|x$9t2?qNyxI(@>u#S3 z{4&c%)A#X{Ylel++sN8%kDfj)gB^kqXKv62M;RE5<>meG*#l#`2qPO= zS${B{aChHB57K);eSua+K|#U8&CT&*h>(sN4mD~4}N^kr^ex#2}Sn)~YVo?)O<89ZASR7XJmMN&rbA+1E@IZY~hDPDqNVvIz zJ7VB(xHZCI0gj7gj7?AXllbUaDy#H#_QK~ zM|$!tkVPumiR;*I7JZ+YA##aBf0dDyyh~wJ|0skn=-j z{!wD$)q^NF0npc%SWltQ-`^ikhDt~QEaOQclM7a8mcq%&DeDd@{jcH}A0Dri>dsrA z8GrM=PVnZKd>FZ8|A$`IK@VO<{cFyh%0(>!v^Sv^51j|_+>csVaz6|`;Mk|NM2 z!hy4;lHohPMg=}P;P%*guonl+DRkdE2MGzHF2K2M9US-t3wby>OX0q9-@ffowMZ=| zkaBV=xN=^r3W`N z597lMzP>kng}NQR@SsYF?5(|%b*oon_=QHF^KDDBx>P@6_EH8;?orlssLFHPSjkFH zH&aw>g2EJ*qf$zId=r$Cbin@MU(lD?yKRpEn~FcUCvp$ss?j!Ay{q0MI9OEvnDD?A z6TXp=k+*N(3L!D!;SizHGBWC&xq^@A?a3??k0)miun&4YwIKJ{VhS{w75eywyx{t9K5)t9#byY=`F@}QW+K4)KClw zS$r!2lRQk=g&xc$CZ_&q*3qG%OKSP-EG$x6ZFk#8l(g0vy2xIX@#V)q`$MQc$oq#- zU48)91&4*{*G1qIaYiS}$-(BUL{zI%++k*CB<-z)<>*URnzC!K-=U%6F_f6+NTy&( zLc$G~!fx{jqEn9MP9tbu63O)0K(($|epSiAVS^BH@#5$5 za?jS}ML~2b&vQ;QWh^;4`B#clH`ilkDewzvXD^WIA^#g-ke060c5Nyf6AK-ff2kK18h7XpPqzNw3X!pWA&v9U{cGS3SON8;HN zDS%v}(Tex)UnnqECQQuBYwPQa_M{?acQi?UFA-sx#(Y^o;2zXqSuOv(x%rMrT*(zt z(PE!!0}qXvf=wZcCR%|;k8>&?yNVZ_L#LPpt|Bl33aXT6&g5B-%51H25e%OG^>nnp z=msv~4EivOed;0S*ksneed0Lyb*@GE`K;&%+eHb3>RS(t|8r8lQ!r34pnYV^zkJEu z{-91PQ$bjqh1;k&0iXM8BRoP>!7IS0o1X>7Zr;W(KK5>8M_ZfM=59{jNz9%IbUr81 zpF|D6hJSlIe|*DM|7-QI)4+X0N+8HjoXBz_n3wpsxwQ;TntxuyBh(fe1*~Uw#Q1*! z|KTsRa%dZk1Az)sB35n;Xx|gJ9?I$&8<@RzzGZ!^h0aNWnbT`QNpKH?D!Zfp0SY0t z|G)Ku7{YzyYS3sIuFKlK&NLKi=jYF#!+LOa-Ksp+*6*nP`>Ecj{I9UNYlu%$e9uZ* z%t7@7u4gdd05%{XyGtiON-s4^|g=BQEZNZ-3cWBZN0$JXBA~- zQ1^|)y55B*Rc4x^q;Y9Fpp2h5&YZ5Kb;0L3|X{gu>R9( zugL=iKIozd$*)Fd#H}st?E#G3p314;8rIw@D=mG(1kMWKFC{AJMxVizyeQLdeAm#> z07gulOVHbcc4J5kBobgew-Nbr>RJg^($)9yl+pG!G?WDGjuKStbc@ZAw=F1+ampJrHOeW#%#nuWq9J;xW+H)5{LV!4esYfaz_rAlQ<&;>dyTsp@ zSaVI@DUa8{g|U$QV(lR-^=+AQOA_YH3-77rmVz1T=~Ru#k^JxUtQxAW-hAxmCj%3h zu*gaVMfcNQxe7>D=x`HJ+RM8T4VNQ4i{A`Da<{}0)6Y;qb~s1<=QsZsc@iC4MJN42 z4@s_QW@z{b<>!D=T6mW80-USlKay5DFUWCVMvp}aAR+SOvtH1f*RQ{5XALZ~^iaQ} zxu*kmOj1%u3ZIP0w?GyoZkxpOS9hWemly)8V5Ie^I3r};morvu_CdY#{K!?@l6s(t zV7p=QgbI0a|MS-l$;kH)=LQ-Y@_U42bss&`q$O(fpv==X$nwnm}7_eba2J_si zswy%x;oiONv!?;PgNy|OY2Yjm-K)vCHatAcA$txWhYxXY7Z(>{H@tzPg$(--uy~i?BD&zbgq=j^2#l@xSRvpbRy6~7fy1R_X1=T)pPlvh^@Wty+S(e$ zYu@|x$eD-lyr#bcAqG%6I3*p*eC)`-T=7tjAllvC)zy_er2bH0xBa>USK>{Z1R}xo zhk0(JtLz=hHjh!rQ|rV8#QT2j-m@J4$FS;gt_J`}*VF zM{s&N--+EHW*y!6;neKxmGj4GPvV0Yd=@)vNi8mm8CIG9i9=tW?bAJpf1Ct9N4^YH za2k|zapN*s%0p4h%RIElpPeA8q}zEMXW3R(5)`yVeK;^vGiKNS{yYss!@=VES7 zd1uj~)gwhyyhoNjU;LmDt=Tf#u07!0J{8USidTVNmUQ3VSXcbi55BL2Z!a%HMHH$k z;jJWX-dYkNxo9M_^TrZk2ewM)Fi?J!8x>RU!7z4-a7V5La+wqP{QS$h3Kvrpd}vZ9 zx2$5U5c0gtd@&dk%eB*#GOs*etBAd~muq3!ae@Umo}m zu}_w?$Oij>x|g!II)D52^C*SaDijIE^&v4b*TkeIPw5Pj=SJq4sViBdJwL>aP8#HY z5cm1;Xjg0aXl_3|U=EC_(*`Yrg5-oqt%w~9Ky@a8o(kuHP#uk}Kd9@POuKFzh z`WnlF@HO-p=Wa)T(u16nb+4p~*W_9zV)7^{C==iWC zoSGnJHq+PZ;DjyON-JI|E8hCymhn(7pqB2XqWJYGBnO5c%y0DrQbutkL>*?jT)t7A z*?KO6r5E2tG39cF99VI}gl#Fv%G#HD+D}f-^AVw@h)!<-ZG1JHOPIMMt5o_tyX#Vm zrpMFip~d(S7KJdLtH)&WNGJ~*B}wy!-M9*z5>oBBA2nfmppxC}>MM$hT=E@|zvff^ z`?hW>qD@C?LOVO{ro1`MqjeP{KwR;o%!Qov-S%qImux#bd6CDB6GN(-54TSnMdc&C z?!G1)K1)F%M<49Al=fazlkcvkeMl5N(MI(4-P)m-w3~DO@38c39pZ^4=wh4kSxN6E zrsVI%f_at{p3^<6UZR((3c{HkzZW)z<@NMz*GOm$)J4uFN;i#~i+MuG-iCP+Lx!T; zkzvgfvSAy`nJ>VV65FP%79^9Ui&NFjG2Po??%EsN875e;)uz+`dB68fVh)PmE0p%a z1@dqn7vD|x1G?Gc@+TPnT|P3FjWepJzMy#Q*fLhUtd2#z1A*WSMe-|X^x97;=JFYC zy{REfjKE;D%|u=_S%7?`sD8_nDI{1Unx0+0)B1rlURSaqt>IJ)=R+<;_{tmXUh$5K zWa>!5+v?(y#z31yHANTIn>SU*nUBY_?heWcw1nnYEJI@ND~XFAu`4qS!QJ#-jd+$X z567N|S;*e#pPD)I{qAABV(XA>#xU2$g;7fPl9i-2!6n=Gk2UKO#1pq9Cop|%4pOqR zA*-gNEEy>6i4?rd;(^SICnIgG8znH7c_aL^>E)#tflP-|6K=}vCCzio=X($);zl|V zq2BiLo!r)`xdf)^+pbti&6q~&6dSnrg!_hj|5R?;c->!>G_omMpZ{MTi*SM%mu}DTQ7pC21UL>+S zsj0d-p<!xVY#FGDn8K?FXwPU*bnG<Q+PTC(l%w#2?R zH86Hjiyg`+Q`nVKN>VDobSi^s$OPmKQNmqHQc{y4#Ste?k4Uk8Y0lYScTv{$QE@?R z>{eRF)27Lm9TA*W~&#aq?Apv zeL6L#;C7_Nq2KATu&wR3a+Wf7%rmW;f|iyLALzIJ#Qwy(xg!wk_F!JW!6{Mn1qaQn zsMZ!ujrboC5Mc_G1B@mG`8HQcndR?9l7E1g;bsA<6;6?}l5c(9C3-+3Wqwn&cDcCa zfaV(k+x45NLq?CUoNp%iwaD6lyi9+bs>nWrs6acYN;i0gVz2wzfM0=WuCBjSw7o03 z%=Ii5$#hyBB(;CCXYcsLL^wYuLbP~Kfi_oFLh^t)KJ)JVnWPBd^0hIqSLROs^@#+J z!qM?}5N?;YDcrC4-1?aT2_7DRUsk|eVw3v&8wjG@;kT6#S)>GKKk=UbnZ+I%d>h%x z#5;^|0s^f{8{4J3_o#8Tn?wchv@IiSwiG$LfV^E8SQ`YvgPRQ z@T8WVT7bYa8iwXl)wFFHD)&`rZObxVb^AdAB_7?8D_0TunF(t;X8%G zqyB?C&s&n2(KO+b|4~cm?R4u*;f_T7B?#mcic?63x0$_n!~1WItS71^|hDtc9nTs<)1iYEpN; zb9l0;(O*7by~mWEUI`Ahsd<0*o~kM_F)<8nLz5hxoS=>e0{wUjNVmb3p{Jw-Z`}@x z5tJBc9w5%Zz`3ZX=*5c{O3cGGgG^1p3%*wi0+JGULQ`ScQecn3(NVx3gF^h&nKRb! z|AmA)`XFYE3 zWuUe8{xlGIy=x#MsINqP%GR%LjDqvm`wzmeOeI8_fg1L1|9t<4PppFpY)J|>olkGx z0$wn1`$MgajVFM;5$XXtm}cTD`|XYaSNcDUJ!HJ_d|ikOt*ol=eBO*28SaV_d1!VC z7-g4(G=nmLQX(i=0EQDB+$viYX=X-7L`RQ0Prk`pv45PE1yc>=xVEkB5;*r@s$yc! z3!vT-Hrzja?AWW>4PV~g^ZWIT0an}r*zf-X4cEt`;XLvJO3nNN@g_CDwwIikrsg&{ z^-J8lM{ifgh{iY2m{_>U9auX_!MQW|CPMsTKuQW;LKzHRZec+|U+D0?F%i(MU~;2h z1$P8p7-|)ONg(k=9AiR1xTB_4)4ITAYG|lcg~a$2*7MMDd>j9mYW%v#Dx|pO2CyK? zib;X_aEg*rRZ)?)?>T5-HtuWtv*k$nQ}GWB4Si|GkKM<<#z#DW=XB=KK2uWcHSx%J z&JX3kwh6(oTE5&CFndp}-?zc(wy0|Z+Rng|MD%R_{a1m-0T>XJ?@xa*FadGU#DZ>C}u&mh? z>yi6oPi09z{6Hb4bKqwTd?a}bA;FYIb0YvxfxSD}HWN5m&|$HQX0K96J`CCfU*=SHh`DmeU!>4**+{egNCP!}*g3kAX>YlyEj2or%{gMG3{;T&0b( zNltdNxl#Rlug9E(Zps$9dc9SRyf}6iw@n~ zzbt6$MM9&IrM>^{^lu)3!C`7LvM)T~v*6kQl!Us|^Do@PBK?J-H7ijcmK9m`FkpDC zn&+qF%PfJAMxjEh9z7yh7DU7B%iY~Qq7Ft!yMQ@e9Ozcy?8l1%m0!QgZ#`o?$2>t3 z`4#y))_upP2PwpJzjc)_3~ld{)^0U=L>LwiT!S7+J8f*t5CYGt!vZwk`}SUSa}$N< z>KdmA_*iYN@8(-s$!CAH=hSZpP@kBrfo|ID-D%~DK^I>z2*`Q5p&g??s-u7a;JNSN zAaPXW%b*}#Jw5DifmdR7T3U5e6MB_fg*g*Wn-m23cFHQjlz|8wz=7ICMG18@HwWFO zbGsgN?9`Hfogw+}h_eFSr#u6me9A14wR}I@WZgarU}wC758Akt4u@T;sxtWzJOqrN z?hurmhoUeUEinMda(qpD6=(WCtUQ!b^y`1mxS!zX&3Mri0l_zZd{$sYi<-=Ee^-1J z;kJ!$s(*dv%e&b_x>i=?%cXn)&|?2ePyPL%ZGnUc$bI{%mw)}>f|d@c+l11dWkP&E z{3{C|`e#=D<^cUVKC}M*mQVlu`vN}RiX)L>CwNLq-kK?&e)dS}mmSo3 z_l^(Ye@_enmKCY>N5Y#*b>Gw2_6kcvSM^$CR7&=KG0f9*^9z*vbv{tal%_Xa!8kXr=1)kGNXP^M zaTIa#nB$6*8Dr7$s!NTELEjT{Y{{fMJ{?i!7Wd4;GswVU2#6OO8yf+^5;CHtjhBBt zy9+wzZp+{MX)Os%_j+0JS$a ze-RQ#YU%0%6m?5>`oHlLs7`)`>!%=~a)1^OZ>Qx3q?{s1JFw`H^~uSMGNM0b`|NFO z65jqKbgJGW0`LeVWdmQHr#6z!7G(cz9nj(NA8GvBF3v%4mKtt_Q%}LUTsiC%D@{7( z6jEl*idj5KUFrQkfR6t$3w{m2u^9n#ru7*72OI#E+qVNfOuO^t8Oa9np+2KZ-%}ER zg9+fv_<7#HDUkh(oNikifD-N;$Hde58N~aUf5yIr2^ou4#s}}bGrenJ!5*%)lb&(5 zpyNNorg8MwQhErhmpJ%e@?-@)0G9uKp5$YVS4Vj15m*fQPQgJ|FN&YC^q|9}K6bCgVK*9_#*G-R<~G3c}Ov=-LPq$gi5_@90>(oQdg` zT!wL?dUzTW9D4>>F`&4&2tz%9bu@C986F?IUYKq%vLrzQ&FDpKsdl3Pb*!2|?jt9D z9NXuyrmGU0fBz2^FiAOuKm1A;Ze(G%F`dtl+VQ;Ft*XCAd>aAt8r`NJ(cG@ntnZ7$ ziB(4P%&Dx=8L=MVb!9<;?Bmq|qlCL~fYt5Wt-xq*$8k9kdL5o3rV1p^y5pn6QLZ~b zN4!T?k-({jbyM7UjsGtPU-%&O5((?%j zqy|bT8%3O`Ydr|Ul0FQ~@8RG4iYVWa$;pNsTt1E)`9})GuIUDj<-3VHTRm_}^#>&e z-jxda1IBmWetxZxHljH+^DUs~!HbU3Mk5tMKu!Rudpk{G!hgz+L$WTQMXd=S$^7w@ za=P7;usiF#Etv*`oqp4H*edY)5wcN0*p{qS#wCEd_>jR7b#-+ZC4;P4!F{umE)rTC5ks@S!_>RoRR|$8g&gqef0eNhC3bU6B^`criSPXW`S))Q?H`t`w7%I+9fZsS zDQkDx9RH2V9{$Jw{yryxEpgqYW#RK1z{-2NBbuoo3AD62Gi0r4Ybj^5iPvJkz52+O zd~(N-X$Ju&2s;F~{TL<5Y_1%Ah9}7j_sd=>_l`?lNYrOn{Lpmg%O90PjY7-%FUjbM zY;n}2X!GE9r~f3=`ikJ%uSUcZk8NN5zcP_B8t*t{ZSHgNEN7}6RO)|CJgbHn1^)Bn zOzSp3GI3wIfn4=p`BrG35!rr0^BNH-WN!wbjFrrx#2JS%$3OBA-|x@3;aO5LNlonr z82&2qu8V8I;_ZY>>ue}z2g9!4hBukPc)uI}rp%6N6@ei<>*^A34UHKI{LPV^~_AgL@Z5 zaXXz`(LlzAE|ls1uCyWPa>u&|l+%Z|+C&g~fqHN{9Gn8lw>ClL@@pBF)(=*wdwR;B zI(51I6x-c@YXX}r;6yJxl_@PP?adqYcc$cm`~Cg=G>V)Z^z`U!%fRK6k?b&L?fZ8N zAnid~k^{mKiNS!#-?<3PXm*kj9rG>+X=%^Nvz?WldkkrxJbBWwZ074)>^4&0+RmSXnJ`VUMQ-|s9lX6`WJG6&z&CRokf7_YiMa=b_ zjhRV%%feCIdQ^lELu0ov-E;qF@JQrzcbM8od`DPrseMTmF&+_U(?4ZDGW9E&Hyko) zr2{vtlP(W?kq#CzidFYk^Xnr5KiZ#2Vti&ZdWnk1^bQE$IO}k@`tRyB&Viom!Eu| z06kr*Uur_a7qHrc{*!C@`*%L8p+lVRJrB&xSPN8@{nd;00;kfUXX9Is>y! z%n8_0-|M6IpJC8^hC1wjnT%nThkiZBGJ4g)DnH5jDdLd7gXL*hDpFVleH7s`JzpW0 zTgnrSLPz-kSLQku=l-aGfPQEsjE$={3NKzZU=VU#d={CZAJ*7obu5slrC#L&*vTxG zdXY5UZ}033nz`Mg(`Jsj#LCLU%UjVgThrmSQ*4GgxzJuce(i|H9gC7O+$bA5 zE?4-64C`@*H@br}YaL}h3&Sj2{jSDm4PrNfaWKfoU(U$sL;Jk#g`HO{xZ4s9&0#ww zgD;oU?TDtQs2SHnF zxh!bCJSRv4;kBW8GJJXY#y*bRZ%_9hREu!lLUtfh`e{O2EL@+jd`4np!wvUJ4_<=2 zv^|8DZMXN!V*7MWOw5oIs4{Q=Kgzy3uBvTo8x>Im1qqRmk`9qjIt39Vl#)hiMCk_U zMkO}2=|(^rrNN@5MFFKdq>+YiY(USs?|bfj?|1$>KiPY)wdR_0#511pj5jy<`JLf( z%RB=mUFiG-j6izmhS8%(7xD4CL01JIoPLHhy^<^^H+QD9(%K1V9{;6f4Fy`LYRV_$ zdskQQ!7W|WEPE&Skb?hwFZWoM)4UTSf&=-wtSnll2%6V{3UT-@H{)@@k{ZvhzmQQ0 zru4m3Rd5fTh(57c2Jb~_JLa!eWB-jy^qUr47HzR+DVTvd(>JR9{QR=AW&l#+O`HTe zDgEWp*;vA*@7}kI{>z=T8>eHeNxL}d1wc2&M$+~$FDrOZ*go-p<>1jxOrY>17(HXJy8R$Wp zq8A=xLZ6X=^&%|eLAg>6OsG1$x9vMUeZnx3maS62UcTZGO7k{N&19M`Mx>hu%X!yt z=wRP|tll*`l)U{b;o?MqV}LJjKD$@o3X5=U-PPMwOO&q9-k(^r*X#AFp}7t|rHh%&>kX88enm8TDg@V}UEA zw{PE$bF%GW#R<+o6N8fki-oM1c3mhkSaqxt-P^8y>$+#vmYw!#TGUJXz;#Tz?v_MI zCRmJDXNc%;yeC0>hjqHv2el9jQBD0Z0&*(!N@Ufnk4863<#DFC3u0H6 zZ|}^SjcmnejUM6fx*qHdY2ESHo%{T*InbV$)|XhP!sbK2(^<~_j}$B>ik9ZFH*<>$ zt_u^nsV-Aq99KJubfI?sr7xG@g8mGRL(Lg>3s%rDO#8b;IP#tCkW23#Co@uq&-zx!m>Ce|fvcu&R2_NRJc?f$x;+(6@W#7Ys2ZNezY zQjHoSZJJ7vSO}E#r)MO|UnoZ*fA`J3)G-{YN$P&J%aoOO@CYi+fq`7?-xo2fEpq|J*R5I~}h&7J$SLz05 zequ^*F!4lnV|-Tr=G1Pj>*hkw7kr;B%psRC>RKk|)wP00D$Ea9?g_}DJI;#G@xzWK zp;J>+zHs5p^cP9VsZ=0opblcZjEYJc)1;>B{>o-^eCel3s~DbS>H%?lf(M1>(Ofrg zZnx+R3b|eL%;h}g+9a{Ts}mEuk%`*2PFYJ`V)<^^BwPhLwcozJ)^1dbh_HRUX)$MT zxAwl%tFtQv9x`@#nsHnVfq{<)e&~Wl`S`)CQU9m$*+WL7gQrYnR60Xz-;XK-qvjg< z+&;@e6$Dy zu?R+%@*?iNmqWZGqnrkJ+r!Vq5iQ8q-jcX+7gwDABywJ$j3;Zzzb=<1J@H$R(wkMvmFJtCsWvmrdgtk3Ei!(#-bN?QN?xsi?-@eDc>SEcBW7A`c0t`DE{UNN;gp2yIH?w>|u|+UEnzrEi`!6J+O&@kIgM${KOFXF=_eEmq z_`)Jy907D_A6+JI9sPmo_aDGULerqeyE>_Ow4tpNhfAdWTn5l;2?!(6(ZwYsl7-*m+5L~Xz1y&J$U<0#nr|7_A8f|JTulHZHCFrBwI8NlL8uA z%q9&BO9j$*$5%yr8rlSa)JoG*$BW9hdB~Yrg#_DdUQU)#$#!M!Vk_Nm(p{wrpB{L5 z3p>BP@y&L2LoAqlfG2my?df_)x{hX`WX}F(<=S+1cJ}`MMlH0If@JBlwN6QBwdz{r zJd1R>ZDG0M^Jj7TX%XIKH0jHep&O&ZoMC=7CqQ|L8M`nKP6K zb=MNDn1kg83Q)*SgSrD~bte#_)aLZ@UY&sOlk)eYC#7?!Iq8~oPrL~GBHK!w%v$c( zE$7!BKT*}zz&cgNMu_b2?i#zxgN2WW2eaBufFWmK@Wy$=Y|=*vi*xGN&+nisG6$$0 zq%m;QOn5L~4iwR06k;{-ry=YCs3ImNM%6m00*WEfd(woUM@=B8B;nA%V`a61PXwaQ zhzrjzn6FKDLe)Wf@xd~cak)%3uT`C71J%{5D4k5mk3LT>x*b4s#OpG*0Y0xai)m4< zTGuNaTV$x%6{lwP)S>M%ej{`4LOHhxlT)8p;JqzmU zeD({P>HDj{zMIq2(LqQo?6CB%yW1KBB&0K+f(p+EZ%h}V+Pu8B*4EaB2ETX^F!l8H z^%Zpf6|&nw9=#0X?KeL80GJ1|^5gnH``|MJS*#DubvQrf=Un_cX#kI82wa9X>%te}N_?cod+=%t}wlM^!feRxFX z3|5BYGQ!`iSSIq)IxbSn-N&72Q@i7eM?#{mqLMM_rrJpDAdt{y0*mA0Q~NAb%hvWy zLA7rCgstl=;a=S-G})H|!1#M0!8x<_E@}OVLC|BQRVbEVoMvd#yYCQc&n7`@hYkLoQe1}352VjZY+OZ`UlKk?A94~Jk`QXZZ*Ycc%+?lD zt?)32q63?Eto}uJ9cQE1TbVWitMNNdjce~fw1S#77d$Gd(4K_#@b5dk)|AHZw7nXE z^+}4kudLG5&T_+L>zr&^B1wjgUog2KOhhV%2K<{)DP?qKEt(%t`T3v<@j9xfZ@#nkulGSQ5aY}~|Jz}NIcq|>QGrxOo$r+N$ZY?raK z+4VtpwXr#ydgOi;Pe8DruuSt_i(>D1s?=4nRyC~z8yF{TtQ*Eb=883w&kz6|A)Ar_}ZU`XD-|8u^N z-g)DK5*L)9f@HqRRWz=N4_-cW-KdZYKcAxbjqQTD({zn2H@k2ptkto*YV(b4w^b_wwAmXkV@h#W^W4n>P_wr)d(vo zaSfY*c|5!s2sGZ;Vq#T3dQx?fgE2UBia7n-6EDxMC2t7+;EuN$5zsCJjug6spo4Q7 z$6dx#E(~G4*vkEp5`k^heksR^J1d}Ra@&b9;W}I!i7qmvA0}f3i8nJpWg@|9et5zP z{%y95@Ve7q49TA&ghaYwu^A*-%;LEh3G~A>LmRN}(;^5UeiG0)ym|MUCJ>%S*9!xX z9P?mir#{YDs$Ra8`>mq!Jw#c}+NLi10mn85B|?NyGI$d5Svu3XdtN`^t<5xiiKa=n zUwoI6qAs9(^jq3Z`XVA|$TaA#gFy=WPd##XHz%Lp+v3t1P`^}t@3Xw)in%wr{3`#* zjEV=*FJ~R2b|QU+)DT8qe$wfoCWu8j>x~UBiQkqbX4j4K`gr2py8f?u1c7`z=gJT- z=Fvrj8ugWw2)6Vcrt7sdzJ0c_Wo+l`i6g$WoI1snuf|(wN;{*$IGQ8+AyM#q%v^~Y z9q&%3#MFHO!}Z{lyTOH$XFym1l@CAAc?QMobzOs%twc6hefSS{gH5Ik-e_2OeXOK< zko;=5d|5@s+i}TfJL^P5zpf!P&+A?d+#pP+=%7M=Y0}BkayhFNA+@~)r37fq0)rb9 z9j#gGI*`;Bb+d6?0*&wdzUk@1*vm$Q?yfw`(~7G5VHH`tS4(I&Ec$1b%8TQ^ZIw-s zZKPA<$J}#r!8CdV?FOEwv9>oB51=~))xX%|1^Qv@bKl^!1F@zJ$(acv;aM&E96+K0 zL&SlE;@nFm$jF_6E>Kbm8hvu{e9AO

%^=_sHLP^Gf$9Mu`4QYcbFQ@2y~DUuF4 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%0DAjdMXvs*lU8e6`mW>6ge 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 arQXrK`uuS~qYLK$N<5Mg%X;wq_5T4`NGJ3F literal 0 HcmV?d00001 diff --git a/src/main/resources/checkstyle.xml b/src/main/resources/checkstyle.xml new file mode 100644 index 0000000..14bca0a --- /dev/null +++ b/src/main/resources/checkstyle.xml @@ -0,0 +1,183 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/corelib/Array.monty b/src/main/resources/corelib/Array.monty new file mode 100644 index 0000000..4314af6 --- /dev/null +++ b/src/main/resources/corelib/Array.monty @@ -0,0 +1,2 @@ +Int operator[](Array array, Int index): + pass diff --git a/src/main/resources/corelib/Bool.monty b/src/main/resources/corelib/Bool.monty new file mode 100644 index 0000000..8ad7d54 --- /dev/null +++ b/src/main/resources/corelib/Bool.monty @@ -0,0 +1,21 @@ +class Bool: + + initializer(Bool b): + pass + + + Bool operator_not(): + pass + + + Bool operator_xor(Bool other): + pass + + + Bool operator_and(Bool other): + pass + + + Bool operator_or(Bool other): + pass + + + Bool operator=(Bool other): + pass + + + Bool operator!=(Bool other): + pass diff --git a/src/main/resources/corelib/Char.monty b/src/main/resources/corelib/Char.monty new file mode 100644 index 0000000..50aa2a8 --- /dev/null +++ b/src/main/resources/corelib/Char.monty @@ -0,0 +1,3 @@ +class Char: + + initializer(Char c): + pass diff --git a/src/main/resources/corelib/Float.monty b/src/main/resources/corelib/Float.monty new file mode 100644 index 0000000..b88660a --- /dev/null +++ b/src/main/resources/corelib/Float.monty @@ -0,0 +1,36 @@ +class Float: + + initializer(Float f): + pass + + + Float operator-(): + pass + + + Float operator+(Float other): + pass + + + Float operator-(Float other): + pass + + + Float operator*(Float other): + pass + + + Float operator/(Float other): + pass + + + Bool operator<(Float other): + pass + + + Bool operator>(Float other): + pass + + + Bool operator<=(Float other): + pass + + + Bool operator>=(Float other): + pass + + + Bool operator=(Float other): + pass + + + Bool operator!=(Float other): + pass diff --git a/src/main/resources/corelib/Int.monty b/src/main/resources/corelib/Int.monty new file mode 100644 index 0000000..6e16990 --- /dev/null +++ b/src/main/resources/corelib/Int.monty @@ -0,0 +1,39 @@ +class Int: + + initializer(Int i): + pass + + + Int operator-(): + pass + + + Int operator+(Int other): + pass + + + Int operator-(Int other): + pass + + + Int operator*(Int other): + pass + + + Int operator/(Int other): + pass + + + Int operator%(Int other): + pass + + + Bool operator<(Int other): + pass + + + Bool operator>(Int other): + pass + + + Bool operator<=(Int other): + pass + + + Bool operator>=(Int other): + pass + + + Bool operator=(Int other): + pass + + + Bool operator!=(Int other): + pass diff --git a/src/main/resources/corelib/Object.monty b/src/main/resources/corelib/Object.monty new file mode 100644 index 0000000..ffc1871 --- /dev/null +++ b/src/main/resources/corelib/Object.monty @@ -0,0 +1,2 @@ +class Object: + pass diff --git a/src/main/resources/corelib/Print.monty b/src/main/resources/corelib/Print.monty new file mode 100644 index 0000000..ca8367a --- /dev/null +++ b/src/main/resources/corelib/Print.monty @@ -0,0 +1,14 @@ +print(String arg1): + pass + +print(Int arg1): + pass + +print(Float arg1): + pass + +print(Bool arg1): + pass + +print(Char arg1): + pass diff --git a/src/main/resources/find-missing-license.sh b/src/main/resources/find-missing-license.sh new file mode 100755 index 0000000..cccf4f8 --- /dev/null +++ b/src/main/resources/find-missing-license.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +DIR="$SCRIPT_DIR/../../[mt]*/" + +for i in $(find $DIR -iname *.java) +do + grep "General Public License" $i > /dev/null + STATUS=$? + + if [ $STATUS -ne 0 ] + then + REALPATH=$(readlink -m $i) + echo "[WARNING] $REALPATH lacks license header" + fi +done diff --git a/src/main/resources/java-code-conv.xml b/src/main/resources/java-code-conv.xml new file mode 100644 index 0000000..84f13bb --- /dev/null +++ b/src/main/resources/java-code-conv.xml @@ -0,0 +1,291 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/log4j.properies b/src/main/resources/log4j.properies new file mode 100644 index 0000000..a970538 --- /dev/null +++ b/src/main/resources/log4j.properies @@ -0,0 +1 @@ +log4j.rootLogger = DEBUG \ No newline at end of file diff --git a/src/main/resources/moco-code-conv.xml b/src/main/resources/moco-code-conv.xml new file mode 100644 index 0000000..6a7f0a3 --- /dev/null +++ b/src/main/resources/moco-code-conv.xml @@ -0,0 +1,295 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/rm_trailing_whitespace.sh b/src/main/resources/rm_trailing_whitespace.sh new file mode 100755 index 0000000..c410cd2 --- /dev/null +++ b/src/main/resources/rm_trailing_whitespace.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +SRC_DIR=$1 + +echo $1 > /tmp/rm_result + +if [[ -z "$1" ]]; then + SRC_DIR="../.." +fi + +# find all java files and remove trailing ws (using system dependent sed command) +OS=`uname -s` +if [[ $OS == "Linux" ]]; then + find $SRC_DIR -type f -name "*.java" -print0 | xargs -0 sed -i -r -e 's/\s+$//g' +elif [[ $OS == "Darwin" ]]; then + find "$SRC_DIR" -type f -name "*.java" -print0 | xargs -0 sed -E -e "s/[[:space:]]+$//" -i '' +fi \ No newline at end of file diff --git a/src/main/resources/std_llvm_include.ll b/src/main/resources/std_llvm_include.ll new file mode 100644 index 0000000..aa1e4cf --- /dev/null +++ b/src/main/resources/std_llvm_include.ll @@ -0,0 +1,57 @@ +; Begin of the standard declarations and definitions every Monty program needs. +declare void @exit(i32 %status) noreturn +declare i8* @malloc(i32 %size) nounwind +declare i32 @printf(i8* %format, ... ) nounwind + +@.stringFormat = private constant [3 x i8] c"%s\00"; +@.floatFormat = private constant [3 x i8] c"%g\00"; +@.intFormat = private constant [3 x i8] c"%i\00"; +@.charFormat = private constant [3 x i8] c"%c\00"; + +; Search the sourceCTData array of pointers to vmtData for the toVMTPtr +; pointer for class inheritance-test. +define i1 @vmt_isa_class([0 x i8*]* %sourceCTData, i8* %toVMTPtr) { + %cnt = alloca i32 + store i32 0, i32* %cnt + br label %loop.start + + loop.start: + %cnt_val = load i32* %cnt + %index = getelementptr [0 x i8*]* %sourceCTData, i32 0, i32 %cnt_val + %ptr = load i8** %index + ; If the end of the array is reached (null terminated) fail.. + %cmp_null = icmp eq i8* %ptr, null + br i1 %cmp_null, label %loop.failure, label %loop.next + + loop.next: + %cnt_inr = add i32 %cnt_val, 1 + store i32 %cnt_inr, i32* %cnt + ; If the pointers are equal the class equals or inherits. + %cmp = icmp eq i8* %toVMTPtr, %ptr + br i1 %cmp, label %loop.success, label %loop.start + + loop.failure: + ret i1 0 + loop.success: + ret i1 1 +} + +; Check if the given index is within bounds (0 <= index < array.size). If not exit(3) +define void @array_bounds_check({ i64, [0 x i8*] }* %array, i64 %index) { + %gt_zero = icmp sge i64 %index, 0 + br i1 %gt_zero, label %bounds.next, label %bounds.error + + bounds.next: + %size_field = getelementptr inbounds {i64, [0 x i8*]}* %array, i32 0, i32 0 + %size = load i64* %size_field + %lt_size = icmp slt i64 %index, %size + br i1 %lt_size, label %bounds.success, label %bounds.error + + bounds.error: + call void @exit(i32 3) + ret void + bounds.success: + ret void +} +; End of the standard declarations and definitions every Monty program needs. + diff --git a/src/site/site.xml b/src/site/site.xml new file mode 100644 index 0000000..fc98acb --- /dev/null +++ b/src/site/site.xml @@ -0,0 +1,18 @@ + + + + + Monty's CocoNut + http://www.informatik.uni-bremen.de/monty/img/logo.png + http://www.informatik.uni-bremen.de/monty/ + + + + org.apache.maven.skins + maven-fluido-skin + 1.3.1 + + diff --git a/src/test/java/de/uni/bremen/monty/moco/CompileFilesBaseTest.java b/src/test/java/de/uni/bremen/monty/moco/CompileFilesBaseTest.java new file mode 100644 index 0000000..4ad9399 --- /dev/null +++ b/src/test/java/de/uni/bremen/monty/moco/CompileFilesBaseTest.java @@ -0,0 +1,96 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco; + +import de.uni.bremen.monty.moco.util.MultiOutputStream; +import org.apache.commons.io.FileUtils; + +import java.io.File; +import java.io.FilenameFilter; +import java.net.URI; +import java.net.URISyntaxException; + +import java.util.Arrays; +import java.util.Collection; + +public class CompileFilesBaseTest { + protected File file; + protected String fileName; + + public CompileFilesBaseTest(File file, String fileName) { + this.file = file; + this.fileName = fileName; + } + + protected static Collection buildParameterObject(Collection programFiles) { + Object[][] a = new Object[programFiles.size()][1]; + int i = 0; + for (File programFile : programFiles) { + a[i++] = new Object[] { programFile, programFile.getName() }; + } + return Arrays.asList(a); + } + + protected static Collection getFiles4Filter(String folderPath, String[] filter) throws URISyntaxException { + Class aClass = CompileTestProgramsTest.class; + ClassLoader classLoader = aClass.getClassLoader(); + File testprogramFolder = new File(classLoader.getResource(folderPath).toURI()); + return FileUtils.listFiles(testprogramFolder, filter, true); + } + + protected static Collection getAllMontyFiles(String folderPath) throws URISyntaxException { + return getFiles4Filter(folderPath, new String[] { "monty" }); + } + + protected static File getLastModifiedMontyFile(String folderPath) throws URISyntaxException { + + final File[] montyFilesInDir = + getFiles4Filter(folderPath, new String[] { "monty", "ignore" }).toArray(new File[0]); + File latestModifiedMontyProgram = montyFilesInDir[0]; + + for (File file : montyFilesInDir) { + if (file.lastModified() > latestModifiedMontyProgram.lastModified()) { + latestModifiedMontyProgram = file; + } + } + + return latestModifiedMontyProgram; + } + +} diff --git a/src/test/java/de/uni/bremen/monty/moco/CompileLatestTestProgramsTest.java b/src/test/java/de/uni/bremen/monty/moco/CompileLatestTestProgramsTest.java new file mode 100644 index 0000000..dae8601 --- /dev/null +++ b/src/test/java/de/uni/bremen/monty/moco/CompileLatestTestProgramsTest.java @@ -0,0 +1,94 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ + +package de.uni.bremen.monty.moco; + +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.PrintStream; +import java.util.Arrays; +import java.util.Collection; + +import static de.uni.bremen.monty.moco.IntegrationTestUtils.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.isEmptyString; +import static org.junit.runners.Parameterized.Parameters; + +@Ignore +@RunWith(Parameterized.class) +public class CompileLatestTestProgramsTest extends CompileFilesBaseTest { + + public CompileLatestTestProgramsTest(File file, String fileName) { + super(file, fileName); + } + + @Parameters(name = "Program: {1}") + public static Collection data() throws Exception { + + File[] programFiles = { getLastModifiedMontyFile("testPrograms/") }; + return buildParameterObject(Arrays.asList(programFiles)); + } + + @Test + public void compileProgramTest() throws IOException { + final PrintStream bufferOut = System.out; + final PrintStream bufferErr = System.err; + final ByteArrayOutputStream outStream = setStdout(); + final ByteArrayOutputStream errorStream = setStdErr(file); + + Main.main(new String[] { "-k", file.getAbsolutePath(), "-e" }); + + if (outputFileExists(file)) { + assertThat(getOutput(errorStream), is(isEmptyString())); + assertThat(getOutput(outStream), is(expectedResultFromFile(file))); + } else { + assertThat(getOutput(errorStream), is(expectedErrorFromFile(file))); + assertThat(getOutput(outStream), is(isEmptyString())); + } + System.setOut(bufferOut); + System.setErr(bufferErr); + } +} diff --git a/src/test/java/de/uni/bremen/monty/moco/CompileTestProgramsTest.java b/src/test/java/de/uni/bremen/monty/moco/CompileTestProgramsTest.java new file mode 100644 index 0000000..df0c053 --- /dev/null +++ b/src/test/java/de/uni/bremen/monty/moco/CompileTestProgramsTest.java @@ -0,0 +1,91 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco; + +import static de.uni.bremen.monty.moco.IntegrationTestUtils.*; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.PrintStream; +import java.util.Collection; +import org.apache.commons.lang3.StringUtils; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.isEmptyString; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +@RunWith(Parameterized.class) +public class CompileTestProgramsTest extends CompileFilesBaseTest { + + public CompileTestProgramsTest(File file, String fileName) { + super(file, fileName); + } + + @Parameters(name = "Program: {1}") + public static Collection data() throws Exception { + Collection programFiles = getAllMontyFiles("testPrograms/"); + + return buildParameterObject(programFiles); + } + + @Test + public void compileProgramTest() throws IOException { + final PrintStream bufferOut = System.out; + final PrintStream bufferErr = System.err; + final ByteArrayOutputStream outStream = setStdout(); + final ByteArrayOutputStream errorStream = setStdErr(file); + + Main.main(new String[] { "-k", file.getAbsolutePath(), "-e" }); + + if (outputFileExists(file)) { + assertThat(getOutput(errorStream), is(isEmptyString())); + assertThat(getOutput(outStream), is(expectedResultFromFile(file))); + } else { + // chop the last char to not contain /n in the string + assertThat(StringUtils.chop(getOutput(errorStream)), is(expectedErrorFromFile(file))); + assertThat(getOutput(outStream), is(isEmptyString())); + } + System.setOut(bufferOut); + System.setErr(bufferErr); + } + +} diff --git a/src/test/java/de/uni/bremen/monty/moco/IntegrationTestUtils.java b/src/test/java/de/uni/bremen/monty/moco/IntegrationTestUtils.java new file mode 100644 index 0000000..46f85fa --- /dev/null +++ b/src/test/java/de/uni/bremen/monty/moco/IntegrationTestUtils.java @@ -0,0 +1,106 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ + +package de.uni.bremen.monty.moco; + +import static de.uni.bremen.monty.moco.IntegrationTestUtils.outputFileExists; +import de.uni.bremen.monty.moco.util.MultiOutputStream; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; + +public class IntegrationTestUtils { + protected static String getOutput(ByteArrayOutputStream outStream) { + return new String(outStream.toByteArray()); + + } + + protected static ByteArrayOutputStream setStdout() { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + System.setOut(new PrintStream(byteArrayOutputStream)); + return byteArrayOutputStream; + } + + protected static ByteArrayOutputStream setStdErr(File file) { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + + if (outputFileExists(file)) { + OutputStream errStream = new MultiOutputStream(byteArrayOutputStream, System.err); + System.setErr(new PrintStream(errStream)); + } else { + + System.setErr(new PrintStream(byteArrayOutputStream)); + } + + return byteArrayOutputStream; + } + + protected static ByteArrayOutputStream setStdErr() { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + OutputStream errStream = new MultiOutputStream(byteArrayOutputStream, System.err); + System.setErr(new PrintStream(errStream)); + return byteArrayOutputStream; + } + + protected static String getExpectedResultFromFile(String outputFile) throws IOException { + byte[] encoded = Files.readAllBytes(Paths.get(outputFile)); + return new String(encoded, StandardCharsets.UTF_8); + } + + protected static String expectedResultFromFile(File file) throws IOException { + String outputFile = changeFileExtension(file, ".output"); + return IntegrationTestUtils.getExpectedResultFromFile(outputFile); + } + + private static String changeFileExtension(File file, String newExtension) { + return file.getAbsolutePath().substring(0, file.getAbsolutePath().lastIndexOf('.')) + newExtension; + } + + protected static String expectedErrorFromFile(File file) throws IOException { + String outputFile = changeFileExtension(file, ".error"); + return IntegrationTestUtils.getExpectedResultFromFile(outputFile); + } + + protected static boolean outputFileExists(File file) { + String outputFile = changeFileExtension(file, ".output"); + return new File(outputFile).exists(); + } +} diff --git a/src/test/java/de/uni/bremen/monty/moco/ModuleProgramsTest.java b/src/test/java/de/uni/bremen/monty/moco/ModuleProgramsTest.java new file mode 100644 index 0000000..e88697e --- /dev/null +++ b/src/test/java/de/uni/bremen/monty/moco/ModuleProgramsTest.java @@ -0,0 +1,77 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ + +package de.uni.bremen.monty.moco; + +import org.junit.Test; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.net.URISyntaxException; +import java.net.URL; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.isEmptyString; + +public class ModuleProgramsTest { + + @Test + public void compileProgramTest() throws Exception { + ByteArrayOutputStream outStream = IntegrationTestUtils.setStdout(); + ByteArrayOutputStream errorStream = IntegrationTestUtils.setStdErr(); + + Class aClass = ModuleProgramsTest.class; + ClassLoader classLoader = aClass.getClassLoader(); + String name = "testModuleProgramms/"; + String absolutePath = getAbsolutePath(classLoader, name); + Main.main(new String[] { "-k", absolutePath, "de.dafuq.monty.Module1", "-e" }); + + assertThat(IntegrationTestUtils.getOutput(errorStream), is(isEmptyString())); + String outputFileName = getAbsolutePath(classLoader, name + "de/dafuq/monty/Main.output"); + String expectedResultFromFile = IntegrationTestUtils.getExpectedResultFromFile(outputFileName); + assertThat(IntegrationTestUtils.getOutput(outStream), is(expectedResultFromFile)); + } + + private String getAbsolutePath(ClassLoader classLoader, String name) throws URISyntaxException { + URL testModulesFolder = classLoader.getResource(name); + + return new File(testModulesFolder.toURI()).getAbsolutePath(); + } +} diff --git a/src/test/java/de/uni/bremen/monty/moco/ast/ASTBuilderTest.java b/src/test/java/de/uni/bremen/monty/moco/ast/ASTBuilderTest.java new file mode 100644 index 0000000..1cfa19a --- /dev/null +++ b/src/test/java/de/uni/bremen/monty/moco/ast/ASTBuilderTest.java @@ -0,0 +1,270 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast; + +import de.uni.bremen.monty.moco.CompileTestProgramsTest; +import de.uni.bremen.monty.moco.antlr.MontyLexer; +import de.uni.bremen.monty.moco.antlr.MontyParser; +import de.uni.bremen.monty.moco.ast.declaration.*; +import de.uni.bremen.monty.moco.ast.expression.FunctionCall; +import de.uni.bremen.monty.moco.ast.expression.VariableAccess; +import de.uni.bremen.monty.moco.ast.expression.literal.IntegerLiteral; +import de.uni.bremen.monty.moco.ast.expression.literal.StringLiteral; +import de.uni.bremen.monty.moco.ast.statement.Assignment; +import de.uni.bremen.monty.moco.ast.statement.ConditionalStatement; +import org.antlr.v4.runtime.ANTLRInputStream; +import org.antlr.v4.runtime.CommonTokenStream; +import org.apache.commons.io.FileUtils; +import org.junit.Ignore; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; + +import static de.uni.bremen.monty.moco.ast.declaration.VariableDeclaration.DeclarationType; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertTrue; + +public class ASTBuilderTest { + + @Test + public void shouldConvertVariableInitialisation() throws Exception { + ModuleDeclaration ast = buildASTfrom("varDecl"); + + VariableDeclaration declaration = (VariableDeclaration) ast.getBlock().getDeclarations().get(0); + + Assignment statement = (Assignment) ast.getBlock().getStatements().get(0); + VariableAccess left = (VariableAccess) statement.getLeft(); + StringLiteral right = (StringLiteral) statement.getRight(); + + assertThat(declaration.getIdentifier().getSymbol(), is("s")); + assertThat(left.getIdentifier().getSymbol(), is("s")); + assertThat(right.getValue(), is("Hallo")); + + } + + @Test + public void shouldConvertDeclarationType() throws Exception { + ModuleDeclaration ast = buildASTfrom("declarationType"); + + ClassDeclaration classDecl = (ClassDeclaration) ast.getBlock().getDeclarations().get(0); + VariableDeclaration memberDecl = (VariableDeclaration) classDecl.getBlock().getDeclarations().get(0); + VariableDeclaration memberInit = (VariableDeclaration) classDecl.getBlock().getDeclarations().get(1); + ProcedureDeclaration memberProc = (ProcedureDeclaration) classDecl.getBlock().getDeclarations().get(2); + FunctionDeclaration memberFun = (FunctionDeclaration) classDecl.getBlock().getDeclarations().get(3); + + VariableDeclaration varDecl = (VariableDeclaration) ast.getBlock().getDeclarations().get(1); + VariableDeclaration varInit = (VariableDeclaration) ast.getBlock().getDeclarations().get(2); + FunctionDeclaration funDecl = (FunctionDeclaration) ast.getBlock().getDeclarations().get(3); + ProcedureDeclaration procDecl = (ProcedureDeclaration) ast.getBlock().getDeclarations().get(4); + + assertThat(varDecl.getDeclarationType(), is(VariableDeclaration.DeclarationType.VARIABLE)); + assertThat(varInit.getDeclarationType(), is(VariableDeclaration.DeclarationType.VARIABLE)); + assertThat( + funDecl.getParameter().get(0).getDeclarationType(), + is(VariableDeclaration.DeclarationType.PARAMETER)); + assertThat( + procDecl.getParameter().get(0).getDeclarationType(), + is(VariableDeclaration.DeclarationType.PARAMETER)); + + assertThat(memberDecl.getDeclarationType(), is(VariableDeclaration.DeclarationType.ATTRIBUTE)); + assertThat(memberInit.getDeclarationType(), is(VariableDeclaration.DeclarationType.ATTRIBUTE)); + assertThat( + memberProc.getParameter().get(0).getDeclarationType(), + is(VariableDeclaration.DeclarationType.PARAMETER)); + assertThat( + memberFun.getParameter().get(0).getDeclarationType(), + is(VariableDeclaration.DeclarationType.PARAMETER)); + + assertThat(memberProc.getDeclarationType(), is(ProcedureDeclaration.DeclarationType.METHOD)); + assertThat(memberFun.getDeclarationType(), is(ProcedureDeclaration.DeclarationType.METHOD)); + assertThat(funDecl.getDeclarationType(), is(ProcedureDeclaration.DeclarationType.UNBOUND)); + assertThat(procDecl.getDeclarationType(), is(ProcedureDeclaration.DeclarationType.UNBOUND)); + + } + + @Test + public void shouldConvertIf() throws Exception { + ModuleDeclaration ast = buildASTfrom("ifElse"); + + ConditionalStatement condStmt = (ConditionalStatement) ast.getBlock().getStatements().get(0); + + VariableAccess condition = (VariableAccess) condStmt.getCondition(); + FunctionCall thenBlock = (FunctionCall) condStmt.getThenBlock().getStatements().get(0); + Block elseBlock = condStmt.getElseBlock(); + + assertThat(condition.getIdentifier().getSymbol(), is("a")); + + assertThat(getValue(thenBlock), is(1)); + assertTrue(elseBlock.isEmpty()); + } + + @Test + public void shouldConvertIfElse() throws Exception { + ModuleDeclaration ast = buildASTfrom("ifElse"); + + ConditionalStatement condStmt = (ConditionalStatement) ast.getBlock().getStatements().get(1); + + VariableAccess condition = (VariableAccess) condStmt.getCondition(); + FunctionCall thenBlock = (FunctionCall) condStmt.getThenBlock().getStatements().get(0); + FunctionCall elseBlock = (FunctionCall) condStmt.getElseBlock().getStatements().get(0); + + assertThat(condition.getIdentifier().getSymbol(), is("a")); + + assertThat(getValue(thenBlock), is(1)); + assertThat(getValue(elseBlock), is(2)); + } + + @Test + public void shouldConvertIfWithElseAndElseIf() throws Exception { + ModuleDeclaration ast = buildASTfrom("ifElse"); + + ConditionalStatement condStmt = (ConditionalStatement) ast.getBlock().getStatements().get(2); + + VariableAccess firstCondition = (VariableAccess) condStmt.getCondition(); + FunctionCall firstThenBlock = (FunctionCall) condStmt.getThenBlock().getStatements().get(0); + ConditionalStatement firstElseBlock = (ConditionalStatement) condStmt.getElseBlock().getStatements().get(0); + + VariableAccess secondCondition = (VariableAccess) firstElseBlock.getCondition(); + FunctionCall secondThenBlock = (FunctionCall) firstElseBlock.getThenBlock().getStatements().get(0); + FunctionCall secondElseBlock = (FunctionCall) firstElseBlock.getElseBlock().getStatements().get(0); + + assertThat(firstCondition.getIdentifier().getSymbol(), is("a")); + assertThat(secondCondition.getIdentifier().getSymbol(), is("b")); + + assertThat(getValue(firstThenBlock), is(1)); + assertThat(getValue(secondThenBlock), is(2)); + assertThat(getValue(secondElseBlock), is(3)); + + } + + @Test + public void shouldConvertIfWithElseAnd2ElseIf() throws Exception { + ModuleDeclaration ast = buildASTfrom("ifElse"); + + ConditionalStatement condStmt = (ConditionalStatement) ast.getBlock().getStatements().get(3); + + VariableAccess firstCondition = (VariableAccess) condStmt.getCondition(); + FunctionCall firstThenBlock = (FunctionCall) condStmt.getThenBlock().getStatements().get(0); + ConditionalStatement firstElseBlock = (ConditionalStatement) condStmt.getElseBlock().getStatements().get(0); + + VariableAccess secondCondition = (VariableAccess) firstElseBlock.getCondition(); + FunctionCall secondThenBlock = (FunctionCall) firstElseBlock.getThenBlock().getStatements().get(0); + ConditionalStatement secondElseBlock = + (ConditionalStatement) firstElseBlock.getElseBlock().getStatements().get(0); + + VariableAccess thirdCondition = (VariableAccess) secondElseBlock.getCondition(); + FunctionCall thirdThenBlock = (FunctionCall) secondElseBlock.getThenBlock().getStatements().get(0); + FunctionCall thirdElseBlock = (FunctionCall) secondElseBlock.getElseBlock().getStatements().get(0); + + assertThat(firstCondition.getIdentifier().getSymbol(), is("a")); + assertThat(secondCondition.getIdentifier().getSymbol(), is("b")); + assertThat(thirdCondition.getIdentifier().getSymbol(), is("c")); + + assertThat(getValue(firstThenBlock), is(1)); + assertThat(getValue(secondThenBlock), is(2)); + assertThat(getValue(thirdThenBlock), is(3)); + assertThat(getValue(thirdElseBlock), is(4)); + + } + + @Test + public void shouldConvertIfWith2ElseIf() throws Exception { + ModuleDeclaration ast = buildASTfrom("ifElse"); + + ConditionalStatement condStmt = (ConditionalStatement) ast.getBlock().getStatements().get(4); + + VariableAccess firstCondition = (VariableAccess) condStmt.getCondition(); + FunctionCall firstThenBlock = (FunctionCall) condStmt.getThenBlock().getStatements().get(0); + ConditionalStatement firstElseBlock = (ConditionalStatement) condStmt.getElseBlock().getStatements().get(0); + + VariableAccess secondCondition = (VariableAccess) firstElseBlock.getCondition(); + FunctionCall secondThenBlock = (FunctionCall) firstElseBlock.getThenBlock().getStatements().get(0); + ConditionalStatement secondElseBlock = + (ConditionalStatement) firstElseBlock.getElseBlock().getStatements().get(0); + + VariableAccess thirdCondition = (VariableAccess) secondElseBlock.getCondition(); + FunctionCall thirdThenBlock = (FunctionCall) secondElseBlock.getThenBlock().getStatements().get(0); + + assertThat(firstCondition.getIdentifier().getSymbol(), is("a")); + assertThat(secondCondition.getIdentifier().getSymbol(), is("b")); + assertThat(thirdCondition.getIdentifier().getSymbol(), is("c")); + + assertThat(getValue(firstThenBlock), is(1)); + assertThat(getValue(secondThenBlock), is(2)); + assertThat(getValue(thirdThenBlock), is(3)); + + assertTrue(secondElseBlock.getElseBlock().isEmpty()); + + } + + private int getValue(FunctionCall print) { + return ((IntegerLiteral) print.getArguments().get(0)).getValue(); + } + + private ModuleDeclaration buildASTfrom(String varDecl) throws IOException, URISyntaxException { + String fileName = "testAstBuilder/" + varDecl + ".monty"; + + String montyProgram = getFileContent(fileName); + MontyParser parser = createMontyParser(montyProgram); + return buildAST(fileName, parser); + } + + private ModuleDeclaration buildAST(String fileName, MontyParser parser) { + ASTBuilder astBuilder = new ASTBuilder(fileName); + ASTNode rootNode = astBuilder.visitModuleDeclaration(parser.moduleDeclaration()); + return (ModuleDeclaration) rootNode; + } + + private MontyParser createMontyParser(String montyProgram) { + ANTLRInputStream input = new ANTLRInputStream(montyProgram + "\n"); + MontyLexer lexer = new MontyLexer(input); + CommonTokenStream tokens = new CommonTokenStream(lexer); + return new MontyParser(tokens); + } + + private String getFileContent(String fileName) throws URISyntaxException, IOException { + Class aClass = CompileTestProgramsTest.class; + ClassLoader classLoader = aClass.getClassLoader(); + File file = new File(classLoader.getResource(fileName).toURI()); + return FileUtils.readFileToString(file); + } +} diff --git a/src/test/java/de/uni/bremen/monty/moco/ast/ControlFlowTest.java b/src/test/java/de/uni/bremen/monty/moco/ast/ControlFlowTest.java new file mode 100644 index 0000000..c271bbd --- /dev/null +++ b/src/test/java/de/uni/bremen/monty/moco/ast/ControlFlowTest.java @@ -0,0 +1,894 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast; + +import de.uni.bremen.monty.moco.ast.declaration.FunctionDeclaration; +import de.uni.bremen.monty.moco.ast.declaration.ModuleDeclaration; +import de.uni.bremen.monty.moco.ast.declaration.ProcedureDeclaration; +import de.uni.bremen.monty.moco.ast.declaration.VariableDeclaration; +import de.uni.bremen.monty.moco.ast.expression.Expression; +import de.uni.bremen.monty.moco.ast.expression.literal.BooleanLiteral; +import de.uni.bremen.monty.moco.ast.expression.literal.StringLiteral; +import de.uni.bremen.monty.moco.ast.statement.*; +import de.uni.bremen.monty.moco.exception.InvalidControlFlowException; +import de.uni.bremen.monty.moco.visitor.ControlFlowVisitor; +import de.uni.bremen.monty.moco.visitor.DeclarationVisitor; +import de.uni.bremen.monty.moco.visitor.SetParentVisitor; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +public class ControlFlowTest { + + private SetParentVisitor setParentVisitor; + private ControlFlowVisitor controlFlowVisitor; + + // MODULE + private Block moduleBlock; + private List moduleImports; + private Package aPackage; + private ModuleDeclaration moduleDeclaration; + + // MODULE LOOP + private Expression moduleLoopCondition; + private Block moduleLoopBlock; + private WhileLoop moduleLoop; + private ContinueStatement moduleLoopContinueStatement; + private BreakStatement moduleLoopBreakStatement; + private Expression moduleLoopLoopCondition; + private Block moduleLoopLoopBlock; + + // MODULE LOOP LOOP + private WhileLoop moduleLoopLoop; + private ContinueStatement moduleLoopLoopContinueStatement; + private BreakStatement moduleLoopLoopBreakStatement; + private Expression moduleLoopLoopConditionalStatementCondition; + private Block moduleLoopLoopConditionalStatementThenBlock; + private Block moduleLoopLoopConditionalStatementElseBlock; + private ConditionalStatement moduleLoopLoopConditionalStatement; + private Expression moduleLoopLoopThenConditionalStatementCondition; + private Block moduleLoopLoopThenConditionalStatementThenBlock; + private Block moduleLoopLoopThenConditionalStatementElseBlock; + private ConditionalStatement moduleLoopLoopThenConditionalStatement; + private Expression moduleLoopLoopElseConditionalStatementCondition; + private Block moduleLoopLoopElseConditionalStatementThenBlock; + private Block moduleLoopLoopElseConditionalStatementElseBlock; + private ConditionalStatement moduleLoopLoopElseConditionalStatement; + + // MODULE LOOP CONDITIONAL STATEMENT + private Expression moduleLoopConditionalStatementCondition; + private Block moduleLoopConditionalStatementThenBlock; + private Block moduleLoopConditionalStatementElseBlock; + private ConditionalStatement moduleLoopConditionalStatement; + private ContinueStatement moduleLoopConditionalContinueStatement; + private BreakStatement moduleLoopConditionalBreakStatement; + + // MODULE CONDITIONAL STATEMENT + private Expression moduleConditionalStatementCondition; + private Block moduleConditionalStatementThenBlock; + private Block moduleConditionalStatementElseBlock; + private ConditionalStatement moduleConditionalStatement; + + // MODULE STATETEMENTS + private ContinueStatement moduleContinueStatement; + private BreakStatement moduleBreakStatement; + private Expression moduleReturnStatementParameter; + private ReturnStatement moduleReturnStatement; + + // MODULE FUNCTION + private Block moduleFunctionBlock; + private List moduleFunctionParameter; + private FunctionDeclaration moduleFunctionDeclaration; + private Expression moduleFunctionReturnStatementParameter; + private ReturnStatement moduleFunctionReturnStatement; + + // MODULE FUNCTION PROCEDURE + private Block moduleFunctionProcedureBlock; + private List moduleFunctionProcedureParameter; + private ProcedureDeclaration moduleFunctionProcedureDeclaration; + private Expression moduleFunctionProcedureReturnStatementParameter; + private ReturnStatement moduleFunctionProcedureReturnStatement; + + // MODULE FUNCTION CONDITIONAL STATEMENT + private Expression moduleFunctionConditionalStatementCondition; + private Block moduleFunctionConditionalStatementThenBlock; + private Block moduleFunctionConditionalStatementElseBlock; + private ConditionalStatement moduleFunctionConditionalStatement; + private Expression moduleFunctionConditionalReturnThenStatementParameter; + private ReturnStatement moduleFunctionConditionalReturnThenStatement; + private Expression moduleFunctionConditionalReturnElseStatementParameter; + private ReturnStatement moduleFunctionConditionalReturnElseStatement; + private Expression moduleFunctionConditionalConditionalStatementCondition; + private Block moduleFunctionConditionalConditionalStatementThenBlock; + private Block moduleFunctionConditionalConditionalStatementElseBlock; + private ConditionalStatement moduleFunctionConditionalConditionalStatement; + private Expression moduleFunctionConditionalConditionalReturnStatementParameter; + private ReturnStatement moduleFunctionConditionalConditionalReturnStatement; + private Expression moduleFunctionConditionalConditionalConditionalStatementCondition; + private Block moduleFunctionConditionalConditionalConditionalStatementThenBlock; + private Block moduleFunctionConditionalConditionalConditionalStatementElseBlock; + private ConditionalStatement moduleFunctionConditionalConditionalConditionalStatement; + private Expression moduleFunctionConditionalConditionalConditionalThenReturnStatementParameter; + private ReturnStatement moduleFunctionConditionalConditionalConditionalThenReturnStatement; + private Expression moduleFunctionConditionalConditionalConditionalElseReturnStatementParameter; + private ReturnStatement moduleFunctionConditionalConditionalConditionalElseReturnStatement; + + // MODULE FUNCTION LOOP + private Expression moduleFunctionLoopCondition; + private Block moduleFunctionLoopBlock; + private WhileLoop moduleFunctionLoop; + private Expression moduleFunctionLoopReturnStatementParameter; + private ReturnStatement moduleFunctionLoopReturnStatement; + private Expression moduleFunctionLoopLoopCondition; + private Block moduleFunctionLoopLoopBlock; + private WhileLoop moduleFunctionLoopLoop; + private Expression moduleFunctionLoopLoopLoopCondition; + private Block moduleFunctionLoopLoopLoopBlock; + private WhileLoop moduleFunctionLoopLoopLoop; + private Expression moduleFunctionLoopLoopLoopReturnStatementParameter; + private ReturnStatement moduleFunctionLoopLoopLoopReturnStatement; + + // helper + private int counter = 0; + + public Position nextPosition() { + return new Position("TestFile", counter++, 1); + } + + @Before + public void setUpAST() { + + // reset counter + counter = 0; + + // VISITORS --------------------------- + setParentVisitor = new SetParentVisitor(); + setParentVisitor.setStopOnFirstError(true); + controlFlowVisitor = new ControlFlowVisitor(); + controlFlowVisitor.setStopOnFirstError(true); + + // AST -------------------------------- + + // MODULE + moduleBlock = new Block(nextPosition()); + moduleImports = new ArrayList<>(); // empty list is fine here ... + moduleDeclaration = + new ModuleDeclaration(nextPosition(), new Identifier("TestModule"), moduleBlock, moduleImports); + + aPackage = new Package(new Identifier("")); + aPackage.addModule(moduleDeclaration); + + // MODULE LOOP + moduleLoopCondition = new BooleanLiteral(nextPosition(), true); + moduleLoopBlock = new Block(nextPosition()); + moduleLoop = new WhileLoop(nextPosition(), moduleLoopCondition, moduleLoopBlock); + moduleLoopContinueStatement = new ContinueStatement(nextPosition()); + moduleLoopBreakStatement = new BreakStatement(nextPosition()); + // add module loop to module + moduleBlock.addStatement(moduleLoop); + + // MODULE LOOP LOOP + moduleLoopLoopCondition = new BooleanLiteral(nextPosition(), true); + moduleLoopLoopBlock = new Block(nextPosition()); + moduleLoopLoop = new WhileLoop(nextPosition(), moduleLoopLoopCondition, moduleLoopLoopBlock); + moduleLoopLoopContinueStatement = new ContinueStatement(nextPosition()); + moduleLoopLoopBreakStatement = new BreakStatement(nextPosition()); + // add module loop loop to module loop + moduleLoopBlock.addStatement(moduleLoopLoop); + moduleLoopLoopConditionalStatementCondition = new BooleanLiteral(nextPosition(), true); + moduleLoopLoopConditionalStatementThenBlock = new Block(nextPosition()); + moduleLoopLoopConditionalStatementElseBlock = new Block(nextPosition()); + moduleLoopLoopConditionalStatement = + new ConditionalStatement(nextPosition(), moduleLoopLoopConditionalStatementCondition, + moduleLoopLoopConditionalStatementThenBlock, moduleLoopLoopConditionalStatementElseBlock); + moduleLoopLoopThenConditionalStatementCondition = new BooleanLiteral(nextPosition(), true); + moduleLoopLoopThenConditionalStatementThenBlock = new Block(nextPosition()); + moduleLoopLoopThenConditionalStatementElseBlock = new Block(nextPosition()); + moduleLoopLoopThenConditionalStatement = + new ConditionalStatement(nextPosition(), moduleLoopLoopThenConditionalStatementCondition, + moduleLoopLoopThenConditionalStatementThenBlock, + moduleLoopLoopThenConditionalStatementElseBlock); + moduleLoopLoopElseConditionalStatementCondition = new BooleanLiteral(nextPosition(), true); + moduleLoopLoopElseConditionalStatementThenBlock = new Block(nextPosition()); + moduleLoopLoopElseConditionalStatementElseBlock = new Block(nextPosition()); + moduleLoopLoopElseConditionalStatement = + new ConditionalStatement(nextPosition(), moduleLoopLoopElseConditionalStatementCondition, + moduleLoopLoopElseConditionalStatementThenBlock, + moduleLoopLoopElseConditionalStatementElseBlock); + + // MODULE LOOP CONDITIONAL STATEMENT + moduleLoopConditionalStatementCondition = new BooleanLiteral(nextPosition(), true); + moduleLoopConditionalStatementThenBlock = new Block(nextPosition()); + moduleLoopConditionalStatementElseBlock = new Block(nextPosition()); + moduleLoopConditionalStatement = + new ConditionalStatement(nextPosition(), moduleLoopConditionalStatementCondition, + moduleLoopConditionalStatementThenBlock, moduleLoopConditionalStatementElseBlock); + moduleLoopConditionalContinueStatement = new ContinueStatement(nextPosition()); + moduleLoopConditionalBreakStatement = new BreakStatement(nextPosition()); + // add module loop conditional statement to module loop + moduleLoopBlock.addStatement(moduleLoopConditionalStatement); + + // MODULE CONDITIONAL STATEMENT + moduleConditionalStatementCondition = new BooleanLiteral(nextPosition(), true); + moduleConditionalStatementThenBlock = new Block(nextPosition()); + moduleConditionalStatementElseBlock = new Block(nextPosition()); + moduleConditionalStatement = + new ConditionalStatement(nextPosition(), moduleConditionalStatementCondition, + moduleConditionalStatementThenBlock, moduleConditionalStatementElseBlock); + // add statements to module conditional statement (then) + // add module conditional statement to module + moduleBlock.addStatement(moduleConditionalStatement); + + // MODULE STATETEMENTS + moduleContinueStatement = new ContinueStatement(nextPosition()); + moduleBreakStatement = new BreakStatement(nextPosition()); + moduleReturnStatementParameter = new StringLiteral(nextPosition(), "return"); + moduleReturnStatement = new ReturnStatement(nextPosition(), moduleReturnStatementParameter); + // add statements to module + // moduleBlock.addStatement(moduleContinueStatement); + // moduleBlock.addStatement(moduleBreakStatement); + // moduleBlock.addStatement(moduleReturnStatement); + + // MODULE FUNCTION + moduleFunctionBlock = new Block(nextPosition()); + moduleFunctionParameter = new ArrayList<>(); + moduleFunctionDeclaration = + new FunctionDeclaration(nextPosition(), new Identifier("ModuleFunction"), moduleFunctionBlock, + moduleFunctionParameter, new ResolvableIdentifier("String")); + moduleFunctionReturnStatementParameter = new StringLiteral(nextPosition(), "return"); + moduleFunctionReturnStatement = new ReturnStatement(nextPosition(), moduleFunctionReturnStatementParameter); + + // MODULE FUNCTION PROCEDURE + moduleFunctionProcedureBlock = new Block(nextPosition()); + moduleFunctionProcedureParameter = new ArrayList<>(); + moduleFunctionProcedureDeclaration = + new ProcedureDeclaration(nextPosition(), new Identifier("ModuleFunctionProcedure"), + moduleFunctionProcedureBlock, moduleFunctionProcedureParameter); + moduleFunctionProcedureReturnStatementParameter = new StringLiteral(nextPosition(), "return"); + moduleFunctionProcedureReturnStatement = + new ReturnStatement(nextPosition(), moduleFunctionProcedureReturnStatementParameter); + // add module function procedure to module function + // moduleFunctionBlock.addDeclaration(moduleFunctionProcedureDeclaration); + + // MODULE FUNCTION CONDITIONAL STATEMENT + moduleFunctionConditionalStatementCondition = new BooleanLiteral(nextPosition(), false); + moduleFunctionConditionalStatementThenBlock = new Block(nextPosition()); + moduleFunctionConditionalStatementElseBlock = new Block(nextPosition()); + moduleFunctionConditionalStatement = + new ConditionalStatement(nextPosition(), moduleFunctionConditionalStatementCondition, + moduleFunctionConditionalStatementThenBlock, moduleFunctionConditionalStatementElseBlock); + // add module function conditional statement to module function + moduleFunctionBlock.addStatement(moduleFunctionConditionalStatement); + moduleFunctionConditionalReturnThenStatementParameter = new StringLiteral(nextPosition(), "return"); + moduleFunctionConditionalReturnThenStatement = + new ReturnStatement(nextPosition(), moduleFunctionConditionalReturnThenStatementParameter); + moduleFunctionConditionalReturnElseStatementParameter = new StringLiteral(nextPosition(), "return"); + moduleFunctionConditionalReturnElseStatement = + new ReturnStatement(nextPosition(), moduleFunctionConditionalReturnElseStatementParameter); + moduleFunctionConditionalConditionalStatementCondition = new BooleanLiteral(nextPosition(), true); + moduleFunctionConditionalConditionalStatementThenBlock = new Block(nextPosition()); + moduleFunctionConditionalConditionalStatementElseBlock = new Block(nextPosition()); + moduleFunctionConditionalConditionalStatement = + new ConditionalStatement(nextPosition(), moduleFunctionConditionalConditionalStatementCondition, + moduleFunctionConditionalConditionalStatementThenBlock, + moduleFunctionConditionalConditionalStatementElseBlock); + // add module function conditional conditional statement to module + // function conditional else block + moduleFunctionConditionalStatementElseBlock.addStatement(moduleFunctionConditionalConditionalStatement); + moduleFunctionConditionalConditionalReturnStatementParameter = new StringLiteral(nextPosition(), "return"); + moduleFunctionConditionalConditionalReturnStatement = + new ReturnStatement(nextPosition(), moduleFunctionConditionalConditionalReturnStatementParameter); + moduleFunctionConditionalConditionalConditionalStatementCondition = + new BooleanLiteral(new Position("TestFile", 37, 1), false); + moduleFunctionConditionalConditionalConditionalStatementThenBlock = new Block(nextPosition()); + moduleFunctionConditionalConditionalConditionalStatementElseBlock = new Block(nextPosition()); + moduleFunctionConditionalConditionalConditionalStatement = + new ConditionalStatement(nextPosition(), + moduleFunctionConditionalConditionalConditionalStatementCondition, + moduleFunctionConditionalConditionalConditionalStatementThenBlock, + moduleFunctionConditionalConditionalConditionalStatementElseBlock); + // add module function conditional conditional conditional statement to + // module function conditional conditional then block + moduleFunctionConditionalConditionalStatementThenBlock.addStatement(moduleFunctionConditionalConditionalConditionalStatement); + moduleFunctionConditionalConditionalConditionalThenReturnStatementParameter = + new StringLiteral(nextPosition(), "return"); + moduleFunctionConditionalConditionalConditionalThenReturnStatement = + new ReturnStatement(nextPosition(), + moduleFunctionConditionalConditionalConditionalThenReturnStatementParameter); + moduleFunctionConditionalConditionalConditionalElseReturnStatementParameter = + new StringLiteral(nextPosition(), "return"); + moduleFunctionConditionalConditionalConditionalElseReturnStatement = + new ReturnStatement(nextPosition(), + moduleFunctionConditionalConditionalConditionalElseReturnStatementParameter); + + // MODULE FUNCTION LOOP + moduleFunctionLoopCondition = new BooleanLiteral(nextPosition(), true); + moduleFunctionLoopBlock = new Block(nextPosition()); + moduleFunctionLoop = new WhileLoop(nextPosition(), moduleFunctionLoopCondition, moduleFunctionLoopBlock); + // add module function loop to module function + moduleFunctionBlock.addStatement(moduleFunctionLoop); + + moduleFunctionLoopReturnStatementParameter = new StringLiteral(nextPosition(), "return"); + moduleFunctionLoopReturnStatement = + new ReturnStatement(nextPosition(), moduleFunctionLoopReturnStatementParameter); + + moduleFunctionLoopLoopCondition = new BooleanLiteral(nextPosition(), true); + moduleFunctionLoopLoopBlock = new Block(nextPosition()); + moduleFunctionLoopLoop = + new WhileLoop(nextPosition(), moduleFunctionLoopLoopCondition, moduleFunctionLoopLoopBlock); + // ass module function loop loop to module function loop block + moduleFunctionLoopBlock.addStatement(moduleFunctionLoopLoop); + + moduleFunctionLoopLoopLoopCondition = new BooleanLiteral(nextPosition(), true); + moduleFunctionLoopLoopLoopBlock = new Block(nextPosition()); + moduleFunctionLoopLoopLoop = + new WhileLoop(nextPosition(), moduleFunctionLoopLoopLoopCondition, moduleFunctionLoopLoopLoopBlock); + // add module function loop loop loop to module function loop loop block + moduleFunctionLoopLoopBlock.addStatement(moduleFunctionLoopLoopLoop); + + moduleFunctionLoopLoopLoopReturnStatementParameter = new StringLiteral(nextPosition(), "return"); + moduleFunctionLoopLoopLoopReturnStatement = + new ReturnStatement(nextPosition(), moduleFunctionLoopLoopLoopReturnStatementParameter); + + } + + @Test + public void setUpASTTest() { + assertNotNull("setParentVisitor is null", setParentVisitor); + assertNotNull("controlFlowVisitor is null", controlFlowVisitor); + + // MODULE + assertNotNull("moduleDeclaration is null", moduleDeclaration); + assertNotNull("moduleBlock is null", moduleBlock); + assertNotNull("moduleImports is null", moduleImports); + assertNotNull("package is null", aPackage); + + // MODULE LOOP + assertNotNull("moduleLoopCondition is null", moduleLoopCondition); + assertNotNull("moduleLoopBlock is null", moduleLoopBlock); + assertNotNull("moduleLoop is null", moduleLoop); + assertNotNull("moduleLoopContinueStatement is null", moduleLoopContinueStatement); + assertNotNull("moduleLoopBreakStatement is null", moduleLoopBreakStatement); + assertNotNull("moduleLoopLoopCondition is null", moduleLoopLoopCondition); + assertNotNull("moduleLoopLoopBlock is null", moduleLoopLoopBlock); + + // MODULE LOOP LOOP + assertNotNull("moduleLoopLoop is null", moduleLoopLoop); + assertNotNull("moduleLoopLoopContinueStatement is null", moduleLoopLoopContinueStatement); + assertNotNull("moduleLoopLoopBreakStatement is null", moduleLoopLoopBreakStatement); + assertNotNull( + "moduleLoopLoopConditionalStatementCondition is null", + moduleLoopLoopConditionalStatementCondition); + assertNotNull( + "moduleLoopLoopConditionalStatementThenBlock is null", + moduleLoopLoopConditionalStatementThenBlock); + assertNotNull( + "moduleLoopLoopConditionalStatementElseBlock is null", + moduleLoopLoopConditionalStatementElseBlock); + assertNotNull("moduleLoopLoopConditionalStatement is null", moduleLoopLoopConditionalStatement); + assertNotNull( + "moduleLoopLoopThenConditionalStatementCondition is null", + moduleLoopLoopThenConditionalStatementCondition); + assertNotNull( + "moduleLoopLoopThenConditionalStatementThenBlock is null", + moduleLoopLoopThenConditionalStatementThenBlock); + assertNotNull( + "moduleLoopLoopThenConditionalStatementElseBlock is null", + moduleLoopLoopThenConditionalStatementElseBlock); + assertNotNull("moduleLoopLoopThenConditionalStatement is null", moduleLoopLoopThenConditionalStatement); + assertNotNull( + "moduleLoopLoopElseConditionalStatementCondition is null", + moduleLoopLoopElseConditionalStatementCondition); + assertNotNull( + "moduleLoopLoopElseConditionalStatementThenBlock is null", + moduleLoopLoopElseConditionalStatementThenBlock); + assertNotNull( + "moduleLoopLoopElseConditionalStatementElseBlock is null", + moduleLoopLoopElseConditionalStatementElseBlock); + assertNotNull("moduleLoopLoopElseConditionalStatement is null", moduleLoopLoopElseConditionalStatement); + + // MODULE LOOP CONDITIONAL STATEMENT + assertNotNull("moduleLoopConditionalStatementCondition is null", moduleLoopConditionalStatementCondition); + assertNotNull("moduleLoopConditionalStatementThenBlock is null", moduleLoopConditionalStatementThenBlock); + assertNotNull("moduleLoopConditionalStatementElseBlock is null", moduleLoopConditionalStatementElseBlock); + assertNotNull("moduleLoopConditionalStatement is null", moduleLoopConditionalStatement); + assertNotNull("moduleLoopConditionalContinueStatement is null", moduleLoopConditionalContinueStatement); + assertNotNull("moduleLoopConditionalBreakStatement is null", moduleLoopConditionalBreakStatement); + + // MODULE CONDITIONAL STATEMENT + assertNotNull("moduleConditionalStatementCondition is null", moduleConditionalStatementCondition); + assertNotNull("moduleConditionalStatementThenBlock is null", moduleConditionalStatementThenBlock); + assertNotNull("moduleConditionalStatementElseBlock is null", moduleConditionalStatementElseBlock); + assertNotNull("moduleConditionalStatement is null", moduleConditionalStatement); + + // MODULE STATETEMENTS + assertNotNull("moduleContinueStatement is null", moduleContinueStatement); + assertNotNull("moduleBreakStatement is null", moduleBreakStatement); + assertNotNull("moduleReturnStatementParameter is null", moduleReturnStatementParameter); + assertNotNull("moduleReturnStatement is null", moduleReturnStatement); + + // MODULE FUNCTION + assertNotNull("moduleFunctionBlock is null", moduleFunctionBlock); + assertNotNull("moduleFunctionParameter is null", moduleFunctionParameter); + assertNotNull("moduleFunctionDeclaration is null", moduleFunctionDeclaration); + assertNotNull("moduleFunctionReturnStatementParameter is null", moduleFunctionReturnStatementParameter); + assertNotNull("moduleFunctionReturnStatement is null", moduleFunctionReturnStatement); + + // MODULE FUNCTION PROCEDURE + assertNotNull("moduleFunctionProcedureBlock is null", moduleFunctionProcedureBlock); + assertNotNull("moduleFunctionProcedureParameter is null", moduleFunctionProcedureParameter); + assertNotNull("moduleFunctionProcedureDeclaration is null", moduleFunctionProcedureDeclaration); + assertNotNull( + "moduleFunctionProcedureReturnStatementParameter is null", + moduleFunctionProcedureReturnStatementParameter); + assertNotNull("moduleFunctionProcedureReturnStatement is null", moduleFunctionProcedureReturnStatement); + + // MODULE FUNCTION CONDITIONAL STATEMENT + assertNotNull( + "moduleFunctionConditionalStatementCondition is null", + moduleFunctionConditionalStatementCondition); + assertNotNull( + "moduleFunctionConditionalStatementThenBlock is null", + moduleFunctionConditionalStatementThenBlock); + assertNotNull( + "moduleFunctionConditionalStatementElseBlock is null", + moduleFunctionConditionalStatementElseBlock); + assertNotNull("moduleFunctionConditionalStatement is null", moduleFunctionConditionalStatement); + assertNotNull( + "moduleFunctionConditionalReturnThenStatementParameter is null", + moduleFunctionConditionalReturnThenStatementParameter); + assertNotNull( + "moduleFunctionConditionalReturnThenStatement is null", + moduleFunctionConditionalReturnThenStatement); + assertNotNull( + "moduleFunctionConditionalReturnElseStatementParameter is null", + moduleFunctionConditionalReturnElseStatementParameter); + assertNotNull( + "moduleFunctionConditionalReturnElseStatement is null", + moduleFunctionConditionalReturnElseStatement); + assertNotNull( + "moduleFunctionConditionalConditionalStatementCondition is null", + moduleFunctionConditionalConditionalStatementCondition); + assertNotNull( + "moduleFunctionConditionalConditionalStatementThenBlock is null", + moduleFunctionConditionalConditionalStatementThenBlock); + assertNotNull( + "moduleFunctionConditionalConditionalStatementElseBlock is null", + moduleFunctionConditionalConditionalStatementElseBlock); + assertNotNull( + "moduleFunctionConditionalConditionalStatement is null", + moduleFunctionConditionalConditionalStatement); + assertNotNull( + "moduleFunctionConditionalConditionalReturnStatementParameter is null", + moduleFunctionConditionalConditionalReturnStatementParameter); + assertNotNull( + "moduleFunctionConditionalConditionalReturnStatement is null", + moduleFunctionConditionalConditionalReturnStatement); + assertNotNull( + "moduleFunctionConditionalConditionalConditionalStatementCondition is null", + moduleFunctionConditionalConditionalConditionalStatementCondition); + assertNotNull( + "moduleFunctionConditionalConditionalConditionalStatementThenBlock is null", + moduleFunctionConditionalConditionalConditionalStatementThenBlock); + assertNotNull( + "moduleFunctionConditionalConditionalConditionalStatementElseBlock is null", + moduleFunctionConditionalConditionalConditionalStatementElseBlock); + assertNotNull( + "moduleFunctionConditionalConditionalConditionalStatement is null", + moduleFunctionConditionalConditionalConditionalStatement); + assertNotNull( + "moduleFunctionConditionalConditionalConditionalThenReturnStatementParameter is null", + moduleFunctionConditionalConditionalConditionalThenReturnStatementParameter); + assertNotNull( + "moduleFunctionConditionalConditionalConditionalThenReturnStatement is null", + moduleFunctionConditionalConditionalConditionalThenReturnStatement); + assertNotNull( + "moduleFunctionConditionalConditionalConditionalElseReturnStatementParameter is null", + moduleFunctionConditionalConditionalConditionalElseReturnStatementParameter); + assertNotNull( + "moduleFunctionConditionalConditionalConditionalElseReturnStatement is null", + moduleFunctionConditionalConditionalConditionalElseReturnStatement); + + // MODULE FUNCTION LOOP + assertNotNull("moduleFunctionLoopCondition is null", moduleFunctionLoopCondition); + assertNotNull("moduleFunctionLoopBlock is null", moduleFunctionLoopBlock); + assertNotNull("moduleFunctionLoop is null", moduleFunctionLoop); + assertNotNull("moduleFunctionLoopReturnStatementParameter is null", moduleFunctionLoopReturnStatementParameter); + assertNotNull("moduleFunctionLoopReturnStatement is null", moduleFunctionLoopReturnStatement); + assertNotNull("moduleFunctionLoopLoopCondition is null", moduleFunctionLoopLoopCondition); + assertNotNull("moduleFunctionLoopLoopBlock is null", moduleFunctionLoopLoopBlock); + assertNotNull("moduleFunctionLoopLoop is null", moduleFunctionLoopLoop); + assertNotNull("moduleFunctionLoopLoopLoopCondition is null", moduleFunctionLoopLoopLoopCondition); + assertNotNull("moduleFunctionLoopLoopLoopBlock is null", moduleFunctionLoopLoopLoopBlock); + assertNotNull("moduleFunctionLoopLoopLoop is null", moduleFunctionLoopLoopLoop); + assertNotNull( + "moduleFunctionLoopLoopLoopReturnStatementParameter is null", + moduleFunctionLoopLoopLoopReturnStatementParameter); + assertNotNull("moduleFunctionLoopLoopLoopReturnStatement is null", moduleFunctionLoopLoopLoopReturnStatement); + } + + /** Creates a continue statement inside of a while loop. */ + @Test + public void continueStatementTest01() { + // add previously defined statement to module loop + moduleLoopBlock.addStatement(moduleLoopContinueStatement); + + // control flow visitor should not complain about it, since the + // structure is + // valid + setParentVisitor.visit(aPackage); + controlFlowVisitor.visit(aPackage); + } + + /** Creates a continue statement inside of a nested while loop. */ + @Test + public void continueStatementTest02() { + // add previously defined statement to module loop + moduleLoopLoopBlock.addStatement(moduleLoopLoopContinueStatement); + + // control flow visitor should not complain about it, since the + // structure is + // valid + setParentVisitor.visit(aPackage); + controlFlowVisitor.visit(aPackage); + } + + /** Creates a continue statement inside of a conditional statement within a while loop */ + @Test + public void continueStatementTest03() { + // add statements to module loop conditional statement (then) + moduleLoopConditionalStatementThenBlock.addStatement(moduleLoopConditionalContinueStatement); + + // control flow visitor should not complain about it, since the + // structure is + // valid + setParentVisitor.visit(aPackage); + controlFlowVisitor.visit(aPackage); + } + + /** Create continue statement outside of a while loop */ + @Test(expected = InvalidControlFlowException.class) + public void continueStatementTest04() { + moduleBlock.addStatement(moduleContinueStatement); + + // control flow visitor should throw an exception now, since the + // structure is invalid + setParentVisitor.visit(aPackage); + controlFlowVisitor.visit(aPackage); + } + + /** Create break statement outside of a while loop */ + @Test(expected = InvalidControlFlowException.class) + public void breakStatementTest04() { + moduleBlock.addStatement(moduleBreakStatement); + + // control flow visitor should throw an exception now, since the + // structure is invalid + setParentVisitor.visit(aPackage); + controlFlowVisitor.visit(aPackage); + } + + /** Creates return statement outside of a function block */ + @Test(expected = InvalidControlFlowException.class) + public void returnStatementTest01() { + moduleBlock.addStatement(moduleReturnStatement); + + // control flow visitor should throw an exception now, since the + // structure is invalid + setParentVisitor.visit(aPackage); + controlFlowVisitor.visit(aPackage); + } + + /** Creates a return statement inside of a function block */ + @Test + public void returnStatementTest02() { + // add function to module + moduleBlock.addDeclaration(moduleFunctionDeclaration); + // ad a return statement to module function block + moduleFunctionBlock.addStatement(moduleFunctionReturnStatement); + + // control flow visitor should not complain about it, since the + // structure is + // valid + setParentVisitor.visit(aPackage); + controlFlowVisitor.visit(aPackage); + } + + /** Creates a return statement inside of a nested procedure declaration within a function block */ + @Test + public void returnStatementTest03() { + // add function to module + moduleBlock.addDeclaration(moduleFunctionDeclaration); + // add return statement to procedure + moduleFunctionProcedureBlock.addStatement(moduleFunctionProcedureReturnStatement); + // add procedure to function + moduleFunctionBlock.addDeclaration(moduleFunctionProcedureDeclaration); + + // start visitors and expect InvalidControlFlowException, since there's + // no guarantee, that the function always executes a return statement + boolean invalidControlFlow = false; + try { + setParentVisitor.visit(aPackage); + controlFlowVisitor.visit(aPackage); + } catch (InvalidControlFlowException icfe) { + invalidControlFlow = true; + } + // there should have been an InvalidControlFlowException during the + // visit ... + assertTrue("ReturnStatements needed inside the moduleFunction", invalidControlFlow); + + // now, add another return statement to the surrounding function + moduleFunctionBlock.addStatement(moduleFunctionReturnStatement); + + // control flow visitor should not complain anymore, since the + // structure is now valid + setParentVisitor.visit(aPackage); + controlFlowVisitor.visit(aPackage); + } + + /** Creates a return statement inside of a conditional statement within a function block */ + @Test + public void returnStatementTest04() { + // add function to module + moduleBlock.addDeclaration(moduleFunctionDeclaration); + // add module function conditional return statement to module function + // conditional statement + moduleFunctionConditionalStatementElseBlock.addStatement(moduleFunctionConditionalReturnElseStatement); + // add module function conditional statement to module function block + moduleFunctionBlock.addStatement(moduleFunctionConditionalStatement); + + // control flow visitor should definitely complain about it, since there + // is only a return statement in the else block, but neither in the then + // block, nor in the function itself. + boolean invalidControlFlow = false; + try { + setParentVisitor.visit(aPackage); + controlFlowVisitor.visit(aPackage); + } catch (InvalidControlFlowException icfe) { + invalidControlFlow = true; + } + // there should have been an InvalidControlFlowException during the + // visit ... + assertTrue("ReturnStatements does not need to be found inside both conditional branches", invalidControlFlow); + + // now, add another return statement to the surrounding function + moduleFunctionBlock.addStatement(moduleFunctionReturnStatement); + + // run visitors again + setParentVisitor.visit(aPackage); + controlFlowVisitor.visit(aPackage); + + // The controlFlowVisitor should not complain about anything anymore, + // since the structure is now valid. + } + + /** Creates a return statement inside of a conditional statement within a function block again, but resolve errors by + * adding another conditional return statement */ + @Test + public void returnStatementTest05() { + // add function to module + moduleBlock.addDeclaration(moduleFunctionDeclaration); + // add module function conditional return statement to module function + // conditional statement + moduleFunctionConditionalStatementElseBlock.addStatement(moduleFunctionConditionalReturnElseStatement); + // add module function conditional statement to module function block + moduleFunctionBlock.addStatement(moduleFunctionConditionalStatement); + + // control flow visitor should definitely complain about it, since there + // is only a return statement in the else block, but neither in the then + // block, nor in the function itself. + boolean invalidControlFlow = false; + try { + setParentVisitor.visit(aPackage); + controlFlowVisitor.visit(aPackage); + } catch (InvalidControlFlowException icfe) { + invalidControlFlow = true; + } + // there should have been an InvalidControlFlowException during the + // visit ... + assertTrue("ReturnStatements does not need to be found inside both conditional branches", invalidControlFlow); + + // add return statement to conditional statements then block + moduleFunctionConditionalStatementThenBlock.addStatement(moduleFunctionConditionalReturnThenStatement); + + // run visitors again + setParentVisitor.visit(aPackage); + controlFlowVisitor.visit(aPackage); + + // The controlFlowVisitor should not complain about anything, since the + // structure is valid. + } + + /** Creates return statement inside of a 3-times nested conditional statement within a function block */ + @Test + public void returnStatementTest06() { + // add function to module + moduleBlock.addDeclaration(moduleFunctionDeclaration); + // add module function conditional conditional conditional return + // statement to module function conditional conditional conditional then + // block + moduleFunctionConditionalConditionalConditionalStatementElseBlock.addStatement(moduleFunctionConditionalConditionalConditionalElseReturnStatement); + + // control flow should be invalid now, since there's no global return + // statement + boolean invalidControlFlow = false; + try { + setParentVisitor.visit(aPackage); + controlFlowVisitor.visit(aPackage); + } catch (InvalidControlFlowException icfe) { + invalidControlFlow = true; + } + // there should have been an InvalidControlFlowException during the + // visit ... + assertTrue("ReturnStatements does not need to be found inside both conditional branches", invalidControlFlow); + + // resolve these errors by adding another return statement to each + // conditional branch + moduleFunctionConditionalConditionalConditionalStatementThenBlock.addStatement(moduleFunctionConditionalConditionalConditionalThenReturnStatement); + moduleFunctionConditionalConditionalStatementElseBlock.addStatement(moduleFunctionConditionalConditionalReturnStatement); + moduleFunctionConditionalStatementThenBlock.addStatement(moduleFunctionConditionalReturnThenStatement); + + // everything should be just fine now + setParentVisitor.visit(aPackage); + controlFlowVisitor.visit(aPackage); + } + + /** Creates return statement inside a while loop within a function block */ + @Test + public void returnStatementTest07() { + // add function to module + moduleBlock.addDeclaration(moduleFunctionDeclaration); + // add module function loop return statement to module function loop + // block + moduleFunctionLoopBlock.addStatement(moduleFunctionLoopReturnStatement); + + // control flow should be invalid now, since there's no global return + // statement + boolean invalidControlFlow = false; + try { + setParentVisitor.visit(aPackage); + controlFlowVisitor.visit(aPackage); + } catch (InvalidControlFlowException icfe) { + invalidControlFlow = true; + } + // there should have been an InvalidControlFlowException during the + // visit ... + assertTrue("ReturnStatements does not need to be found inside both conditional branches", invalidControlFlow); + + // resolve errors by adding a return statement to module function + moduleFunctionBlock.addStatement(moduleFunctionReturnStatement); + + // everything should be just fine now + setParentVisitor.visit(aPackage); + controlFlowVisitor.visit(aPackage); + } + + /** Create return statement inside of a 3-times nested while loop within a function block */ + @Test + public void returnStatementTest08() { + // add function to module + moduleBlock.addDeclaration(moduleFunctionDeclaration); + // add module function loop loop loop return statement to module + // function loop loop loop block + moduleFunctionLoopLoopLoopBlock.addStatement(moduleFunctionLoopLoopLoopReturnStatement); + + // control flow should be invalid now, since there's no global return + // statement + boolean invalidControlFlow = false; + try { + setParentVisitor.visit(aPackage); + controlFlowVisitor.visit(aPackage); + } catch (InvalidControlFlowException icfe) { + invalidControlFlow = true; + } + // there should have been an InvalidControlFlowException during the + // visit ... + assertTrue("ReturnStatements does not need to be found inside both conditional branches", invalidControlFlow); + + // resolve errors by adding a return statement to module function + moduleFunctionBlock.addStatement(moduleFunctionReturnStatement); + + // everything should be just fine now + setParentVisitor.visit(aPackage); + controlFlowVisitor.visit(aPackage); + } + + /** Creates a conditional statement inside a while loop */ + @Test + public void conditionalStatementTest01() { + moduleLoopBlock.addStatement(moduleLoopConditionalStatement); + + // control flow visitor should not complain about it, since the + // structure is valid + setParentVisitor.visit(aPackage); + controlFlowVisitor.visit(aPackage); + } + + /** Creates a conditional statement inside a conditional statements then block */ + @Test + public void conditionalStatementTest02() { + moduleConditionalStatementThenBlock.addStatement(moduleLoopConditionalStatement); + + // control flow visitor should not complain about it, since the + // structure is valid + setParentVisitor.visit(aPackage); + controlFlowVisitor.visit(aPackage); + } + + /** Creates a conditional statement inside a conditional statements else block */ + @Test + public void conditionalStatementTest03() { + moduleConditionalStatementElseBlock.addStatement(moduleLoopConditionalStatement); + + // control flow visitor should not complain about it, since the + // structure is valid + setParentVisitor.visit(aPackage); + controlFlowVisitor.visit(aPackage); + } + + /** Creates a conditional statement inside of a nested while loop */ + @Test + public void conditionalStatementTest04() { + moduleLoopLoopBlock.addStatement(moduleLoopLoopConditionalStatement); + + // everything should be just fine + setParentVisitor.visit(aPackage); + controlFlowVisitor.visit(aPackage); + } + + /** Creates conditional statement inside of a nested conditional statement within a while loop */ + @Test + public void conditionalStatementTest05() { + // add a conditional statement inside a nested while loop + moduleLoopLoopBlock.addStatement(moduleLoopLoopConditionalStatement); + // add some more conditional statements to the one above + moduleLoopLoopConditionalStatementThenBlock.addStatement(moduleLoopLoopThenConditionalStatement); + moduleLoopLoopConditionalStatementElseBlock.addStatement(moduleLoopLoopElseConditionalStatement); + + // everything should be just fine + setParentVisitor.visit(aPackage); + controlFlowVisitor.visit(aPackage); + } +} diff --git a/src/test/java/de/uni/bremen/monty/moco/ast/DeclarationTest.java b/src/test/java/de/uni/bremen/monty/moco/ast/DeclarationTest.java new file mode 100644 index 0000000..9719b72 --- /dev/null +++ b/src/test/java/de/uni/bremen/monty/moco/ast/DeclarationTest.java @@ -0,0 +1,971 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast; + +import de.uni.bremen.monty.moco.ast.declaration.*; +import de.uni.bremen.monty.moco.ast.expression.Expression; +import de.uni.bremen.monty.moco.ast.expression.FunctionCall; +import de.uni.bremen.monty.moco.ast.expression.MemberAccess; +import de.uni.bremen.monty.moco.ast.expression.VariableAccess; +import de.uni.bremen.monty.moco.ast.expression.literal.BooleanLiteral; +import de.uni.bremen.monty.moco.ast.expression.literal.StringLiteral; +import de.uni.bremen.monty.moco.ast.statement.*; +import de.uni.bremen.monty.moco.exception.InvalidPlaceToDeclareException; +import de.uni.bremen.monty.moco.exception.RedeclarationException; +import de.uni.bremen.monty.moco.visitor.DeclarationVisitor; +import de.uni.bremen.monty.moco.visitor.SetParentVisitor; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.*; + +/** Test the DeclarationVisitor. + *

+ * Note the following limitations! This does not test:
+ * - Overriding
+ * - Overloading
+ * - Inheritance with multiple super-classes
+ * - Access-modifiers */ +public class DeclarationTest { + + private SetParentVisitor setParentVisitor; + private DeclarationVisitor declarationVisitor; + private int lineCounter = 0; + + // module + private Import moduleImport01; + private Import moduleImport02; + private List moduleImports; + private Block moduleBlock; + private Package aPackage; + private ModuleDeclaration moduleDeclaration; + + // module class + private Block classBlock; + private ClassDeclaration classDeclaration; + private VariableDeclaration classVariableDeclaration; + + private Block classFunctionBlock; + private List classFunctionParams; + private FunctionDeclaration classFunctionDeclaration; + + private Block classProcedureBlock; + private List classProcedureParams; + private ProcedureDeclaration classProcedureDeclaration; + + // module class extends + private Block extendedClassBlock; + private ClassDeclaration extendedClassDeclaration; + + // module function + private Block moduleFunctionBlock; + private VariableDeclaration moduleFunctionParamsVariable01; + private VariableDeclaration moduleFunctionParamsVariable02; + private List moduleFunctionParams; + private FunctionDeclaration moduleFunctionDeclaration; + private VariableDeclaration moduleFunctionVariableDeclaration; + private Block moduleFunctionFunctionBlock; + private List moduleFunctionFunctionParams; + private FunctionDeclaration moduleFunctionFunctionDeclaration; + private Block moduleFunctionProcedureBlock; + private List moduleFunctionProcedureParams; + private ProcedureDeclaration moduleFunctionProcedureDeclaration; + + // module procedure + private Block moduleProcedureBlock; + private VariableDeclaration moduleProcedureParamsVariable01; + private VariableDeclaration moduleProcedureParamsVariable02; + private List moduleProcedureParams; + private ProcedureDeclaration moduleProcedureDeclaration; + private VariableDeclaration moduleProcedureVariableDeclaration; + private Block moduleProcedureFunctionBlock; + private List moduleProcedureFunctionParams; + private FunctionDeclaration moduleProcedureFunctionDeclaration; + private Block moduleProcedureProcedureBlock; + private List moduleProcedureProcedureParams; + private ProcedureDeclaration moduleProcedureProcedureDeclaration; + + // module variable + private VariableDeclaration moduleVariableDeclaration; + + // module loop + private Expression moduleLoopCondition; + private Block moduleLoopBlock; + private WhileLoop moduleLoop; + private ContinueStatement moduleLoopContinueStatement; + private BreakStatement moduleLoopBreakStatement; + + // module conditional + private Expression moduleConditionalStatementCondition; + private ConditionalStatement moduleConditionalStatement; + private Block moduleConditionalStatementThenBlock; + private Block moduleConditionalStatementElseBlock; + + // module function return statement + private Expression moduleReturnStatementParameter; + private ReturnStatement moduleReturnStatement; + + // module procedure call + private Expression moduleProcedureCallFunctionCallParameter01; + private Expression moduleProcedureCallFunctionCallParameter02; + private List moduleProcedureCallFunctionCallParameters; + private FunctionCall moduleProcedureCall; + + // module assignment with function call as left side + private VariableDeclaration moduleAssignmentMemberAccessVariableDeclaration; + private VariableAccess moduleAssignmentMemberAccessVariableAccessClass; + private VariableAccess moduleAssignmentMemberAccessVariableAccessVariable; + private MemberAccess moduleAssignmentMemberAccess; + private Expression moduleAssignmentFunctionCallParameter01; + private Expression moduleAssignmentFunctionCallParameter02; + private List moduleAssignmentFunctionCallParameters; + private FunctionCall moduleAssignmentFunctionCall; + private Assignment moduleAssignment; + + // invalid modul + private Import invalidModuleImport01; + private Import invalidModuleImport02; + private List invalidModuleImports; + private Block invalidModuleBlock; + private ModuleDeclaration invalidModuleDeclaration; + + // invalid class + private List invalidClassSuperClasses; + private Block invalidClassBlock; + private ClassDeclaration invalidClassDeclaration; + + private Position buildPosition() { + return new Position("declarationTest", lineCounter++, 0); + } + + @Before + public void setUpAST() { + lineCounter = 0; + setParentVisitor = new SetParentVisitor(); + setParentVisitor.setStopOnFirstError(true); + declarationVisitor = new DeclarationVisitor(); + declarationVisitor.setStopOnFirstError(true); + + // module + moduleImport01 = new Import(buildPosition(), new ResolvableIdentifier("Dummy")); + moduleImport02 = new Import(buildPosition(), new ResolvableIdentifier("Dummy")); + moduleImports = new ArrayList(); + moduleBlock = new Block(buildPosition()); + aPackage = new Package(new Identifier("")); + moduleDeclaration = + new ModuleDeclaration(buildPosition(), new Identifier("moduleDeclaration"), moduleBlock, moduleImports); + aPackage.addModule(moduleDeclaration); + + // module class + classBlock = new Block(buildPosition()); + List classDeclSuperClasses = new ArrayList(); + classDeclaration = + new ClassDeclaration(buildPosition(), new Identifier("classDeclaration"), classDeclSuperClasses, + classBlock); + classVariableDeclaration = + new VariableDeclaration(buildPosition(), new Identifier("classVariableDeclaration"), + new ResolvableIdentifier("String"), VariableDeclaration.DeclarationType.ATTRIBUTE); + + classFunctionBlock = new Block(buildPosition()); + classFunctionParams = new ArrayList(); + classFunctionDeclaration = + new FunctionDeclaration(buildPosition(), new Identifier("classFunctionDeclaration"), + classFunctionBlock, classFunctionParams, new ResolvableIdentifier("String")); + + classProcedureBlock = new Block(buildPosition()); + classProcedureParams = new ArrayList(); + classProcedureDeclaration = + new ProcedureDeclaration(buildPosition(), new Identifier("classProcedureDeclaration"), + classProcedureBlock, classProcedureParams); + + // module class extended + extendedClassBlock = new Block(buildPosition()); + List extendedClassDeclSuperClasses = new ArrayList(); + extendedClassDeclSuperClasses.add(new ResolvableIdentifier("classDeclaration")); + extendedClassDeclaration = + new ClassDeclaration(buildPosition(), new Identifier("extendedClassDeclaration"), + extendedClassDeclSuperClasses, extendedClassBlock); + + // module function + moduleFunctionBlock = new Block(buildPosition()); + moduleFunctionParamsVariable01 = + new VariableDeclaration(buildPosition(), new Identifier("moduleFunctionParamsVariable01"), + new ResolvableIdentifier("String"), VariableDeclaration.DeclarationType.PARAMETER); + moduleFunctionParamsVariable02 = + new VariableDeclaration(buildPosition(), new Identifier("moduleFunctionParamsVariable02"), + new ResolvableIdentifier("String"), VariableDeclaration.DeclarationType.PARAMETER); + moduleFunctionParams = new ArrayList(); + moduleFunctionDeclaration = + new FunctionDeclaration(buildPosition(), new Identifier("moduleFunctionDeclaration"), + moduleFunctionBlock, moduleFunctionParams, new ResolvableIdentifier("String")); + moduleFunctionVariableDeclaration = + new VariableDeclaration(buildPosition(), new Identifier("moduleFunctionVariableDeclaration"), + new ResolvableIdentifier("String"), VariableDeclaration.DeclarationType.VARIABLE); + moduleFunctionFunctionBlock = new Block(buildPosition()); + moduleFunctionFunctionParams = new ArrayList(); + moduleFunctionFunctionDeclaration = + new FunctionDeclaration(buildPosition(), new Identifier("moduleFunctionFunctionDeclaration"), + moduleFunctionFunctionBlock, moduleFunctionFunctionParams, new ResolvableIdentifier("String")); + moduleFunctionProcedureBlock = new Block(buildPosition()); + moduleFunctionProcedureParams = new ArrayList(); + moduleFunctionProcedureDeclaration = + new ProcedureDeclaration(buildPosition(), new Identifier("moduleFunctionProcedureDeclaration"), + moduleFunctionProcedureBlock, moduleFunctionProcedureParams); + + // module procedure + moduleProcedureBlock = new Block(buildPosition()); + moduleProcedureParamsVariable01 = + new VariableDeclaration(buildPosition(), new Identifier("moduleProcedureParamsVariable01"), + new ResolvableIdentifier("String"), VariableDeclaration.DeclarationType.PARAMETER); + moduleProcedureParamsVariable02 = + new VariableDeclaration(buildPosition(), new Identifier("moduleProcedureParamsVariable02"), + new ResolvableIdentifier("String"), VariableDeclaration.DeclarationType.PARAMETER); + moduleProcedureParams = new ArrayList(); + moduleProcedureDeclaration = + new ProcedureDeclaration(buildPosition(), new Identifier("moduleProcedureDeclaration"), + moduleProcedureBlock, moduleProcedureParams); + moduleProcedureVariableDeclaration = + new VariableDeclaration(buildPosition(), new Identifier("moduleProcedureVariableDeclaration"), + new ResolvableIdentifier("String"), VariableDeclaration.DeclarationType.VARIABLE); + moduleProcedureFunctionBlock = new Block(buildPosition()); + moduleProcedureFunctionParams = new ArrayList(); + moduleProcedureFunctionDeclaration = + new FunctionDeclaration(buildPosition(), new Identifier("moduleProcedureFunctionDeclaration"), + moduleProcedureFunctionBlock, moduleProcedureFunctionParams, new ResolvableIdentifier("String")); + moduleProcedureProcedureBlock = new Block(buildPosition()); + moduleProcedureProcedureParams = new ArrayList(); + moduleProcedureProcedureDeclaration = + new ProcedureDeclaration(buildPosition(), new Identifier("moduleProcedureProcedureDeclaration"), + moduleProcedureProcedureBlock, moduleProcedureProcedureParams); + + // module variable + moduleVariableDeclaration = + new VariableDeclaration(buildPosition(), new Identifier("moduleVariableDeclaration"), + new ResolvableIdentifier("String"), VariableDeclaration.DeclarationType.VARIABLE); + + // module loop + moduleLoopCondition = new BooleanLiteral(buildPosition(), true); + moduleLoopBlock = new Block(buildPosition()); + moduleLoop = new WhileLoop(buildPosition(), moduleLoopCondition, moduleLoopBlock); + moduleLoopContinueStatement = new ContinueStatement(buildPosition()); + moduleLoopBreakStatement = new BreakStatement(buildPosition()); + + // module conditional + moduleConditionalStatementCondition = new BooleanLiteral(buildPosition(), true); + moduleConditionalStatementThenBlock = new Block(buildPosition()); + moduleConditionalStatementElseBlock = new Block(buildPosition()); + moduleConditionalStatement = + new ConditionalStatement(buildPosition(), moduleConditionalStatementCondition, + moduleConditionalStatementThenBlock, moduleConditionalStatementElseBlock); + + // module function return statement + moduleReturnStatementParameter = new StringLiteral(buildPosition(), "42"); + moduleReturnStatement = new ReturnStatement(buildPosition(), moduleReturnStatementParameter); + + // module procedure call + moduleProcedureCallFunctionCallParameter01 = new StringLiteral(buildPosition(), "42"); + moduleProcedureCallFunctionCallParameter02 = new StringLiteral(buildPosition(), "42"); + moduleProcedureCallFunctionCallParameters = new ArrayList(); + + moduleProcedureCall = + new FunctionCall(buildPosition(), new ResolvableIdentifier("moduleProcedureDeclaration"), + moduleProcedureCallFunctionCallParameters); + + // module assignment with function call as left side + moduleAssignmentMemberAccessVariableDeclaration = + new VariableDeclaration(buildPosition(), new Identifier( + "moduleAssignmentMemberAccessVariableDeclaration"), + new ResolvableIdentifier("classDeclaration"), VariableDeclaration.DeclarationType.VARIABLE); + moduleAssignmentMemberAccessVariableAccessClass = + new VariableAccess(buildPosition(), new ResolvableIdentifier( + "moduleAssignmentMemberAccessVariableDeclaration")); + moduleAssignmentMemberAccessVariableAccessVariable = + new VariableAccess(buildPosition(), new ResolvableIdentifier("classVariableDeclaration")); + moduleAssignmentMemberAccess = + new MemberAccess(buildPosition(), moduleAssignmentMemberAccessVariableAccessClass, + moduleAssignmentMemberAccessVariableAccessVariable); + moduleAssignmentFunctionCallParameter01 = new StringLiteral(buildPosition(), "42"); + moduleAssignmentFunctionCallParameter02 = new StringLiteral(buildPosition(), "42"); + moduleAssignmentFunctionCallParameters = new ArrayList(); + moduleAssignmentFunctionCall = + new FunctionCall(buildPosition(), new ResolvableIdentifier("moduleFunctionDeclaration"), + moduleAssignmentFunctionCallParameters); + moduleAssignment = new Assignment(buildPosition(), moduleAssignmentMemberAccess, moduleAssignmentFunctionCall); + + // invalid modul + invalidModuleImport01 = new Import(buildPosition(), new ResolvableIdentifier("Dummy")); + invalidModuleImport02 = new Import(buildPosition(), new ResolvableIdentifier("Dummy")); + invalidModuleImports = new ArrayList(); + invalidModuleBlock = new Block(buildPosition()); + invalidModuleDeclaration = + new ModuleDeclaration(buildPosition(), new Identifier("invalidModuleDeclaration"), invalidModuleBlock, + invalidModuleImports); + + // invalid class + invalidClassBlock = new Block(buildPosition()); + invalidClassSuperClasses = new ArrayList(); + invalidClassDeclaration = + new ClassDeclaration(buildPosition(), new Identifier("invalidClass"), invalidClassSuperClasses, + invalidClassBlock); + + } + + private void fillASTModule() { + moduleImports.add(moduleImport01); + moduleImports.add(moduleImport02); + } + + private void fillASTClass() { + moduleBlock.addDeclaration(classDeclaration); + } + + private void fillASTClassVariable() { + classBlock.addDeclaration(classVariableDeclaration); + } + + private void fillASTClassFunction() { + classBlock.addDeclaration(classFunctionDeclaration); + } + + private void fillASTClassProcedure() { + classBlock.addDeclaration(classProcedureDeclaration); + } + + private void fillASTExtendedClass() { + moduleBlock.addDeclaration(extendedClassDeclaration); + } + + private void fillASTModuleFunction() { + moduleBlock.addDeclaration(moduleFunctionDeclaration); + } + + private void fillASTModuleFunctionVariable() { + moduleFunctionParams.add(moduleFunctionParamsVariable01); + moduleFunctionParams.add(moduleFunctionParamsVariable02); + moduleFunctionBlock.addDeclaration(moduleFunctionVariableDeclaration); + } + + private void fillASTModuleFunctionFunction() { + moduleFunctionBlock.addDeclaration(moduleFunctionFunctionDeclaration); + } + + private void fillASTModuleFunctionProcedure() { + moduleFunctionBlock.addDeclaration(moduleFunctionProcedureDeclaration); + } + + private void fillASTModuleProcedure() { + moduleBlock.addDeclaration(moduleProcedureDeclaration); + } + + private void fillASTModuleProcedureVariable() { + moduleProcedureParams.add(moduleProcedureParamsVariable01); + moduleProcedureParams.add(moduleProcedureParamsVariable02); + moduleProcedureBlock.addDeclaration(moduleProcedureVariableDeclaration); + } + + private void fillASTModuleProcedureFunction() { + moduleProcedureBlock.addDeclaration(moduleProcedureFunctionDeclaration); + } + + private void fillASTModuleProcedureProcedure() { + moduleProcedureBlock.addDeclaration(moduleProcedureProcedureDeclaration); + } + + private void fillASTModuleVariable() { + moduleBlock.addDeclaration(moduleVariableDeclaration); + } + + private void fillASTModuleStatements() { + moduleLoopBlock.addStatement(moduleLoopContinueStatement); + moduleLoopBlock.addStatement(moduleLoopBreakStatement); + + moduleBlock.addDeclaration(moduleAssignmentMemberAccessVariableDeclaration); + moduleBlock.addStatement(moduleLoop); + moduleBlock.addStatement(moduleConditionalStatement); + moduleBlock.addStatement(moduleReturnStatement); + + moduleProcedureCallFunctionCallParameters.add(moduleProcedureCallFunctionCallParameter01); + moduleProcedureCallFunctionCallParameters.add(moduleProcedureCallFunctionCallParameter02); + moduleBlock.addStatement(moduleProcedureCall); + + moduleAssignmentFunctionCallParameters.add(moduleAssignmentFunctionCallParameter01); + moduleAssignmentFunctionCallParameters.add(moduleAssignmentFunctionCallParameter02); + moduleBlock.addStatement(moduleAssignment); + } + + private void fillASTInvalidModule() { + invalidModuleImports.add(invalidModuleImport01); + invalidModuleImports.add(invalidModuleImport02); + } + + @Test + public void setUpASTTest() { + assertNotNull("setParentVisitor is null", setParentVisitor); + assertNotNull("declarationVisitor is null", declarationVisitor); + + assertNotNull("moduleImport01 is null", moduleImport01); + assertNotNull("moduleImport02 is null", moduleImport02); + assertNotNull("moduleImports is null", moduleImports); + assertNotNull("moduleBlock is null", moduleBlock); + assertNotNull("moduleDeclaration is null", moduleDeclaration); + assertNotNull("package is null", aPackage); + + assertNotNull("classDeclarationDeclarations is null", classBlock); + assertNotNull("classDeclaration is null", classDeclaration); + assertNotNull("classVariableDeclaration is null", classVariableDeclaration); + + assertNotNull("classFunctionBlock is null", classFunctionBlock); + assertNotNull("classFunctionParams is null", classFunctionParams); + assertNotNull("classFunctionDeclaration is null", classFunctionDeclaration); + + assertNotNull("classProcedureBlock is null", classProcedureBlock); + assertNotNull("classProcedureParams is null", classProcedureParams); + assertNotNull("classProcedureDeclaration is null", classProcedureDeclaration); + + assertNotNull("extendedClassDeclarationDeclarations is null", extendedClassBlock); + assertNotNull("extendedClassDeclaration is null", extendedClassDeclaration); + + assertNotNull("moduleFunctionBlock is null", moduleFunctionBlock); + assertNotNull("moduleFunctionParamsVariable01 is null", moduleFunctionParamsVariable01); + assertNotNull("moduleFunctionParamsVariable02 is null", moduleFunctionParamsVariable02); + assertNotNull("moduleFunctionParams is null", moduleFunctionParams); + assertNotNull("moduleFunctionDeclaration is null", moduleFunctionDeclaration); + assertNotNull("moduleFunctionVariableDeclaration is null", moduleFunctionVariableDeclaration); + assertNotNull("moduleFunctionFunctionBlock is null", moduleFunctionFunctionBlock); + assertNotNull("moduleFunctionFunctionParams is null", moduleFunctionFunctionParams); + assertNotNull("moduleFunctionFunctionDeclaration is null", moduleFunctionFunctionDeclaration); + assertNotNull("moduleFunctionProcedureBlock is null", moduleFunctionProcedureBlock); + assertNotNull("moduleFunctionProcedureParams is null", moduleFunctionProcedureParams); + assertNotNull("moduleFunctionProcedureDeclaration is null", moduleFunctionProcedureDeclaration); + + assertNotNull("moduleProcedureBlock is null", moduleProcedureBlock); + assertNotNull("moduleProcedureParamsVariable01 is null", moduleProcedureParamsVariable01); + assertNotNull("moduleProcedureParamsVariable02 is null", moduleProcedureParamsVariable02); + assertNotNull("moduleProcedureParams is null", moduleProcedureParams); + assertNotNull("moduleProcedureDeclaration is null", moduleProcedureDeclaration); + assertNotNull("moduleProcedureVariableDeclaration is null", moduleProcedureVariableDeclaration); + assertNotNull("moduleProcedureFunctionBlock is null", moduleProcedureFunctionBlock); + assertNotNull("moduleProcedureFunctionParams is null", moduleProcedureFunctionParams); + assertNotNull("moduleProcedureFunctionDeclaration is null", moduleProcedureFunctionDeclaration); + assertNotNull("moduleProcedureProcedureBlock is null", moduleProcedureProcedureBlock); + assertNotNull("moduleProcedureProcedureParams is null", moduleProcedureProcedureParams); + assertNotNull("moduleProcedureProcedureDeclaration is null", moduleProcedureProcedureDeclaration); + + assertNotNull("moduleVariableDeclaration is null", moduleVariableDeclaration); + + assertNotNull("moduleLoopCondition is null", moduleLoopCondition); + assertNotNull("moduleLoopBlock is null", moduleLoopBlock); + assertNotNull("moduleLoop is null", moduleLoop); + assertNotNull("moduleLoopContinueStatement is null", moduleLoopContinueStatement); + assertNotNull("moduleLoopBreakStatement is null", moduleLoopBreakStatement); + + assertNotNull("moduleConditionalStatementCondition is null", moduleConditionalStatementCondition); + assertNotNull("moduleConditionalStatement is null", moduleConditionalStatement); + assertNotNull("moduleConditionalStatementThenBlock is null", moduleConditionalStatementThenBlock); + assertNotNull("moduleConditionalStatementElseBlock is null", moduleConditionalStatementElseBlock); + + assertNotNull("moduleReturnStatementParameter is null", moduleReturnStatementParameter); + assertNotNull("moduleReturnStatement is null", moduleReturnStatement); + + assertNotNull("moduleProcedureCallFunctionCallParameter01 is null", moduleProcedureCallFunctionCallParameter01); + assertNotNull("moduleProcedureCallFunctionCallParameter02 is null", moduleProcedureCallFunctionCallParameter02); + assertNotNull("moduleProcedureCallFunctionCallParameters is null", moduleProcedureCallFunctionCallParameters); + assertNotNull("moduleProcedureCall is null", moduleProcedureCall); + + assertNotNull( + "moduleAssignmentMemberAccessVariableDeclaration is null", + moduleAssignmentMemberAccessVariableDeclaration); + assertNotNull( + "moduleAssignmentMemberAccessVariableAccessClass is null", + moduleAssignmentMemberAccessVariableAccessClass); + assertNotNull( + "moduleAssignmentMemberAccessVariableAccessVariable is null", + moduleAssignmentMemberAccessVariableAccessVariable); + assertNotNull("moduleAssignmentMemberAccess is null", moduleAssignmentMemberAccess); + assertNotNull("moduleAssignmentFunctionCallParameter01 is null", moduleAssignmentFunctionCallParameter01); + assertNotNull("moduleAssignmentFunctionCallParameter02 is null", moduleAssignmentFunctionCallParameter02); + assertNotNull("moduleAssignmentFunctionCallParameters is null", moduleAssignmentFunctionCallParameters); + assertNotNull("moduleAssignmentFunctionCall is null", moduleAssignmentFunctionCall); + assertNotNull("moduleAssignment is null", moduleAssignment); + + assertNotNull("invalidModuleImport01 is null", invalidModuleImport01); + assertNotNull("invalidModuleImport02 is null", invalidModuleImport02); + assertNotNull("invalidModuleImports is null", invalidModuleImports); + assertNotNull("invalidModuleBlock is null", invalidModuleBlock); + assertNotNull("invalidModuleDeclaration is null", invalidModuleDeclaration); + + assertNotNull("invalidClassSuperClasses is null", invalidClassSuperClasses); + assertNotNull("invalidClassDeclarations is null", invalidClassBlock); + assertNotNull("invalidClassDeclaration is null", invalidClassDeclaration); + } + + // DECLARATION AND SCOPE + + // ONE CASE TO TEST 'EM ALL + + @Test + public void nodeInteractionTest() { + // Es muss einen Test geben, in dem alle AST-Nodes vorkommen. Nach + // Durchlauf des DeclarationVisitors müssen alle AST-Nodes einen Scope + // haben. Jede AST-Node, die mehr als ein Kind haben kann, muss für + // jeden möglichen Kind-Typ mehr als 1 Kind besitzen. (z.B. Modulblock + // mit 2 Statements und 2 Declarations) + + fillASTModule(); + fillASTExtendedClass(); + fillASTClass(); + fillASTClassVariable(); + fillASTClassFunction(); + fillASTClassProcedure(); + fillASTModuleFunction(); + fillASTModuleFunctionVariable(); + fillASTModuleFunctionFunction(); + fillASTModuleFunctionProcedure(); + fillASTModuleProcedure(); + fillASTModuleProcedureVariable(); + fillASTModuleProcedureFunction(); + fillASTModuleProcedureProcedure(); + fillASTModuleVariable(); + fillASTModuleStatements(); + + setParentVisitor.visit(aPackage); + declarationVisitor.visit(aPackage); + + ASTNode[] allASTNodes = + new ASTNode[] { moduleImport01, moduleImport02, moduleBlock, aPackage, classDeclaration, + classVariableDeclaration, classFunctionBlock, classFunctionDeclaration, classProcedureBlock, + classProcedureDeclaration, extendedClassDeclaration, moduleFunctionBlock, + moduleFunctionParamsVariable01, moduleFunctionParamsVariable02, moduleFunctionDeclaration, + moduleFunctionVariableDeclaration, moduleFunctionFunctionBlock, + moduleFunctionFunctionDeclaration, moduleFunctionProcedureBlock, + moduleFunctionProcedureDeclaration, moduleProcedureBlock, moduleProcedureParamsVariable01, + moduleProcedureParamsVariable02, moduleProcedureDeclaration, + moduleProcedureVariableDeclaration, moduleProcedureFunctionBlock, + moduleProcedureFunctionDeclaration, moduleProcedureProcedureBlock, + moduleProcedureProcedureDeclaration, moduleVariableDeclaration, moduleLoopCondition, + moduleLoopBlock, moduleLoop, moduleLoopContinueStatement, moduleLoopBreakStatement, + moduleConditionalStatementCondition, moduleConditionalStatement, + moduleConditionalStatementThenBlock, moduleConditionalStatementElseBlock, + moduleReturnStatementParameter, moduleReturnStatement, + moduleProcedureCallFunctionCallParameter01, moduleProcedureCallFunctionCallParameter02, + moduleProcedureCall, moduleAssignmentMemberAccessVariableDeclaration, + moduleAssignmentMemberAccessVariableAccessClass, + moduleAssignmentMemberAccessVariableAccessVariable, moduleAssignmentMemberAccess, + moduleAssignmentFunctionCallParameter01, moduleAssignmentFunctionCallParameter02, + moduleAssignmentFunctionCall, moduleAssignment, moduleDeclaration }; + + for (ASTNode node : allASTNodes) { + assertNotNull("Scope not set for class: " + node.getClass().getSimpleName(), node.getScope()); + + if (node instanceof ClassDeclaration) { + assertTrue( + "Scope for ClassDeclaration is no ClassScope: " + node.getClass().getSimpleName(), + node.getScope() instanceof ClassScope); + } + + if (!(node instanceof Package)) { + assertNotNull("Parent not set for class: " + node.getClass().getSimpleName(), node.getParentNode()); + } else { + assertNull( + "Parent set for class (but should be null): " + node.getClass().getSimpleName(), + node.getParentNode()); + } + } + } + + // Module Declaration Tests + + @Test + public void moduleTestModuleDeclaration() { + fillASTModule(); + + // there is no way of validating the correct declaration but to fail + // if an exception occurs. + setParentVisitor.visit(aPackage); + declarationVisitor.visit(aPackage); + } + + @Test(expected = InvalidPlaceToDeclareException.class) + public void moduleTestModuleDeclarationInModule() { + fillASTModule(); + fillASTInvalidModule(); + + moduleBlock.addDeclaration(invalidModuleDeclaration); + setParentVisitor.visit(aPackage); + declarationVisitor.visit(aPackage); + } + + @Test(expected = InvalidPlaceToDeclareException.class) + public void moduleTestModuleDeclarationInClass() { + fillASTModule(); + fillASTClass(); + fillASTInvalidModule(); + + classBlock.addDeclaration(invalidModuleDeclaration); + setParentVisitor.visit(aPackage); + declarationVisitor.visit(aPackage); + } + + @Test(expected = InvalidPlaceToDeclareException.class) + public void moduleTestModuleDeclarationInFunction() { + fillASTModule(); + fillASTModuleFunction(); + fillASTInvalidModule(); + + moduleFunctionBlock.addDeclaration(invalidModuleDeclaration); + setParentVisitor.visit(aPackage); + declarationVisitor.visit(aPackage); + } + + @Test(expected = InvalidPlaceToDeclareException.class) + public void moduleTestModuleDeclarationInProcedure() { + fillASTModule(); + fillASTModuleProcedure(); + fillASTInvalidModule(); + + moduleProcedureBlock.addDeclaration(invalidModuleDeclaration); + setParentVisitor.visit(aPackage); + declarationVisitor.visit(aPackage); + } + + // Class Declaration Tests + + @Test + public void classTestClassDeclarationInModule() { + fillASTModule(); + fillASTClass(); + + setParentVisitor.visit(aPackage); + declarationVisitor.visit(aPackage); + assertSame(classDeclaration, moduleDeclaration.getScope().resolve(new ResolvableIdentifier("classDeclaration"))); + } + + @Test(expected = InvalidPlaceToDeclareException.class) + public void classTestClassDeclarationInClass() { + fillASTModule(); + fillASTClass(); + + classBlock.addDeclaration(invalidClassDeclaration); + setParentVisitor.visit(aPackage); + declarationVisitor.visit(aPackage); + } + + @Test(expected = InvalidPlaceToDeclareException.class) + public void classTestClassDeclarationInFunction() { + fillASTModule(); + fillASTModuleFunction(); + + moduleFunctionBlock.addDeclaration(invalidClassDeclaration); + setParentVisitor.visit(aPackage); + declarationVisitor.visit(aPackage); + } + + @Test(expected = InvalidPlaceToDeclareException.class) + public void classTestClassDeclarationInProcedure() { + fillASTModule(); + fillASTModuleProcedure(); + + moduleProcedureBlock.addDeclaration(invalidClassDeclaration); + setParentVisitor.visit(aPackage); + declarationVisitor.visit(aPackage); + } + + // Function Declaration Tests + + @Test + public void functionTestFunctionDeclarationInModule() { + fillASTModule(); + fillASTModuleFunction(); + + setParentVisitor.visit(aPackage); + declarationVisitor.visit(aPackage); + assertTrue(moduleDeclaration.getScope().resolveProcedure(new ResolvableIdentifier("moduleFunctionDeclaration")).contains( + moduleFunctionDeclaration)); + } + + @Test + public void functionTestFunctionDeclarationInClass() { + fillASTModule(); + fillASTClass(); + fillASTClassFunction(); + + setParentVisitor.visit(aPackage); + declarationVisitor.visit(aPackage); + assertTrue(classDeclaration.getScope().resolveProcedure(new ResolvableIdentifier("classFunctionDeclaration")).contains( + classFunctionDeclaration)); + } + + @Test + public void functionTestFunctionDeclarationInFunction() { + fillASTModule(); + fillASTModuleFunction(); + fillASTModuleFunctionFunction(); + + setParentVisitor.visit(aPackage); + declarationVisitor.visit(aPackage); + assertTrue(moduleFunctionDeclaration.getScope().resolveProcedure( + new ResolvableIdentifier("moduleFunctionFunctionDeclaration")).contains( + moduleFunctionFunctionDeclaration)); + } + + @Test + public void functionTestFunctionDeclarationInProcedure() { + fillASTModule(); + fillASTModuleProcedure(); + fillASTModuleProcedureFunction(); + + setParentVisitor.visit(aPackage); + declarationVisitor.visit(aPackage); + assertTrue(moduleProcedureDeclaration.getScope().resolveProcedure( + new ResolvableIdentifier("moduleProcedureFunctionDeclaration")).contains( + moduleProcedureFunctionDeclaration)); + } + + // Procedure Declaration Tests + + @Test + public void procedureTestProcedureDeclarationInModule() { + fillASTModule(); + fillASTModuleProcedure(); + + setParentVisitor.visit(aPackage); + declarationVisitor.visit(aPackage); + assertTrue(moduleDeclaration.getScope().resolveProcedure(new ResolvableIdentifier("moduleProcedureDeclaration")).contains( + moduleProcedureDeclaration)); + } + + @Test + public void procedureTestProcedureDeclarationInClass() { + fillASTModule(); + fillASTClass(); + fillASTClassProcedure(); + + setParentVisitor.visit(aPackage); + declarationVisitor.visit(aPackage); + assertTrue(classDeclaration.getScope().resolveProcedure(new ResolvableIdentifier("classProcedureDeclaration")).contains( + classProcedureDeclaration)); + } + + @Test + public void procedureTestProcedureDeclarationInFunction() { + fillASTModule(); + fillASTModuleFunction(); + fillASTModuleFunctionProcedure(); + + setParentVisitor.visit(aPackage); + declarationVisitor.visit(aPackage); + assertTrue(moduleFunctionDeclaration.getScope().resolveProcedure( + new ResolvableIdentifier("moduleFunctionProcedureDeclaration")).contains( + moduleFunctionProcedureDeclaration)); + } + + @Test + public void procedureTestProcedureDeclarationInProcedure() { + fillASTModule(); + fillASTModuleProcedure(); + fillASTModuleProcedureProcedure(); + + setParentVisitor.visit(aPackage); + declarationVisitor.visit(aPackage); + assertTrue(moduleProcedureDeclaration.getScope().resolveProcedure( + new ResolvableIdentifier("moduleProcedureProcedureDeclaration")).contains( + moduleProcedureProcedureDeclaration)); + } + + // Variable Declaration Tests + + @Test + public void variableTestVariableDeclarationInModule() { + fillASTModule(); + fillASTModuleVariable(); + + setParentVisitor.visit(aPackage); + declarationVisitor.visit(aPackage); + assertSame( + moduleVariableDeclaration, + moduleDeclaration.getScope().resolve(new ResolvableIdentifier("moduleVariableDeclaration"))); + } + + @Test + public void variableTestVariableDeclarationInClass() { + fillASTModule(); + fillASTClass(); + fillASTClassVariable(); + + setParentVisitor.visit(aPackage); + declarationVisitor.visit(aPackage); + assertSame( + classVariableDeclaration, + classDeclaration.getScope().resolve(new ResolvableIdentifier("classVariableDeclaration"))); + } + + @Test + public void variableTestVariableDeclarationInFunction() { + fillASTModule(); + fillASTModuleFunction(); + fillASTModuleFunctionVariable(); + + setParentVisitor.visit(aPackage); + declarationVisitor.visit(aPackage); + Scope scope = moduleFunctionDeclaration.getScope(); + + assertSame( + moduleFunctionParamsVariable01, + scope.resolve(new ResolvableIdentifier("moduleFunctionParamsVariable01"))); + assertSame( + moduleFunctionParamsVariable02, + scope.resolve(new ResolvableIdentifier("moduleFunctionParamsVariable02"))); + assertSame( + moduleFunctionVariableDeclaration, + scope.resolve(new ResolvableIdentifier("moduleFunctionVariableDeclaration"))); + } + + @Test + public void variableTestVariableDeclarationInProcedure() { + fillASTModule(); + fillASTModuleProcedure(); + fillASTModuleProcedureVariable(); + + setParentVisitor.visit(aPackage); + declarationVisitor.visit(aPackage); + Scope scope = moduleProcedureDeclaration.getScope(); + + assertSame( + moduleProcedureParamsVariable01, + scope.resolve(new ResolvableIdentifier("moduleProcedureParamsVariable01"))); + assertSame( + moduleProcedureParamsVariable02, + scope.resolve(new ResolvableIdentifier("moduleProcedureParamsVariable02"))); + assertSame( + moduleProcedureVariableDeclaration, + scope.resolve(new ResolvableIdentifier("moduleProcedureVariableDeclaration"))); + } + + @Test + public void variableTestResolveVariableInNestedScope() { + fillASTModule(); + fillASTModuleVariable(); + fillASTClass(); + fillASTClassVariable(); + fillASTClassFunction(); + + setParentVisitor.visit(aPackage); + declarationVisitor.visit(aPackage); + Scope scope = classFunctionDeclaration.getScope(); + assertSame(classVariableDeclaration, scope.resolve(new ResolvableIdentifier("classVariableDeclaration"))); + assertSame(moduleVariableDeclaration, scope.resolve(new ResolvableIdentifier("moduleVariableDeclaration"))); + } + + // REDECLARATION + + @Test(expected = RedeclarationException.class) + public void redeclarationTestRedeclarationInSameScopeTest() { + fillASTModule(); + fillASTModuleVariable(); + + VariableDeclaration variableDeclaration = + new VariableDeclaration(buildPosition(), new Identifier("moduleVariableDeclaration"), + new ResolvableIdentifier("String"), VariableDeclaration.DeclarationType.VARIABLE); + moduleBlock.addDeclaration(variableDeclaration); + + setParentVisitor.visit(aPackage); + declarationVisitor.visit(aPackage); + } + + @Test(expected = RedeclarationException.class) + public void redeclarationTestRedeclarationInSameClassScopeTest() { + fillASTModule(); + fillASTClass(); + fillASTClassVariable(); + + VariableDeclaration variableDeclaration = + new VariableDeclaration(buildPosition(), new Identifier("classVariableDeclaration"), + new ResolvableIdentifier("String"), VariableDeclaration.DeclarationType.ATTRIBUTE); + classBlock.addDeclaration(variableDeclaration); + + setParentVisitor.visit(aPackage); + declarationVisitor.visit(aPackage); + } + + @Test + public void redeclarationTestRedeclarationInDifferentScopes() { + fillASTModule(); + fillASTModuleVariable(); + fillASTModuleFunction(); + + VariableDeclaration variableDeclaration = + new VariableDeclaration(buildPosition(), new Identifier("moduleVariableDeclaration"), + new ResolvableIdentifier("String"), VariableDeclaration.DeclarationType.VARIABLE); + moduleFunctionBlock.addDeclaration(variableDeclaration); + + setParentVisitor.visit(aPackage); + declarationVisitor.visit(aPackage); + assertSame( + variableDeclaration, + moduleFunctionDeclaration.getScope().resolve(new ResolvableIdentifier("moduleVariableDeclaration"))); + assertNotSame( + variableDeclaration, + moduleDeclaration.getScope().resolve(new ResolvableIdentifier("moduleVariableDeclaration"))); + } + + @Test + public void redeclarationTestRedeclarationInExtendedClassScope() { + fillASTModule(); + fillASTExtendedClass(); + fillASTClass(); + fillASTClassVariable(); + + VariableDeclaration variableDeclaration = + new VariableDeclaration(buildPosition(), new Identifier("classVariableDeclaration"), + new ResolvableIdentifier("String"), VariableDeclaration.DeclarationType.ATTRIBUTE); + extendedClassBlock.addDeclaration(variableDeclaration); + + setParentVisitor.visit(aPackage); + declarationVisitor.visit(aPackage); + assertSame( + variableDeclaration, + extendedClassDeclaration.getScope().resolve(new ResolvableIdentifier("classVariableDeclaration"))); + assertNotSame( + variableDeclaration, + classDeclaration.getScope().resolve(new ResolvableIdentifier("classVariableDeclaration"))); + } +} diff --git a/src/test/java/de/uni/bremen/monty/moco/ast/TypeCheckTest.java b/src/test/java/de/uni/bremen/monty/moco/ast/TypeCheckTest.java new file mode 100644 index 0000000..7d5e24e --- /dev/null +++ b/src/test/java/de/uni/bremen/monty/moco/ast/TypeCheckTest.java @@ -0,0 +1,1611 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast; + +import de.uni.bremen.monty.moco.ast.declaration.*; +import de.uni.bremen.monty.moco.ast.declaration.VariableDeclaration.DeclarationType; +import de.uni.bremen.monty.moco.ast.expression.*; +import de.uni.bremen.monty.moco.ast.expression.literal.BooleanLiteral; +import de.uni.bremen.monty.moco.ast.expression.literal.FloatLiteral; +import de.uni.bremen.monty.moco.ast.expression.literal.IntegerLiteral; +import de.uni.bremen.monty.moco.ast.expression.literal.StringLiteral; +import de.uni.bremen.monty.moco.ast.statement.*; +import de.uni.bremen.monty.moco.exception.InvalidExpressionException; +import de.uni.bremen.monty.moco.exception.TypeMismatchException; +import de.uni.bremen.monty.moco.exception.UnknownIdentifierException; +import de.uni.bremen.monty.moco.visitor.DeclarationVisitor; +import de.uni.bremen.monty.moco.visitor.ResolveVisitor; +import de.uni.bremen.monty.moco.visitor.SetParentVisitor; +import de.uni.bremen.monty.moco.visitor.TypeCheckVisitor; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static org.junit.Assert.*; + +public class TypeCheckTest { + + private SetParentVisitor SPV; + private DeclarationVisitor DV; + private TypeCheckVisitor TCV; + private ResolveVisitor RV; + + private ModuleDeclaration moduleDeclaration; + private Package aPackage; + private Block moduleBlock; + + private ClassDeclaration object; + private ClassDeclaration classDeclaration; + + private VariableDeclaration intVariable; + private VariableDeclaration floatVariable; + private VariableDeclaration strVariable; + private VariableDeclaration booleanVariable; + + private VariableAccess intVariableAccess; + private VariableAccess floatVariableAccess; + private VariableAccess booleanVariableAccess; + private VariableAccess strVariableAccess; + + private IntegerLiteral intLiteral; + private FloatLiteral floatLiteral; + private StringLiteral strLiteral; + private BooleanLiteral booleanLiteral; + + private FunctionDeclaration functionDeclarationIntReturnInt; + private FunctionDeclaration functionDeclarationStringReturnString; + + private ClassDeclaration classPerson; + private ClassDeclaration classStudent; + + private VariableDeclaration classPersonVarDecl; + private VariableDeclaration classStudentVarDecl; + + private ConditionalExpression ConditionStringString; + private ConditionalExpression ConditionIntString; + private ConditionalExpression ConditionIntInt; + + private int lineCounter = 0; + + private Position buildPosition() { + return new Position("TypeCheckTest", lineCounter++, 0); + } + + // helper + private int counter = 0; + + public Position nextPosition() { + return new Position("TestFile", counter++, 1); + } + + @Rule + public ExpectedException exception = ExpectedException.none(); + + @Before + public void setUpAST() { + // reset counter + counter = 0; + + SPV = new SetParentVisitor(); + SPV.setStopOnFirstError(true); + + DV = new DeclarationVisitor(); + DV.setStopOnFirstError(true); + + RV = new ResolveVisitor(); + RV.setStopOnFirstError(true); + + TCV = new TypeCheckVisitor(); + TCV.setStopOnFirstError(true); + + Block classDeclarationBlock = new Block(buildPosition()); + classDeclaration = + new ClassDeclaration(buildPosition(), new Identifier("classDeclaration"), + new ArrayList(), classDeclarationBlock); + classDeclarationBlock.addDeclaration(new VariableDeclaration(buildPosition(), new Identifier( + "classVariableDeclaration"), new ResolvableIdentifier("String"), + VariableDeclaration.DeclarationType.ATTRIBUTE)); + classDeclarationBlock.addDeclaration(new ProcedureDeclaration(buildPosition(), new Identifier( + "classProcedureDeclaration"), new Block(buildPosition()), new ArrayList())); + + intVariable = + new VariableDeclaration(buildPosition(), new Identifier("intVariable"), + new ResolvableIdentifier("Int"), VariableDeclaration.DeclarationType.VARIABLE); + floatVariable = + new VariableDeclaration(buildPosition(), new Identifier("floatVariable"), new ResolvableIdentifier( + "Float"), VariableDeclaration.DeclarationType.VARIABLE); + booleanVariable = + new VariableDeclaration(buildPosition(), new Identifier("booleanVariable"), new ResolvableIdentifier( + "Bool"), VariableDeclaration.DeclarationType.VARIABLE); + strVariable = + new VariableDeclaration(buildPosition(), new Identifier("strVariable"), new ResolvableIdentifier( + "String"), VariableDeclaration.DeclarationType.VARIABLE); + + intVariableAccess = new VariableAccess(buildPosition(), new ResolvableIdentifier("intVariable")); + floatVariableAccess = new VariableAccess(buildPosition(), new ResolvableIdentifier("floatVariable")); + booleanVariableAccess = new VariableAccess(buildPosition(), new ResolvableIdentifier("booleanVariable")); + strVariableAccess = new VariableAccess(buildPosition(), new ResolvableIdentifier("strVariable")); + + intLiteral = new IntegerLiteral(buildPosition(), 1); + floatLiteral = new FloatLiteral(buildPosition(), 0f); + strLiteral = new StringLiteral(buildPosition(), "42"); + booleanLiteral = new BooleanLiteral(buildPosition(), false); + + // set up test AST + moduleBlock = new Block(new Position("TESTFILE", 2, 10)); + moduleDeclaration = + new ModuleDeclaration(new Position("TESTFILE", 1, 10), new Identifier("Main"), moduleBlock, + new ArrayList()); + aPackage = new Package(new Identifier("")); + aPackage.addModule(moduleDeclaration); + Package corePackage = new Package(new Identifier("core")); + Block block = new Block(new Position()); + for (ClassDeclaration classDeclaration : CoreClasses.getAllCoreClasses()) { + block.addDeclaration(classDeclaration); + } + + corePackage.addModule(new ModuleDeclaration(new Position(), new Identifier("CoreClasses"), block, + Collections. emptyList())); + aPackage.addSubPackage(corePackage); + + // Function Block Declaration + Block functionblock = new Block(buildPosition()); + functionblock.addStatement(new ReturnStatement(buildPosition(), new StringLiteral(buildPosition(), + "StringReturnString Result"))); + ArrayList params = new ArrayList(); + params.add(new VariableDeclaration(buildPosition(), new Identifier("a"), new ResolvableIdentifier("String"), + DeclarationType.PARAMETER)); + functionDeclarationStringReturnString = + new FunctionDeclaration(buildPosition(), new Identifier("StringReturnString"), functionblock, params, + new ResolvableIdentifier("String")); + + Block functionblock2 = new Block(buildPosition()); + functionblock2.addStatement(new ReturnStatement(buildPosition(), new IntegerLiteral(buildPosition(), 1337))); + ArrayList params2 = new ArrayList(); + params2.add(new VariableDeclaration(buildPosition(), new Identifier("a"), new ResolvableIdentifier("Int"), + DeclarationType.PARAMETER)); + functionDeclarationIntReturnInt = + new FunctionDeclaration(buildPosition(), new Identifier("IntReturnInt"), functionblock2, params2, + new ResolvableIdentifier("Int")); + + // Class Declaration Person + Block declList = new Block(buildPosition()); + declList.addDeclaration(new VariableDeclaration(buildPosition(), new Identifier("name"), + new ResolvableIdentifier("String"), DeclarationType.ATTRIBUTE)); + declList.addDeclaration(new VariableDeclaration(buildPosition(), new Identifier("age"), + new ResolvableIdentifier("String"), DeclarationType.ATTRIBUTE)); + classPerson = + new ClassDeclaration(buildPosition(), new Identifier("Person"), new ArrayList(), + declList); + + // Class Declaration Person + Block declList2 = new Block(buildPosition()); + declList2.addDeclaration(new VariableDeclaration(buildPosition(), new Identifier("name"), + new ResolvableIdentifier("String"), DeclarationType.ATTRIBUTE)); + declList2.addDeclaration(new VariableDeclaration(buildPosition(), new Identifier("age"), + new ResolvableIdentifier("String"), DeclarationType.ATTRIBUTE)); + classStudent = + new ClassDeclaration(buildPosition(), new Identifier("Student"), new ArrayList(), + declList2); + + classPersonVarDecl = + new VariableDeclaration(buildPosition(), new Identifier("myPerson"), + new ResolvableIdentifier("Person"), DeclarationType.VARIABLE); + classStudentVarDecl = + new VariableDeclaration(buildPosition(), new Identifier("myStudent"), new ResolvableIdentifier( + "Student"), DeclarationType.VARIABLE); + + ConditionStringString = new ConditionalExpression(buildPosition(), booleanLiteral, strLiteral, strLiteral); + + ConditionIntString = new ConditionalExpression(buildPosition(), booleanLiteral, intLiteral, strLiteral); + + ConditionIntInt = new ConditionalExpression(buildPosition(), booleanLiteral, intLiteral, intLiteral); + + } + + @Test + public void setUpASTTest() { + assertNotNull("SPV is null", SPV); + assertNotNull("DV is null", DV); + assertNotNull("RV is null", RV); + assertNotNull("TCV is null", TCV); + + assertNotNull("package is null", aPackage); + assertNotNull("moduleDeclaration is null", moduleDeclaration); + assertNotNull("moduleBlock is null", moduleBlock); + + assertNotNull("intVariable is null", intVariable); + assertNotNull("floatVariable is null", floatVariable); + assertNotNull("strVariable is null", strVariable); + assertNotNull("booleanVariable is null", booleanVariable); + + assertNotNull("intVariableAccess is null", intVariableAccess); + assertNotNull("floatVariableAccess is null", floatVariableAccess); + assertNotNull("booleanVariableAccess is null", booleanVariableAccess); + assertNotNull("strVariableAccess is null", strVariableAccess); + + assertNotNull("intLiteral is null", intLiteral); + assertNotNull("floatLiteral is null", floatLiteral); + assertNotNull("strLiteral is null", strLiteral); + assertNotNull("booleanLiteral is null", booleanLiteral); + } + + // TYPE COMPATIBILITY + + @Test + public void typeEqualityTest() { + for (TypeDeclaration type1 : CoreClasses.getAllCoreClasses()) { + for (TypeDeclaration type2 : CoreClasses.getAllCoreClasses()) { + if (type2 != CoreClasses.objectType()) { + if (type1 == type2 || type2 == CoreClasses.objectType()) { + assertTrue(String.format( + "%s does not match %s", + type1.getIdentifier().getSymbol(), + type2.getIdentifier().getSymbol()), type1.matchesType(type2)); + } else { + assertFalse(String.format( + "%s does match %s", + type1.getIdentifier().getSymbol(), + type2.getIdentifier().getSymbol()), type1.matchesType(type2)); + } + } + } + } + } + + // LITERAL COMPATIBILITY + + @Test + public void literalCompatibilityTest() { + Assignment intAssignment = new Assignment(buildPosition(), intVariableAccess, intLiteral); + Assignment floatAssignment = new Assignment(buildPosition(), floatVariableAccess, floatLiteral); + Assignment booleanAssignment = new Assignment(buildPosition(), booleanVariableAccess, booleanLiteral); + Assignment strAssignment = new Assignment(buildPosition(), strVariableAccess, strLiteral); + + moduleBlock.addDeclaration(intVariable); + moduleBlock.addDeclaration(floatVariable); + moduleBlock.addDeclaration(booleanVariable); + moduleBlock.addDeclaration(strVariable); + moduleBlock.addStatement(intAssignment); + moduleBlock.addStatement(floatAssignment); + moduleBlock.addStatement(booleanAssignment); + moduleBlock.addStatement(strAssignment); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); // no exception here + } + + // LITERAL INCOMPATIBILITY + + @Test(expected = TypeMismatchException.class) + public void literalIncompatibilityTestIntFloat() { + Assignment intAssignment = new Assignment(buildPosition(), intVariableAccess, floatLiteral); + + moduleBlock.addDeclaration(intVariable); + moduleBlock.addStatement(intAssignment); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); // TypeMismatchException + } + + @Test(expected = TypeMismatchException.class) + public void literalIncompatibilityTestIntBool() { + Assignment intAssignment = new Assignment(buildPosition(), intVariableAccess, booleanLiteral); + + moduleBlock.addDeclaration(intVariable); + moduleBlock.addStatement(intAssignment); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); // TypeMismatchException + } + + @Test(expected = TypeMismatchException.class) + public void literalIncompatibilityTestIntStr() { + Assignment intAssignment = new Assignment(buildPosition(), intVariableAccess, strLiteral); + + moduleBlock.addDeclaration(intVariable); + moduleBlock.addStatement(intAssignment); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); // TypeMismatchException + } + + @Test(expected = TypeMismatchException.class) + public void literalIncompatibilityTestFloatInt() { + Assignment floatAssignment = new Assignment(buildPosition(), floatVariableAccess, intLiteral); + + moduleBlock.addDeclaration(floatVariable); + moduleBlock.addStatement(floatAssignment); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); // TypeMismatchException + } + + @Test(expected = TypeMismatchException.class) + public void literalIncompatibilityTestFloatBool() { + Assignment floatAssignment = new Assignment(buildPosition(), floatVariableAccess, booleanLiteral); + + moduleBlock.addDeclaration(floatVariable); + moduleBlock.addStatement(floatAssignment); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); // TypeMismatchException + } + + @Test(expected = TypeMismatchException.class) + public void literalIncompatibilityTestFloatStr() { + Assignment floatAssignment = new Assignment(buildPosition(), floatVariableAccess, strLiteral); + + moduleBlock.addDeclaration(floatVariable); + moduleBlock.addStatement(floatAssignment); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); // TypeMismatchException + } + + @Test(expected = TypeMismatchException.class) + public void literalIncompatibilityTestBoolInt() { + Assignment booleanAssignment = new Assignment(buildPosition(), booleanVariableAccess, intLiteral); + + moduleBlock.addDeclaration(booleanVariable); + moduleBlock.addStatement(booleanAssignment); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); // TypeMismatchException + } + + @Test(expected = TypeMismatchException.class) + public void literalIncompatibilityTestBoolFloat() { + Assignment booleanAssignment = new Assignment(buildPosition(), booleanVariableAccess, floatLiteral); + + moduleBlock.addDeclaration(booleanVariable); + moduleBlock.addStatement(booleanAssignment); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); // TypeMismatchException + } + + @Test(expected = TypeMismatchException.class) + public void literalIncompatibilityTestBoolStr() { + Assignment booleanAssignment = new Assignment(buildPosition(), booleanVariableAccess, strLiteral); + + moduleBlock.addDeclaration(booleanVariable); + moduleBlock.addStatement(booleanAssignment); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); // TypeMismatchException + } + + @Test(expected = TypeMismatchException.class) + public void literalIncompatibilityTestStrInt() { + Assignment strAssignment = new Assignment(buildPosition(), strVariableAccess, intLiteral); + + moduleBlock.addDeclaration(strVariable); + moduleBlock.addStatement(strAssignment); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); // TypeMismatchException + } + + @Test(expected = TypeMismatchException.class) + public void literalIncompatibilityTestStrFloat() { + Assignment strAssignment = new Assignment(buildPosition(), strVariableAccess, floatLiteral); + + moduleBlock.addDeclaration(strVariable); + moduleBlock.addStatement(strAssignment); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); // TypeMismatchException + } + + @Test(expected = TypeMismatchException.class) + public void literalIncompatibilityTestStrBool() { + Assignment strAssignment = new Assignment(buildPosition(), strVariableAccess, booleanLiteral); + + moduleBlock.addDeclaration(strVariable); + moduleBlock.addStatement(strAssignment); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); // TypeMismatchException + } + + // ASSIGNMENTS + // => Each testcase has to include a well-typed scenario (with a correctly + // typed left and right side), as well as an ill-typed scenario. + + private Object[] makeVarAccessVarAccessAssignment(String LeftResolvableSymbol, String RightResolvableSymbol) { + /* + * Makes a the declarations and VariableAccess objects needed for an variable access = variable access + * AssignmentTest01 and appends it to the Block + */ + VariableDeclaration v1 = + new VariableDeclaration(buildPosition(), new Identifier("var1"), new ResolvableIdentifier( + LeftResolvableSymbol), DeclarationType.VARIABLE); + moduleBlock.addDeclaration(v1); + VariableDeclaration v2 = + new VariableDeclaration(buildPosition(), new Identifier("var2"), new ResolvableIdentifier( + RightResolvableSymbol), DeclarationType.VARIABLE); + moduleBlock.addDeclaration(v2); + VariableAccess val = new VariableAccess(buildPosition(), new ResolvableIdentifier("var1")); + + VariableAccess var = new VariableAccess(buildPosition(), new ResolvableIdentifier("var2")); + + Assignment a = new Assignment(buildPosition(), val, var); + moduleBlock.addStatement(a); + Object[] result = { v1, v2, a }; + return result; + } + + @Test + public void assignmentTest01_1() { + // variable access = variable access + + Object[] generated = makeVarAccessVarAccessAssignment("String", "String"); + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + + Scope bs = moduleBlock.getScope(); + assertNotNull("Scope of module is null, but should be anything else!", moduleDeclaration.getScope()); + assertNotNull("Scope of moduleBlock is null, but should be anything else!", bs); + + assertEquals( + "Declaration doesn't match with the orginal one.", + moduleBlock.getDeclarations().get(0), + (VariableDeclaration) generated[0]); + assertEquals( + "Declaration doesn't match with the orginal one.", + moduleBlock.getDeclarations().get(1), + (VariableDeclaration) generated[1]); + + for (Declaration dc : moduleBlock.getDeclarations()) { + Identifier obj_id = dc.getIdentifier(); + Scope obj_s = dc.getScope(); + assertNotNull("Identifiert shouldn't be null.", obj_id); + assertNotNull("Scope shouldn't be null.", obj_s); + assertEquals("One var declaration is not in the scope of the moduleBlock.", obj_s, bs); + } + + ArrayList statements = (ArrayList) moduleBlock.getStatements(); + + Assignment assignment = null; + if (statements.get(0) instanceof Assignment) { + assignment = (Assignment) statements.get(0); + } else + fail("Statement is not an AssignmentStatement."); + + assertEquals("Statement doesn't match with the orginal one.", statements.get(0), (Assignment) generated[2]); + + if (!(assignment.getLeft() instanceof VariableAccess) && !(assignment.getRight() instanceof VariableAccess)) { + fail("Left or Right of assignment are not from type VariableAccess"); + } + VariableAccess left = (VariableAccess) assignment.getLeft(); + VariableAccess right = (VariableAccess) assignment.getRight(); + + assertEquals("Assignment is not in the moduleBlock scope", assignment.getScope(), bs); + assertNotNull("Type of left Expression is null, but should be string.", left.getType()); + assertNotNull("Type of right Expression is null, but should be string.", right.getType()); + assertEquals("Type of left Expression is not String", left.getType(), CoreClasses.stringType()); + assertEquals("Type of right Expression is not String", right.getType(), CoreClasses.stringType()); + } + + @Test + public void assignmentTest01_2() { + // variable access = variable access + // Ill-Type Test #1 + exception.expect(TypeMismatchException.class); + makeVarAccessVarAccessAssignment("String", "Int"); + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test + public void assignmentTest01_3() { + // variable access = variable access + // Ill-Type Test #2 + exception.expect(TypeMismatchException.class); + makeVarAccessVarAccessAssignment("Float", "String"); + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test + public void assignmentTest01_4() { + // variable access = variable access + // Ill-Type Test #3 + exception.expect(TypeMismatchException.class); + makeVarAccessVarAccessAssignment("Int", "Float"); + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + private void makeVarAccessMemberAccessAssignment(String LeftResolvableSymbol, boolean otherWay) { + /* + * Makes a the declarations and Access objects needed for an variable access = member access AssignmentTest02 + * and appends it to the Blockclass + */ + + // Declaration of a class with a member as attribute. + + moduleBlock.addDeclaration(classPerson); + + // Declaration of a variable + VariableDeclaration v1 = + new VariableDeclaration(buildPosition(), new Identifier("var1"), new ResolvableIdentifier( + LeftResolvableSymbol), DeclarationType.VARIABLE); + moduleBlock.addDeclaration(v1); + + VariableAccess val = new VariableAccess(buildPosition(), new ResolvableIdentifier("var1")); + VariableAccess classvar = new VariableAccess(buildPosition(), new ResolvableIdentifier("Person")); + VariableAccess classaccess = new VariableAccess(buildPosition(), new ResolvableIdentifier("name")); + + MemberAccess mar = new MemberAccess(buildPosition(), classvar, classaccess); + Assignment a; + if (otherWay) + a = new Assignment(buildPosition(), mar, val); + else + a = new Assignment(buildPosition(), val, mar); + moduleBlock.addStatement(a); + } + + @Test + public void assignmentTest02_2() { + // variable access = member access + // Ill-Type Test #1 + exception.expect(TypeMismatchException.class); + makeVarAccessMemberAccessAssignment("Float", false); + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test + public void assignmentTest02_3() { + // variable access = member access + // Ill-Type Test #2 + exception.expect(TypeMismatchException.class); + makeVarAccessMemberAccessAssignment("Int", false); + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test + public void assignmentTest02_4() { + // variable access = member access + // Ill-Type Test #3 + exception.expect(TypeMismatchException.class); + makeVarAccessMemberAccessAssignment("Bool", false); + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + private void variableAccessConditionalExpression_helper(boolean otherway) { + moduleBlock.addDeclaration(strVariable); + Assignment a = + (otherway) ? new Assignment(buildPosition(), strVariableAccess, ConditionStringString) : new Assignment( + buildPosition(), ConditionStringString, strVariableAccess); + moduleBlock.addStatement(a); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + + Statement s = moduleBlock.getStatements().get(0); + + assertEquals( + "Statement doesn't match with the orginal one!", + moduleBlock.getStatements().get(0), + (Assignment) s); + + Scope mbs = moduleBlock.getScope(); + assertEquals( + "ConditionalExpression scope doesn't match with block scope!", + mbs, + ConditionStringString.getScope()); + assertEquals("Assignment scope doesn't match with block scope!", mbs, a.getScope()); + assertEquals("booleanLiteral scope doesn't match with block scope!", mbs, booleanLiteral.getScope()); + assertEquals("strLiteral scope doesn't match with block scope!", mbs, strLiteral.getScope()); + assertEquals("strVariableAccess scope doesn't match with block scope!", mbs, strVariableAccess.getScope()); + assertEquals("strVariable scope doesn't match with block scope!", mbs, strVariable.getScope()); + VariableAccess v = (VariableAccess) a.getLeft(); + assertTrue("VariableAccess Left Expression is not marked as L-Value", v.getLValue()); + assertTrue( + "Type of Left Expression from VariableAccess is not string!", + v.getType() == CoreClasses.stringType()); + + } + + @Test + public void assignmentTest03_1() { + // variable access = conditional expression + variableAccessConditionalExpression_helper(true); + } + + @Test + public void assignmentTest03_2() { + // variable access = conditional expression + // Ill-Type Test #1 + exception.expect(TypeMismatchException.class); + moduleBlock.addDeclaration(strVariable); + Assignment a = new Assignment(buildPosition(), strVariableAccess, ConditionIntInt); + moduleBlock.addStatement(a); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test + public void assignmentTest03_3() { + // variable access = conditional expression + // Ill-Type Test #2 + exception.expect(TypeMismatchException.class); + ConditionalExpression CE = + new ConditionalExpression(buildPosition(), booleanLiteral, floatLiteral, floatLiteral); + moduleBlock.addDeclaration(strVariable); + Assignment a = new Assignment(buildPosition(), strVariableAccess, CE); + moduleBlock.addStatement(a); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test + public void assignmentTest03_4() { + // conditional expression = variable access (is not allowed) + exception.expect(InvalidExpressionException.class); + variableAccessConditionalExpression_helper(false); + } + + private FunctionCall VariableAccessFunctionCallHelper() { + // build function with two parameters ( both int) and return type int: + Block functionblock = new Block(buildPosition()); + functionblock.addStatement(new ReturnStatement(buildPosition(), new IntegerLiteral(buildPosition(), 1337))); + ArrayList params = new ArrayList(); + params.add(new VariableDeclaration(buildPosition(), new Identifier("a"), new ResolvableIdentifier("Int"), + DeclarationType.PARAMETER)); + params.add(new VariableDeclaration(buildPosition(), new Identifier("b"), new ResolvableIdentifier("Int"), + DeclarationType.PARAMETER)); + FunctionDeclaration fd = + new FunctionDeclaration(buildPosition(), new Identifier("testfunction"), functionblock, params, + new ResolvableIdentifier("Int")); + moduleBlock.addDeclaration(fd); + // Make a list with given parameters: + ArrayList values = new ArrayList(); + values.add(intLiteral); + values.add(intLiteral); + return new FunctionCall(buildPosition(), new ResolvableIdentifier("testfunction"), values); + } + + @Test + public void assignmentTest04_1() { + // variable access = function call + moduleBlock.addDeclaration(intVariable); + Assignment a = new Assignment(buildPosition(), intVariableAccess, VariableAccessFunctionCallHelper()); + moduleBlock.addStatement(a); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + + } + + @Test + public void assignmentTest04_2() { + // variable access = function call + // Ill-Type Test #1 (Int return on a string variable) + exception.expect(TypeMismatchException.class); + moduleBlock.addDeclaration(strVariable); + Assignment a = new Assignment(buildPosition(), strVariableAccess, VariableAccessFunctionCallHelper()); + moduleBlock.addStatement(a); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + + } + + @Test + public void assignmentTest04_3() { + // variable access = function call + // (Int return on a float variable) is not allowed + exception.expect(TypeMismatchException.class); + moduleBlock.addDeclaration(floatVariable); + Assignment a = new Assignment(buildPosition(), floatVariableAccess, VariableAccessFunctionCallHelper()); + moduleBlock.addStatement(a); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + + } + + @Test + public void assignmentTest04_4() { + // variable access = function call + // Ill-Type Test #3(Int return on a boolean variable) + exception.expect(TypeMismatchException.class); + moduleBlock.addDeclaration(booleanVariable); + Assignment a = new Assignment(buildPosition(), booleanVariableAccess, VariableAccessFunctionCallHelper()); + moduleBlock.addStatement(a); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + + } + + @Test + public void assignmentTest05_2() { + // member access = variable access + // Ill-Type Test #1 + exception.expect(TypeMismatchException.class); + makeVarAccessMemberAccessAssignment("Float", true); + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test + public void assignmentTest05_3() { + // member access = variable access + // Ill-Type Test #2 + exception.expect(TypeMismatchException.class); + makeVarAccessMemberAccessAssignment("Int", true); + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test + public void assignmentTest05_4() { + // member access = variable access + // Ill-Type Test #3 + exception.expect(TypeMismatchException.class); + makeVarAccessMemberAccessAssignment("Bool", true); + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + private void makeMemberAccessMemberAccessAssignment() { + /* + * Makes a the declarations and Access objects needed for an member access = member access AssignmentTest06 and + * appends it to the Block + */ + + moduleBlock.addDeclaration(classStudent); + moduleBlock.addDeclaration(classPerson); + + // Declaration of variables myPerson and myStudent + moduleBlock.addDeclaration(classPersonVarDecl); + moduleBlock.addDeclaration(classStudentVarDecl); + + // Create VariableAccess objects. + VariableAccess classvar = new VariableAccess(buildPosition(), new ResolvableIdentifier("myPerson")); + VariableAccess classvar2 = new VariableAccess(buildPosition(), new ResolvableIdentifier("myStudent")); + + // Make the Assignment with from two MemberAccesses. + MemberAccess ma1 = + new MemberAccess(buildPosition(), classvar, new VariableAccess(buildPosition(), + new ResolvableIdentifier("name"))); + MemberAccess ma2 = + new MemberAccess(buildPosition(), classvar2, new VariableAccess(buildPosition(), + new ResolvableIdentifier("name"))); + Assignment a = new Assignment(buildPosition(), ma1, ma2); + moduleBlock.addStatement(a); + + } + + @Test + public void assignmentTest06() { + // member access = member access + makeMemberAccessMemberAccessAssignment(); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test + public void assignmentTest07() { + // member access = conditional expression + moduleBlock.addDeclaration(classStudent); + moduleBlock.addDeclaration(classStudentVarDecl); + + VariableAccess classvar = new VariableAccess(buildPosition(), new ResolvableIdentifier("myStudent")); + + MemberAccess ma = + new MemberAccess(buildPosition(), classvar, new VariableAccess(buildPosition(), + new ResolvableIdentifier("name"))); + Assignment a = new Assignment(buildPosition(), ma, ConditionStringString); + moduleBlock.addStatement(a); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + + Scope sc = a.getScope(); + assertNotNull(sc); + assertEquals(sc, moduleBlock.getScope()); + assertTrue(a.getRight() instanceof ConditionalExpression); + assertTrue(a.getLeft() instanceof MemberAccess); + assertTrue(a.getLeft().getType().equals(a.getRight().getType())); + } + + @Test + public void assignmentTest08() { + // member access = function call + + moduleBlock.addDeclaration(classStudent); + moduleBlock.addDeclaration(classStudentVarDecl); + moduleBlock.addDeclaration(functionDeclarationStringReturnString); + + VariableAccess classvar = new VariableAccess(buildPosition(), new ResolvableIdentifier("myStudent")); + + MemberAccess ma = + new MemberAccess(buildPosition(), classvar, new VariableAccess(buildPosition(), + new ResolvableIdentifier("name"))); + + ArrayList values = new ArrayList(); + values.add(strLiteral); + FunctionCall fc = new FunctionCall(buildPosition(), new ResolvableIdentifier("StringReturnString"), values); + + Assignment a = new Assignment(buildPosition(), ma, fc); + moduleBlock.addStatement(a); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + + Scope sc = a.getScope(); + assertNotNull(sc); + assertEquals(sc, moduleBlock.getScope()); + assertTrue(a.getLeft() instanceof MemberAccess); + assertTrue(a.getRight() instanceof FunctionCall); + assertTrue(a.getLeft().getType().equals(a.getRight().getType())); + } + + @Test + public void assignmentTest09() { + // function call = variable access + exception.expect(InvalidExpressionException.class); + moduleBlock.addDeclaration(intVariable); + Assignment a = new Assignment(buildPosition(), VariableAccessFunctionCallHelper(), intVariableAccess); + moduleBlock.addStatement(a); + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + // MEMBER ACCESS + + @Test(expected = UnknownIdentifierException.class) + public void memberAccessTest01() { + // x 1: left ist keine classDeclaration + FunctionDeclaration functionDeclaration = + new FunctionDeclaration(buildPosition(), new Identifier("functionDeclaration"), new Block( + buildPosition()), new ArrayList(), new ResolvableIdentifier("String")); + + VariableAccess varAccess = new VariableAccess(buildPosition(), new ResolvableIdentifier("functionDeclaration")); + + MemberAccess memberAccess = new MemberAccess(buildPosition(), varAccess, intVariableAccess); + + WhileLoop loop = new WhileLoop(buildPosition(), memberAccess, new Block(buildPosition())); + + moduleBlock.addDeclaration(intVariable); + moduleBlock.addDeclaration(functionDeclaration); + moduleBlock.addStatement(loop); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test(expected = TypeMismatchException.class) + public void memberAccessTest02() { + // x 2: left löst nach classDeclaration auf, right ist conditional + ConditionalExpression conditionalExpression = + new ConditionalExpression(buildPosition(), booleanLiteral, strLiteral, strLiteral); + + VariableAccess varAccess = new VariableAccess(buildPosition(), new ResolvableIdentifier("classDeclaration")); + + MemberAccess memberAccess = new MemberAccess(buildPosition(), varAccess, conditionalExpression); + + WhileLoop loop = new WhileLoop(buildPosition(), memberAccess, new Block(buildPosition())); + + moduleBlock.addDeclaration(classDeclaration); + moduleBlock.addStatement(loop); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test(expected = TypeMismatchException.class) + public void memberAccessTest03() { + // x 3: left löst nach classDeclaration auf, right ist boolean + VariableAccess varAccess = new VariableAccess(buildPosition(), new ResolvableIdentifier("classDeclaration")); + + MemberAccess memberAccess = new MemberAccess(buildPosition(), varAccess, booleanLiteral); + + WhileLoop loop = new WhileLoop(buildPosition(), memberAccess, new Block(buildPosition())); + + moduleBlock.addDeclaration(classDeclaration); + moduleBlock.addStatement(loop); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test(expected = TypeMismatchException.class) + public void memberAccessTest04() { + // x 4: left löst nach classDeclaration auf, right ist string + VariableAccess varAccess = new VariableAccess(buildPosition(), new ResolvableIdentifier("classDeclaration")); + + MemberAccess memberAccess = new MemberAccess(buildPosition(), varAccess, strLiteral); + + WhileLoop loop = new WhileLoop(buildPosition(), memberAccess, new Block(buildPosition())); + + moduleBlock.addDeclaration(classDeclaration); + moduleBlock.addStatement(loop); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test(expected = TypeMismatchException.class) + public void memberAccessTest05() { + // x 5: left löst nach classDeclaration auf, right ist float + VariableAccess varAccess = new VariableAccess(buildPosition(), new ResolvableIdentifier("classDeclaration")); + + MemberAccess memberAccess = new MemberAccess(buildPosition(), varAccess, floatLiteral); + + WhileLoop loop = new WhileLoop(buildPosition(), memberAccess, new Block(buildPosition())); + + moduleBlock.addDeclaration(classDeclaration); + moduleBlock.addStatement(loop); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test(expected = TypeMismatchException.class) + public void memberAccessTest06() { + // x 6: left löst nach classDeclaration auf, right ist int + VariableAccess varAccess = new VariableAccess(buildPosition(), new ResolvableIdentifier("classDeclaration")); + + MemberAccess memberAccess = new MemberAccess(buildPosition(), varAccess, intLiteral); + + WhileLoop loop = new WhileLoop(buildPosition(), memberAccess, new Block(buildPosition())); + + moduleBlock.addDeclaration(classDeclaration); + moduleBlock.addStatement(loop); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test(expected = UnknownIdentifierException.class) + public void memberAccessTest07() { + // x 7: left löst nach classDeclaration auf, right ist nicht vorhandener + // ProcedureCall + VariableAccess varAccess = new VariableAccess(buildPosition(), new ResolvableIdentifier("classDeclaration")); + FunctionCall functionCall = + new FunctionCall(buildPosition(), new ResolvableIdentifier("invalid"), new ArrayList()); + + MemberAccess memberAccess = new MemberAccess(buildPosition(), varAccess, functionCall); + + WhileLoop loop = new WhileLoop(buildPosition(), memberAccess, new Block(buildPosition())); + + moduleBlock.addDeclaration(classDeclaration); + moduleBlock.addStatement(loop); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test(expected = UnknownIdentifierException.class) + public void memberAccessTest08() { + // x 8: left löst nach classDeclaration auf, right ist nicht vorhandener + // variableAccess + VariableAccess varAccess = new VariableAccess(buildPosition(), new ResolvableIdentifier("classDeclaration")); + VariableAccess rightVarAccess = new VariableAccess(buildPosition(), new ResolvableIdentifier("invalid")); + + MemberAccess memberAccess = new MemberAccess(buildPosition(), varAccess, rightVarAccess); + + WhileLoop loop = new WhileLoop(buildPosition(), memberAccess, new Block(buildPosition())); + + moduleBlock.addDeclaration(classDeclaration); + moduleBlock.addStatement(loop); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test(expected = TypeMismatchException.class) + public void memberAccessTest09() { + // y 9: left löst nach classDeclaration auf, right ist vorhandener + // ProcedureCall + VariableAccess varAccess = new VariableAccess(buildPosition(), new ResolvableIdentifier("classDeclaration")); + FunctionCall functionCall = + new FunctionCall(buildPosition(), new ResolvableIdentifier("classProcedureDeclaration"), + new ArrayList()); + + MemberAccess memberAccess = new MemberAccess(buildPosition(), varAccess, functionCall); + + WhileLoop loop = new WhileLoop(buildPosition(), memberAccess, new Block(buildPosition())); + + moduleBlock.addDeclaration(classDeclaration); + moduleBlock.addStatement(loop); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test(expected = TypeMismatchException.class) + public void memberAccessTest10() { + // y 10: left löst nach classDeclaration auf, right ist vorhandener + // variableAccess + VariableAccess varAccess = new VariableAccess(buildPosition(), new ResolvableIdentifier("classDeclaration")); + VariableAccess rightVarAccess = + new VariableAccess(buildPosition(), new ResolvableIdentifier("classVariableDeclaration")); + + MemberAccess memberAccess = new MemberAccess(buildPosition(), varAccess, rightVarAccess); + + WhileLoop loop = new WhileLoop(buildPosition(), memberAccess, new Block(buildPosition())); + + moduleBlock.addDeclaration(classDeclaration); + moduleBlock.addStatement(loop); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + // FUNCTION CALL + @Test + public void functionCallTest() { + // FunctionCall with float returnType + Block functionBlock = new Block(nextPosition()); + functionBlock.addStatement(new ReturnStatement(nextPosition(), floatLiteral)); + FunctionDeclaration functionDeclaration = + new FunctionDeclaration(nextPosition(), new Identifier("functionWithReturn"), functionBlock, + new ArrayList(), new ResolvableIdentifier("Float")); + FunctionCall procedureCall = + new FunctionCall(nextPosition(), new ResolvableIdentifier("functionWithReturn"), + new ArrayList()); + + moduleBlock.addDeclaration(functionDeclaration); + moduleBlock.addStatement(procedureCall); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test + public void functionCallWithParamsTest() { + // Functioncall with int Returntype and matching int Paramters + List variables = new ArrayList(); + variables.add(intVariable); + List parameters = new ArrayList(); + parameters.add(intLiteral); + Block functionBlock = new Block(nextPosition()); + functionBlock.addStatement(new ReturnStatement(nextPosition(), intLiteral)); + FunctionDeclaration functionDeclaration = + new FunctionDeclaration(nextPosition(), new Identifier("functionWithParameters"), functionBlock, + variables, new ResolvableIdentifier("Int")); + FunctionCall procedureCall = + new FunctionCall(nextPosition(), new ResolvableIdentifier("functionWithParameters"), parameters); + + moduleBlock.addDeclaration(functionDeclaration); + moduleBlock.addStatement(procedureCall); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test(expected = TypeMismatchException.class) + public void functionCallWithParamsTest02() { + // Parameters from Declaration and Call doesn't match + List variables = new ArrayList(); + variables.add(intVariable); + List parameters = new ArrayList(); + parameters.add(strLiteral); + Block functionBlock = new Block(nextPosition()); + functionBlock.addStatement(new ReturnStatement(nextPosition(), intLiteral)); + + FunctionDeclaration functionDeclaration = + new FunctionDeclaration(nextPosition(), new Identifier("functionWithParameters02"), functionBlock, + variables, new ResolvableIdentifier("Int")); + FunctionCall procedureCall = + new FunctionCall(nextPosition(), new ResolvableIdentifier("functionWithParameters02"), parameters); + + moduleBlock.addDeclaration(functionDeclaration); + moduleBlock.addStatement(procedureCall); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test(expected = TypeMismatchException.class) + public void functionCallWithParamsTest03() { + // Count of paramters in the FunctionCall does not match the declaration + List variables = new ArrayList(); + variables.add(intVariable); + variables.add(floatVariable); + List parameters = new ArrayList(); + parameters.add(intLiteral); + Block functionBlock = new Block(nextPosition()); + functionBlock.addStatement(new ReturnStatement(nextPosition(), intLiteral)); + + FunctionDeclaration functionDeclaration = + new FunctionDeclaration(nextPosition(), new Identifier("functionWithParameters03"), functionBlock, + variables, new ResolvableIdentifier("Int")); + FunctionCall procedureCall = + new FunctionCall(nextPosition(), new ResolvableIdentifier("functionWithParameters03"), parameters); + + moduleBlock.addDeclaration(functionDeclaration); + moduleBlock.addStatement(procedureCall); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test(expected = TypeMismatchException.class) + public void functionCallWithParamsTest04() { + // Count of paramters in the FunctionCall does not match the declaration + List variables = new ArrayList(); + variables.add(floatVariable); + List parameters = new ArrayList(); + parameters.add(floatLiteral); + parameters.add(strLiteral); + Block functionBlock = new Block(nextPosition()); + functionBlock.addStatement(new ReturnStatement(nextPosition(), intLiteral)); + + FunctionDeclaration functionDeclaration = + new FunctionDeclaration(nextPosition(), new Identifier("functionWithParameters04"), functionBlock, + variables, new ResolvableIdentifier("Int")); + FunctionCall procedureCall = + new FunctionCall(nextPosition(), new ResolvableIdentifier("functionWithParameters04"), parameters); + + moduleBlock.addDeclaration(functionDeclaration); + moduleBlock.addStatement(procedureCall); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test(expected = TypeMismatchException.class) + public void functionCallWithParamsTest05() { + // Count of paramters in the FunctionCall does not match the declaration + List variables = new ArrayList(); + List parameters = new ArrayList(); + parameters.add(floatLiteral); + parameters.add(strLiteral); + Block functionBlock = new Block(nextPosition()); + functionBlock.addStatement(new ReturnStatement(nextPosition(), floatLiteral)); + + FunctionDeclaration functionDeclaration = + new FunctionDeclaration(nextPosition(), new Identifier("functionWithParameters05"), functionBlock, + variables, new ResolvableIdentifier("Float")); + FunctionCall procedureCall = + new FunctionCall(nextPosition(), new ResolvableIdentifier("functionWithParameters05"), parameters); + + moduleBlock.addDeclaration(functionDeclaration); + moduleBlock.addStatement(procedureCall); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test(expected = TypeMismatchException.class) + public void functionCallWithParamsTest06() { + // Count of paramters in the FunctionCall does not match the declaration + List variables = new ArrayList(); + List parameters = new ArrayList(); + parameters.add(floatLiteral); + parameters.add(strLiteral); + Block functionBlock = new Block(nextPosition()); + functionBlock.addStatement(new ReturnStatement(nextPosition(), strLiteral)); + + FunctionDeclaration functionDeclaration = + new FunctionDeclaration(nextPosition(), new Identifier("functionWithParameters06"), functionBlock, + variables, new ResolvableIdentifier("String")); + FunctionCall procedureCall = + new FunctionCall(nextPosition(), new ResolvableIdentifier("functionWithParameters06"), parameters); + + moduleBlock.addDeclaration(functionDeclaration); + moduleBlock.addStatement(procedureCall); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test(expected = TypeMismatchException.class) + public void functionCallWithParamsTest07() { + // ReturnStatement type doesn't match Return Type in Declaration + Block functionBlock = new Block(nextPosition()); + functionBlock.addStatement(new ReturnStatement(nextPosition(), strLiteral)); + + FunctionDeclaration functionDeclaration = + new FunctionDeclaration(nextPosition(), new Identifier("functionWithParameters06"), functionBlock, + new ArrayList(), new ResolvableIdentifier("Int")); + FunctionCall procedureCall = + new FunctionCall(nextPosition(), new ResolvableIdentifier("functionWithParameters06"), + new ArrayList()); + + moduleBlock.addDeclaration(functionDeclaration); + moduleBlock.addStatement(procedureCall); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + // PROCEDURE CALL + + @Test + public void procedureCallTest() { + // ProcedureCall with matching Declaration + ProcedureDeclaration procedureDeclaration = + new ProcedureDeclaration(nextPosition(), new Identifier("procedure"), new Block(nextPosition()), + new ArrayList()); + FunctionCall procedureCall = + new FunctionCall(nextPosition(), new ResolvableIdentifier("procedure"), new ArrayList()); + + moduleBlock.addDeclaration(procedureDeclaration); + moduleBlock.addStatement(procedureCall); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test + public void procedureCallWithParamsTest() { + // ProcedureCall and Declaration with matching types + List variables = new ArrayList(); + variables.add(strVariable); + List parameters = new ArrayList(); + parameters.add(strLiteral); + + ProcedureDeclaration procedureDeclaration = + new ProcedureDeclaration(nextPosition(), new Identifier("procedureWithParams"), new Block( + nextPosition()), variables); + FunctionCall procedureCall = + new FunctionCall(nextPosition(), new ResolvableIdentifier("procedureWithParams"), parameters); + + moduleBlock.addDeclaration(procedureDeclaration); + moduleBlock.addStatement(procedureCall); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test(expected = TypeMismatchException.class) + public void procedureCallWithParamsTest02() { + // Parameters from Declaration and Call doesn't match + List variables = new ArrayList(); + variables.add(strVariable); + List parameters = new ArrayList(); + parameters.add(floatLiteral); + + ProcedureDeclaration procedureDeclaration = + new ProcedureDeclaration(nextPosition(), new Identifier("procedureWithParams02"), new Block( + nextPosition()), variables); + FunctionCall procedureCall = + new FunctionCall(nextPosition(), new ResolvableIdentifier("procedureWithParams02"), parameters); + + moduleBlock.addDeclaration(procedureDeclaration); + moduleBlock.addStatement(procedureCall); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test(expected = TypeMismatchException.class) + public void procedureCallWithParamsTest03() { + // Count of paramters in the ProcedureCall does not match the + // declaration + List variables = new ArrayList(); + variables.add(strVariable); + variables.add(intVariable); + List parameters = new ArrayList(); + parameters.add(strLiteral); + + ProcedureDeclaration procedureDeclaration = + new ProcedureDeclaration(nextPosition(), new Identifier("procedureWithParams03"), new Block( + nextPosition()), variables); + FunctionCall procedureCall = + new FunctionCall(nextPosition(), new ResolvableIdentifier("procedureWithParams03"), parameters); + + moduleBlock.addDeclaration(procedureDeclaration); + moduleBlock.addStatement(procedureCall); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test(expected = TypeMismatchException.class) + public void procedureCallWithParamsTest04() { + // Count of paramters in the ProcedureCall does not match the + // declaration + List variables = new ArrayList(); + variables.add(strVariable); + List parameters = new ArrayList(); + parameters.add(strLiteral); + parameters.add(intLiteral); + + ProcedureDeclaration procedureDeclaration = + new ProcedureDeclaration(nextPosition(), new Identifier("procedureWithParams04"), new Block( + nextPosition()), variables); + FunctionCall procedureCall = + new FunctionCall(nextPosition(), new ResolvableIdentifier("procedureWithParams04"), parameters); + + moduleBlock.addDeclaration(procedureDeclaration); + moduleBlock.addStatement(procedureCall); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test(expected = TypeMismatchException.class) + public void procedureCallWithParamsTest05() { + // Count of paramters in the ProcedureCall does not match the + // declaration + List variables = new ArrayList(); + variables.add(strVariable); + List parameters = new ArrayList(); + + ProcedureDeclaration procedureDeclaration = + new ProcedureDeclaration(nextPosition(), new Identifier("procedureWithParams05"), new Block( + nextPosition()), variables); + FunctionCall procedureCall = + new FunctionCall(nextPosition(), new ResolvableIdentifier("procedureWithParams05"), parameters); + + moduleBlock.addDeclaration(procedureDeclaration); + moduleBlock.addStatement(procedureCall); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test(expected = TypeMismatchException.class) + public void procedureCallWithParamsTest06() { + // Count of paramters in the ProcedureCall does not match the + // declaration + List variables = new ArrayList(); + List parameters = new ArrayList(); + parameters.add(intLiteral); + + ProcedureDeclaration procedureDeclaration = + new ProcedureDeclaration(nextPosition(), new Identifier("procedureWithParams06"), new Block( + nextPosition()), variables); + FunctionCall procedureCall = + new FunctionCall(nextPosition(), new ResolvableIdentifier("procedureWithParams06"), parameters); + + moduleBlock.addDeclaration(procedureDeclaration); + moduleBlock.addStatement(procedureCall); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + // CONDITIONAL STATEMENT + @Test + public void conditionalTestBooleanCondition() { + ConditionalStatement conditionalStatement = + new ConditionalStatement(buildPosition(), booleanLiteral, new Block(buildPosition()), new Block( + buildPosition())); + + moduleBlock.addStatement(conditionalStatement); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test(expected = TypeMismatchException.class) + public void conditionalTestNotBooleanCondition() { + ConditionalStatement conditionalStatement = + new ConditionalStatement(buildPosition(), strLiteral, new Block(buildPosition()), new Block( + buildPosition())); + + moduleBlock.addStatement(conditionalStatement); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + // CONDITIONAL EXPRESSION + + @Test + public void conditionalExpressionTestCorrectConditionalExpression() { + // thenExpression matches elseExpression + ConditionalExpression conditionalExpression = + new ConditionalExpression(buildPosition(), booleanLiteral, strLiteral, strLiteral); + Assignment conditionalAssignment = new Assignment(buildPosition(), strVariableAccess, conditionalExpression); + + moduleBlock.addDeclaration(strVariable); + moduleBlock.addStatement(conditionalAssignment); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test(expected = TypeMismatchException.class) + public void conditionalExpressionTestNotBooleanCondition() { + ConditionalExpression conditionalExpression = + new ConditionalExpression(buildPosition(), intLiteral, strLiteral, strLiteral); + Assignment conditionalAssignment = new Assignment(buildPosition(), strVariableAccess, conditionalExpression); + + moduleBlock.addDeclaration(strVariable); + moduleBlock.addStatement(conditionalAssignment); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } + + @Test(expected = TypeMismatchException.class) + public void conditionalExpressionTestThenElseMismatches() { + // thenExpression mismatches elseExpression + ConditionalExpression conditionalExpression = + new ConditionalExpression(buildPosition(), booleanLiteral, strLiteral, intLiteral); + Assignment conditionalAssignment = new Assignment(buildPosition(), strVariableAccess, conditionalExpression); + + moduleBlock.addDeclaration(strVariable); + moduleBlock.addStatement(conditionalAssignment); + + SPV.visit(aPackage); + DV.visit(aPackage); + RV.visit(aPackage); + TCV.visit(aPackage); + } +} diff --git a/src/test/java/de/uni/bremen/monty/moco/codegeneration/ContextTest.java b/src/test/java/de/uni/bremen/monty/moco/codegeneration/ContextTest.java new file mode 100644 index 0000000..ca91350 --- /dev/null +++ b/src/test/java/de/uni/bremen/monty/moco/codegeneration/ContextTest.java @@ -0,0 +1,113 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.codegeneration; + +import de.uni.bremen.monty.moco.codegeneration.context.CommentAppender; +import de.uni.bremen.monty.moco.codegeneration.context.Context; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.startsWith; +import static org.mockito.AdditionalAnswers.returnsFirstArg; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class ContextTest { + + @Mock + CommentAppender commentAppender; + + @Before + public void setUp() throws Exception { + when(commentAppender.addComment(anyString())).then(returnsFirstArg()); + } + + @Test + public void shouldContainSimpleString() throws Exception { + String testString = "print xxx"; + + Context context = new Context(commentAppender); + context.append(testString); + + assertThat(context.getData(), startsWith(testString)); + } + + @Test + public void shouldContainAnotherContext() throws Exception { + String testString = "call xxx"; + + Context context1 = new Context(commentAppender); + Context context2 = new Context(commentAppender); + context1.append(context2); + context2.append(testString); + + assertThat(context1.getData(), startsWith(testString)); + } + + @Test + public void shouldContainMultpleChildren() throws Exception { + + Context context1 = new Context(commentAppender); + Context context2 = new Context(commentAppender); + Context context3 = new Context(commentAppender); + Context context4 = new Context(commentAppender); + Context context5 = new Context(commentAppender); + + context1.append(context2); + context1.append(context3); + context1.append("World"); + context1.append(context5); + context3.append(context4); + + context2.append("!"); + context4.append("Hello "); + context3.append("pretty "); + + context5.append("!"); + + assertThat(context1.getData(), is("!\nHello \npretty \nWorld\n!\n")); + } + +} diff --git a/src/test/java/de/uni/bremen/monty/moco/util/MultiOutputStream.java b/src/test/java/de/uni/bremen/monty/moco/util/MultiOutputStream.java new file mode 100644 index 0000000..8f4f20f --- /dev/null +++ b/src/test/java/de/uni/bremen/monty/moco/util/MultiOutputStream.java @@ -0,0 +1,57 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.util; + +import java.io.IOException; +import java.io.OutputStream; + +public class MultiOutputStream extends OutputStream { + private OutputStream[] streams; + + public MultiOutputStream(OutputStream... streams) { + this.streams = streams; + } + + @Override + public void write(int b) throws IOException { + for (OutputStream stream : streams) { + stream.write(b); + } + } +} diff --git a/src/test/resources/testAstBuilder/declarationType.monty b/src/test/resources/testAstBuilder/declarationType.monty new file mode 100644 index 0000000..dbb7d14 --- /dev/null +++ b/src/test/resources/testAstBuilder/declarationType.monty @@ -0,0 +1,19 @@ +class Ab: + + String x + + + Float y := 2.4 + + + proc1(Int t): + pass + + + String func1(Bool b): + pass + +Float f +String s := "" + +Int func2(Bool b): + pass + +proc2(Int t): + pass \ No newline at end of file diff --git a/src/test/resources/testAstBuilder/ifElse.monty b/src/test/resources/testAstBuilder/ifElse.monty new file mode 100644 index 0000000..9752784 --- /dev/null +++ b/src/test/resources/testAstBuilder/ifElse.monty @@ -0,0 +1,30 @@ +if a: + p(1) + +if a: + p(1) +else: + p(2) + +if a: + p(1) +elif b: + p(2) +else: + p(3) + +if a: + p(1) +elif b: + p(2) +elif c: + p(3) +else: + p(4) + +if a: + p(1) +elif b: + p(2) +elif c: + p(3) \ No newline at end of file diff --git a/src/test/resources/testAstBuilder/varDecl.monty b/src/test/resources/testAstBuilder/varDecl.monty new file mode 100644 index 0000000..516f262 --- /dev/null +++ b/src/test/resources/testAstBuilder/varDecl.monty @@ -0,0 +1 @@ +String s := "Hallo" \ No newline at end of file diff --git a/src/test/resources/testModuleProgramms/de/dafuq/monty/HelloSayer.monty b/src/test/resources/testModuleProgramms/de/dafuq/monty/HelloSayer.monty new file mode 100644 index 0000000..377820a --- /dev/null +++ b/src/test/resources/testModuleProgramms/de/dafuq/monty/HelloSayer.monty @@ -0,0 +1,11 @@ +// Testing: Functioncall from different Module +// +// The function sayHello is called in Main.monty and it calls +// the function montySays() of module Main.monty +// +// Expected result: see Main.monty + +String sayHello(): + return "Hello" + +print(montySays("says: ")) \ No newline at end of file diff --git a/src/test/resources/testModuleProgramms/de/dafuq/monty/Main.monty b/src/test/resources/testModuleProgramms/de/dafuq/monty/Main.monty new file mode 100644 index 0000000..d912540 --- /dev/null +++ b/src/test/resources/testModuleProgramms/de/dafuq/monty/Main.monty @@ -0,0 +1,13 @@ +// Testing: Functioncall from different Module +// +// The print function calls the function sayHello() in the module +// HelloSayer.monty +// +// Expected result: Monty says: Hello +String montySays(String s): + print("Monty ") + return s + +print(sayHello()) + + diff --git a/src/test/resources/testModuleProgramms/de/dafuq/monty/Main.output b/src/test/resources/testModuleProgramms/de/dafuq/monty/Main.output new file mode 100644 index 0000000..465fed5 --- /dev/null +++ b/src/test/resources/testModuleProgramms/de/dafuq/monty/Main.output @@ -0,0 +1 @@ +Monty says: Hello \ No newline at end of file diff --git a/src/test/resources/testPrograms/CorePackage.monty b/src/test/resources/testPrograms/CorePackage.monty new file mode 100644 index 0000000..adbf383 --- /dev/null +++ b/src/test/resources/testPrograms/CorePackage.monty @@ -0,0 +1,5 @@ +// Testing: Operater Precedence +// +// Expected Output: 2 + +print(1+2*3/4) \ No newline at end of file diff --git a/src/test/resources/testPrograms/CorePackage.output b/src/test/resources/testPrograms/CorePackage.output new file mode 100644 index 0000000..d8263ee --- /dev/null +++ b/src/test/resources/testPrograms/CorePackage.output @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/src/test/resources/testPrograms/array/ArrayEmptyInit.monty.ignore b/src/test/resources/testPrograms/array/ArrayEmptyInit.monty.ignore new file mode 100644 index 0000000..d072792 --- /dev/null +++ b/src/test/resources/testPrograms/array/ArrayEmptyInit.monty.ignore @@ -0,0 +1,7 @@ +// Testing: Arrays +// +// An emtpy array must be initializable. +// +// Expected output: + +Array a := [] diff --git a/src/test/resources/testPrograms/array/ArrayEmptyInit.output b/src/test/resources/testPrograms/array/ArrayEmptyInit.output new file mode 100644 index 0000000..e69de29 diff --git a/src/test/resources/testPrograms/array/ArrayEmptyRead.error b/src/test/resources/testPrograms/array/ArrayEmptyRead.error new file mode 100644 index 0000000..e69de29 diff --git a/src/test/resources/testPrograms/array/ArrayEmptyRead.monty.ignore b/src/test/resources/testPrograms/array/ArrayEmptyRead.monty.ignore new file mode 100644 index 0000000..5d4ba1e --- /dev/null +++ b/src/test/resources/testPrograms/array/ArrayEmptyRead.monty.ignore @@ -0,0 +1,8 @@ +// Testing: Arrays +// +// A read of an empty array must yield an error. +// +// Expected error + +Array a := [] +print(a[0]) diff --git a/src/test/resources/testPrograms/array/ArrayEmptyWrite.error b/src/test/resources/testPrograms/array/ArrayEmptyWrite.error new file mode 100644 index 0000000..e69de29 diff --git a/src/test/resources/testPrograms/array/ArrayEmptyWrite.monty.ignore b/src/test/resources/testPrograms/array/ArrayEmptyWrite.monty.ignore new file mode 100644 index 0000000..fb39fec --- /dev/null +++ b/src/test/resources/testPrograms/array/ArrayEmptyWrite.monty.ignore @@ -0,0 +1,8 @@ +// Testing: Arrays +// +// A write into an empty array must yield an error. +// +// Expected error + +Array a := [] +a[0] := 0 diff --git a/src/test/resources/testPrograms/array/ArrayMany.monty.ignore b/src/test/resources/testPrograms/array/ArrayMany.monty.ignore new file mode 100644 index 0000000..7e38839 --- /dev/null +++ b/src/test/resources/testPrograms/array/ArrayMany.monty.ignore @@ -0,0 +1,25 @@ +// Testing: Arrays +// +// Read/Write with an array of some big size must work. +// +// Expected output: 101112131415202122232425 + +Array a := [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] +print(a[10]) +print(a[11]) +print(a[12]) +print(a[13]) +print(a[14]) +print(a[15]) +a[10] := 20 +a[11] := 21 +a[12] := 22 +a[13] := 23 +a[14] := 24 +a[15] := 25 +print(a[10]) +print(a[11]) +print(a[12]) +print(a[13]) +print(a[14]) +print(a[15]) diff --git a/src/test/resources/testPrograms/array/ArrayMany.output b/src/test/resources/testPrograms/array/ArrayMany.output new file mode 100644 index 0000000..b1634b2 --- /dev/null +++ b/src/test/resources/testPrograms/array/ArrayMany.output @@ -0,0 +1 @@ +101112131415202122232425 \ No newline at end of file diff --git a/src/test/resources/testPrograms/array/ArrayOne.monty.ignore b/src/test/resources/testPrograms/array/ArrayOne.monty.ignore new file mode 100644 index 0000000..28bf70a --- /dev/null +++ b/src/test/resources/testPrograms/array/ArrayOne.monty.ignore @@ -0,0 +1,10 @@ +// Testing: Arrays +// +// Read/Write with an array of size 1 must work. +// +// Expected output: 010 + +Array a := [0] +print(a[0]) +a[0] := 10 +print(a[0]) diff --git a/src/test/resources/testPrograms/array/ArrayOne.output b/src/test/resources/testPrograms/array/ArrayOne.output new file mode 100644 index 0000000..fc06c8b --- /dev/null +++ b/src/test/resources/testPrograms/array/ArrayOne.output @@ -0,0 +1 @@ +010 \ No newline at end of file diff --git a/src/test/resources/testPrograms/array/ArrayOutOfBounds1.error b/src/test/resources/testPrograms/array/ArrayOutOfBounds1.error new file mode 100644 index 0000000..e69de29 diff --git a/src/test/resources/testPrograms/array/ArrayOutOfBounds1.monty.ignore b/src/test/resources/testPrograms/array/ArrayOutOfBounds1.monty.ignore new file mode 100644 index 0000000..3b4e8e6 --- /dev/null +++ b/src/test/resources/testPrograms/array/ArrayOutOfBounds1.monty.ignore @@ -0,0 +1,8 @@ +// Testing: Arrays +// +// A write into an empty array must yield an error. +// +// Expected error + +Array a := [0, 1] +print(a[-1]) diff --git a/src/test/resources/testPrograms/array/ArrayOutOfBounds2.error b/src/test/resources/testPrograms/array/ArrayOutOfBounds2.error new file mode 100644 index 0000000..e69de29 diff --git a/src/test/resources/testPrograms/array/ArrayOutOfBounds2.monty.ignore b/src/test/resources/testPrograms/array/ArrayOutOfBounds2.monty.ignore new file mode 100644 index 0000000..6743263 --- /dev/null +++ b/src/test/resources/testPrograms/array/ArrayOutOfBounds2.monty.ignore @@ -0,0 +1,8 @@ +// Testing: Arrays +// +// A write out of bounds must yield an error. +// +// Expected error + +Array a := [0, 1] +a[-1] := 42 diff --git a/src/test/resources/testPrograms/array/ArrayOutOfBounds3.error b/src/test/resources/testPrograms/array/ArrayOutOfBounds3.error new file mode 100644 index 0000000..e69de29 diff --git a/src/test/resources/testPrograms/array/ArrayOutOfBounds3.monty.ignore b/src/test/resources/testPrograms/array/ArrayOutOfBounds3.monty.ignore new file mode 100644 index 0000000..f8c5bcb --- /dev/null +++ b/src/test/resources/testPrograms/array/ArrayOutOfBounds3.monty.ignore @@ -0,0 +1,8 @@ +// Testing: Arrays +// +// A read out of bounds must yield an error. +// +// Expected error + +Array a := [0, 1] +print(a[42]) diff --git a/src/test/resources/testPrograms/array/ArrayOutOfBounds4.error b/src/test/resources/testPrograms/array/ArrayOutOfBounds4.error new file mode 100644 index 0000000..e69de29 diff --git a/src/test/resources/testPrograms/array/ArrayOutOfBounds4.monty.ignore b/src/test/resources/testPrograms/array/ArrayOutOfBounds4.monty.ignore new file mode 100644 index 0000000..4b533b9 --- /dev/null +++ b/src/test/resources/testPrograms/array/ArrayOutOfBounds4.monty.ignore @@ -0,0 +1,8 @@ +// Testing: Arrays +// +// A write out of bounds must yield an error. +// +// Expected error + +Array a := [0, 1] +a[42] := 42 diff --git a/src/test/resources/testPrograms/array/ArrayTwo.monty.ignore b/src/test/resources/testPrograms/array/ArrayTwo.monty.ignore new file mode 100644 index 0000000..c0bc1a1 --- /dev/null +++ b/src/test/resources/testPrograms/array/ArrayTwo.monty.ignore @@ -0,0 +1,13 @@ +// Testing: Arrays +// +// Read/Write with an array of size 2 must work. +// +// Expected output: 011011 + +Array a := [0, 1] +print(a[0]) +print(a[1]) +a[0] := 10 +a[1] := 11 +print(a[0]) +print(a[1]) diff --git a/src/test/resources/testPrograms/array/ArrayTwo.output b/src/test/resources/testPrograms/array/ArrayTwo.output new file mode 100644 index 0000000..0969ac7 --- /dev/null +++ b/src/test/resources/testPrograms/array/ArrayTwo.output @@ -0,0 +1 @@ +011011 \ No newline at end of file diff --git a/src/test/resources/testPrograms/callable/Function.monty b/src/test/resources/testPrograms/callable/Function.monty new file mode 100644 index 0000000..1d8997f --- /dev/null +++ b/src/test/resources/testPrograms/callable/Function.monty @@ -0,0 +1,11 @@ +// Testing: FunctionDeclaration and FunctionCall +// +// The function must be called correctly and return the evaluated return +// expression. +// +// Expected output: 4 + +Int square(Int value): + return value * value + +print(square(2)) diff --git a/src/test/resources/testPrograms/callable/Function.output b/src/test/resources/testPrograms/callable/Function.output new file mode 100644 index 0000000..bf0d87a --- /dev/null +++ b/src/test/resources/testPrograms/callable/Function.output @@ -0,0 +1 @@ +4 \ No newline at end of file diff --git a/src/test/resources/testPrograms/callable/Function1.monty b/src/test/resources/testPrograms/callable/Function1.monty new file mode 100644 index 0000000..1d8997f --- /dev/null +++ b/src/test/resources/testPrograms/callable/Function1.monty @@ -0,0 +1,11 @@ +// Testing: FunctionDeclaration and FunctionCall +// +// The function must be called correctly and return the evaluated return +// expression. +// +// Expected output: 4 + +Int square(Int value): + return value * value + +print(square(2)) diff --git a/src/test/resources/testPrograms/callable/Function1.output b/src/test/resources/testPrograms/callable/Function1.output new file mode 100644 index 0000000..bf0d87a --- /dev/null +++ b/src/test/resources/testPrograms/callable/Function1.output @@ -0,0 +1 @@ +4 \ No newline at end of file diff --git a/src/test/resources/testPrograms/callable/Function2.monty b/src/test/resources/testPrograms/callable/Function2.monty new file mode 100644 index 0000000..2198971 --- /dev/null +++ b/src/test/resources/testPrograms/callable/Function2.monty @@ -0,0 +1,21 @@ +// Testing: Nested FunctionDeclaration, FunctionCall, multiplication +// +// The function must be called correctly and return the evaluated return +// expression. +// +// Expected output: 16 + +Int calc(Int value1, Int value2): + + Int identity(Int x): + return x + + Int two(): + return 2 + + Int square(Int x): + return 2 * x + + return identity(value1) * two() * square(value2) + +print(calc(2,2)) \ No newline at end of file diff --git a/src/test/resources/testPrograms/callable/Function2.output b/src/test/resources/testPrograms/callable/Function2.output new file mode 100644 index 0000000..19c7bdb --- /dev/null +++ b/src/test/resources/testPrograms/callable/Function2.output @@ -0,0 +1 @@ +16 \ No newline at end of file diff --git a/src/test/resources/testPrograms/callable/Function3.monty b/src/test/resources/testPrograms/callable/Function3.monty new file mode 100644 index 0000000..20d3003 --- /dev/null +++ b/src/test/resources/testPrograms/callable/Function3.monty @@ -0,0 +1,20 @@ +// Testing: Nested FunctionDeclaration, FunctionCall, multiplication, addition +// +// The function must be called correctly and return the evaluated return +// expression. +// +// Expected output: 16 + +Int calc(Int value1, Int value2): + + Int identity(Int x): + return x + + Int two(): + return 2 + + Int square(Int x): + return 2 * x + return identity(value1) + two() + square(value2) + 8 + +print(calc(2,2)) \ No newline at end of file diff --git a/src/test/resources/testPrograms/callable/Function3.output b/src/test/resources/testPrograms/callable/Function3.output new file mode 100644 index 0000000..19c7bdb --- /dev/null +++ b/src/test/resources/testPrograms/callable/Function3.output @@ -0,0 +1 @@ +16 \ No newline at end of file diff --git a/src/test/resources/testPrograms/callable/Function4.monty b/src/test/resources/testPrograms/callable/Function4.monty new file mode 100644 index 0000000..9b2cf7e --- /dev/null +++ b/src/test/resources/testPrograms/callable/Function4.monty @@ -0,0 +1,19 @@ +// Testing: Nested FunctionDeclaration, FunctionCall, ConditionalStatement +// +// The function must be called correctly and return the evaluated return +// expression. +// +// Expected output: 42 + +Int identity(Int x): + return x + +Int square(Int x): + if x < 3: + return identity(4) + else: + return identity(2) + return 9000 // this is needed at the moment, should be fixed + +print(square(2)) +print(square(100)) \ No newline at end of file diff --git a/src/test/resources/testPrograms/callable/Function4.output b/src/test/resources/testPrograms/callable/Function4.output new file mode 100644 index 0000000..f70d7bb --- /dev/null +++ b/src/test/resources/testPrograms/callable/Function4.output @@ -0,0 +1 @@ +42 \ No newline at end of file diff --git a/src/test/resources/testPrograms/callable/FunctionGlobalLocalBoolean.monty b/src/test/resources/testPrograms/callable/FunctionGlobalLocalBoolean.monty new file mode 100644 index 0000000..77183b3 --- /dev/null +++ b/src/test/resources/testPrograms/callable/FunctionGlobalLocalBoolean.monty @@ -0,0 +1,12 @@ +// Testing: VariableDeclaration, VariableAccess, FunctionCall +// +// A global boolean variable as parameter and local copy as return value. +// +// Expected output: 1 + +Bool function(Bool var): + Bool copy := var + return copy + +Bool var := true +print(function(var)) diff --git a/src/test/resources/testPrograms/callable/FunctionGlobalLocalBoolean.output b/src/test/resources/testPrograms/callable/FunctionGlobalLocalBoolean.output new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/src/test/resources/testPrograms/callable/FunctionGlobalLocalBoolean.output @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/src/test/resources/testPrograms/callable/FunctionGlobalLocalFloat.monty b/src/test/resources/testPrograms/callable/FunctionGlobalLocalFloat.monty new file mode 100644 index 0000000..80a19a0 --- /dev/null +++ b/src/test/resources/testPrograms/callable/FunctionGlobalLocalFloat.monty @@ -0,0 +1,12 @@ +// Testing: VariableDeclaration, VariableAccess, FunctionCall +// +// A global float variable as parameter and local copy as return value. +// +// Expected output: 1.3 + +Float function(Float var): + Float copy := var + return copy + +Float var := 1.3 +print(function(var)) diff --git a/src/test/resources/testPrograms/callable/FunctionGlobalLocalFloat.output b/src/test/resources/testPrograms/callable/FunctionGlobalLocalFloat.output new file mode 100644 index 0000000..a58941b --- /dev/null +++ b/src/test/resources/testPrograms/callable/FunctionGlobalLocalFloat.output @@ -0,0 +1 @@ +1.3 \ No newline at end of file diff --git a/src/test/resources/testPrograms/callable/FunctionGlobalLocalInt.monty b/src/test/resources/testPrograms/callable/FunctionGlobalLocalInt.monty new file mode 100644 index 0000000..1145ce4 --- /dev/null +++ b/src/test/resources/testPrograms/callable/FunctionGlobalLocalInt.monty @@ -0,0 +1,12 @@ +// Testing: VariableDeclaration, VariableAccess, FunctionCall +// +// A global int variable as parameter and local copy as return value. +// +// Expected output: 42 + +Int function(Int var): + Int copy := var + return copy + +Int var := 42 +print(function(var)) diff --git a/src/test/resources/testPrograms/callable/FunctionGlobalLocalInt.output b/src/test/resources/testPrograms/callable/FunctionGlobalLocalInt.output new file mode 100644 index 0000000..f70d7bb --- /dev/null +++ b/src/test/resources/testPrograms/callable/FunctionGlobalLocalInt.output @@ -0,0 +1 @@ +42 \ No newline at end of file diff --git a/src/test/resources/testPrograms/callable/FunctionGlobalLocalString.monty b/src/test/resources/testPrograms/callable/FunctionGlobalLocalString.monty new file mode 100644 index 0000000..076b37d --- /dev/null +++ b/src/test/resources/testPrograms/callable/FunctionGlobalLocalString.monty @@ -0,0 +1,12 @@ +// Testing: VariableDeclaration, VariableAccess, FunctionCall +// +// A global string variable as parameter and local copy as return value. +// +// Expected output: Hallo + +String function(String var): + String copy := var + return copy + +String var := "Hallo" +print(function(var)) diff --git a/src/test/resources/testPrograms/callable/FunctionGlobalLocalString.output b/src/test/resources/testPrograms/callable/FunctionGlobalLocalString.output new file mode 100644 index 0000000..53f5007 --- /dev/null +++ b/src/test/resources/testPrograms/callable/FunctionGlobalLocalString.output @@ -0,0 +1 @@ +Hallo \ No newline at end of file diff --git a/src/test/resources/testPrograms/callable/Procedure.monty b/src/test/resources/testPrograms/callable/Procedure.monty new file mode 100644 index 0000000..8e302da --- /dev/null +++ b/src/test/resources/testPrograms/callable/Procedure.monty @@ -0,0 +1,17 @@ +// Testing: ProcedureDeclaration and FunctionCall +// +// The procedures must be called correctly and execute the body. +// +// Expected output: Hello World + +output1(): + print("Hello ") + +output2(): + print("World") + if true: + return + print("Nope") + +output1() +output2() diff --git a/src/test/resources/testPrograms/callable/Procedure.output b/src/test/resources/testPrograms/callable/Procedure.output new file mode 100644 index 0000000..5e1c309 --- /dev/null +++ b/src/test/resources/testPrograms/callable/Procedure.output @@ -0,0 +1 @@ +Hello World \ No newline at end of file diff --git a/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction1.monty b/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction1.monty new file mode 100644 index 0000000..e7dfe58 --- /dev/null +++ b/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction1.monty @@ -0,0 +1,11 @@ +// Testing: FunctionDeclaration and FunctionCall +// +// The function must be called correctly and return the evaluated return +// expression. +// +// Expected output: 4 + +Int square(Int value := 2): + return value * value + +print(square()) diff --git a/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction1.output b/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction1.output new file mode 100644 index 0000000..bf0d87a --- /dev/null +++ b/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction1.output @@ -0,0 +1 @@ +4 \ No newline at end of file diff --git a/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction2.monty b/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction2.monty new file mode 100644 index 0000000..dc93800 --- /dev/null +++ b/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction2.monty @@ -0,0 +1,11 @@ +// Testing: FunctionDeclaration and FunctionCall +// +// The function must be called correctly and return the evaluated return +// expression. +// +// Expected output: 4 + +Int square(Int dummy1, Int dummy2, Int value := 2): + return value * value + +print(square(1,2)) diff --git a/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction2.output b/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction2.output new file mode 100644 index 0000000..bf0d87a --- /dev/null +++ b/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction2.output @@ -0,0 +1 @@ +4 \ No newline at end of file diff --git a/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction3.monty b/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction3.monty new file mode 100644 index 0000000..377d51a --- /dev/null +++ b/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction3.monty @@ -0,0 +1,13 @@ +// Testing: FunctionDeclaration and FunctionCall +// +// The function must be called correctly and return the evaluated return +// expression. +// +// Expected output: 261 + +Int func(Int dummy1, Int dummy2, Int value1 := 2, Int value2 := 6): + print(value1) + print (value2) + return dummy1 + +print(func(1,2)) diff --git a/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction3.output b/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction3.output new file mode 100644 index 0000000..c390b4c --- /dev/null +++ b/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction3.output @@ -0,0 +1 @@ +261 \ No newline at end of file diff --git a/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction4.monty b/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction4.monty new file mode 100644 index 0000000..0a96da7 --- /dev/null +++ b/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction4.monty @@ -0,0 +1,21 @@ +// Testing: FunctionDeclaration and FunctionCall +// +// The function must be called correctly and return the evaluated return +// expression. +// +// Expected output: 3611230 + +Int func1(Int dummy1, Int dummy2, Int value1 := 2, Int value2 := 6): + print(value1) + print (value2) + return dummy1 + +print(func1(1,2,3)) + +Int func2(Int dummy1, Int value3 := 3, Int value1 := 1, Int value2 := 2): + print(value1) + print (value2) + print(value3) + return dummy1 + +print(func2(0)) \ No newline at end of file diff --git a/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction4.output b/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction4.output new file mode 100644 index 0000000..325ab32 --- /dev/null +++ b/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction4.output @@ -0,0 +1 @@ +3611230 \ No newline at end of file diff --git a/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction5.monty b/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction5.monty new file mode 100644 index 0000000..5a51ee6 --- /dev/null +++ b/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction5.monty @@ -0,0 +1,32 @@ +// Testing: ProcedureDeclaration and FunctionCall +// +// The procedure must be called correctly and return the evaluated return +// expression. +// +// Expected output: 400100200000001000012000123 + +square(Int value := 2): + print(value * value) + +square() + + +proc1(Int dummy1, Int dummy2, Int value1 := 1): + print(dummy1) + print(dummy2) + print(value1) + +proc1(0,0) +proc1(0,0,2) + +proc2(Int dummy1, Int dummy2, Int value1 := 0, Int value2 := 0, Int value3 := 0): + print(dummy1) + print(dummy2) + print(value1) + print(value2) + print(value3) + +proc2(0,0) +proc2(0,0,1) +proc2(0,0,1,2) +proc2(0,0,1,2,3) diff --git a/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction5.output b/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction5.output new file mode 100644 index 0000000..9493c05 --- /dev/null +++ b/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction5.output @@ -0,0 +1 @@ +400100200000001000012000123 \ No newline at end of file diff --git a/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction6.monty b/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction6.monty new file mode 100644 index 0000000..98886db --- /dev/null +++ b/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction6.monty @@ -0,0 +1,33 @@ +// Testing: Default-Parameter for methods +// +// The methods (functions and procedures) of a class with parameters must be +// called correctly. +// +// Expected output: + +class Person: + + constructor(): + pass + + + saySomething1(String text := "Hello"): + print(text) + + + saySomething2(Person person := Person()): + person.saySomething1() + + + Int stupidMethod(Int dummy1, Int value1 := 3, Int value2 := 1, Int value3 := 2): + print(value1) + print (value2) + print(value3) + return dummy1 + + + Float liftWeight(Float weight := 100.0): + return weight + +Person person := Person() +person.saySomething1() +person.saySomething1("World") +person.saySomething2() +person.saySomething2(person) +print(person.stupidMethod(12)) +print(person.liftWeight()) \ No newline at end of file diff --git a/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction6.output b/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction6.output new file mode 100644 index 0000000..6994950 --- /dev/null +++ b/src/test/resources/testPrograms/callable/defaultParameter/DefaultFunction6.output @@ -0,0 +1 @@ +HelloWorldHelloHello31212100 \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/ClassMemberBool1.monty b/src/test/resources/testPrograms/classes/ClassMemberBool1.monty new file mode 100644 index 0000000..87fc3cf --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberBool1.monty @@ -0,0 +1,15 @@ +// Testing: VariableDeclaration in ClassDeclaration. +// +// The boolean attribute is written and printed. The access via self must +// work. +// +// Expected output: 1 + +class Ab: + + initializer(): + self.attr := true + print(self.attr) + + + Bool attr + +Ab b := Ab() diff --git a/src/test/resources/testPrograms/classes/ClassMemberBool1.output b/src/test/resources/testPrograms/classes/ClassMemberBool1.output new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberBool1.output @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/ClassMemberBool2.monty b/src/test/resources/testPrograms/classes/ClassMemberBool2.monty new file mode 100644 index 0000000..617280f --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberBool2.monty @@ -0,0 +1,15 @@ +// Testing: VariableDeclaration in ClassDeclaration. +// +// The boolean attribute is written and printed from outside the class. The +// access via self and the member access must work. +// +// Expected output: 1 + +class Ab: + + initializer(): + self.attr := true + + + Bool attr + +Ab b := Ab() +print(b.attr) diff --git a/src/test/resources/testPrograms/classes/ClassMemberBool2.output b/src/test/resources/testPrograms/classes/ClassMemberBool2.output new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberBool2.output @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/ClassMemberBool3.monty b/src/test/resources/testPrograms/classes/ClassMemberBool3.monty new file mode 100644 index 0000000..1ec2cff --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberBool3.monty @@ -0,0 +1,17 @@ +// Testing: VariableDeclaration in ClassDeclaration. +// +// A boolean attribute and a local variable exist with the same name. Both +// must be writable and readable. +// +// Expected output: 10 + +class Ab: + + initializer(): + self.attr := true + Bool attr := false + print(self.attr) + print(attr) + + + Bool attr + +Ab b := Ab() diff --git a/src/test/resources/testPrograms/classes/ClassMemberBool3.output b/src/test/resources/testPrograms/classes/ClassMemberBool3.output new file mode 100644 index 0000000..9a03714 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberBool3.output @@ -0,0 +1 @@ +10 \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/ClassMemberBool4.monty b/src/test/resources/testPrograms/classes/ClassMemberBool4.monty new file mode 100644 index 0000000..036c305 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberBool4.monty @@ -0,0 +1,16 @@ +// Testing: VariableDeclaration in ClassDeclaration. +// +// The boolean attribute is written and a copy printed. The access via self +// must work. +// +// Expected output: 1 + +class Ab: + + initializer(): + self.attr := true + Bool copy := self.attr + print(copy) + + + Bool attr + +Ab b := Ab() diff --git a/src/test/resources/testPrograms/classes/ClassMemberBool4.output b/src/test/resources/testPrograms/classes/ClassMemberBool4.output new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberBool4.output @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/ClassMemberChar1.monty b/src/test/resources/testPrograms/classes/ClassMemberChar1.monty new file mode 100644 index 0000000..5ba9d00 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberChar1.monty @@ -0,0 +1,15 @@ +// Testing: VariableDeclaration in ClassDeclaration. +// +// The char attribute is written and printed. The access via self must +// work. +// +// Expected output: 'M' + +class Ab: + + initializer(): + self.attr := 'M' + print(self.attr) + + + Char attr + +Ab b := Ab() diff --git a/src/test/resources/testPrograms/classes/ClassMemberChar1.output b/src/test/resources/testPrograms/classes/ClassMemberChar1.output new file mode 100644 index 0000000..ef6bce1 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberChar1.output @@ -0,0 +1 @@ +M \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/ClassMemberChar2.monty b/src/test/resources/testPrograms/classes/ClassMemberChar2.monty new file mode 100644 index 0000000..04650dc --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberChar2.monty @@ -0,0 +1,15 @@ +// Testing: VariableDeclaration in ClassDeclaration. +// +// The char attribute is written and printed from outside the class. The +// access via self and the member access must work. +// +// Expected output: M + +class Ab: + + initializer(): + self.attr := 'M' + + + Char attr + +Ab b := Ab() +print(b.attr) diff --git a/src/test/resources/testPrograms/classes/ClassMemberChar2.output b/src/test/resources/testPrograms/classes/ClassMemberChar2.output new file mode 100644 index 0000000..ef6bce1 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberChar2.output @@ -0,0 +1 @@ +M \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/ClassMemberChar3.monty b/src/test/resources/testPrograms/classes/ClassMemberChar3.monty new file mode 100644 index 0000000..59d55e0 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberChar3.monty @@ -0,0 +1,17 @@ +// Testing: VariableDeclaration in ClassDeclaration. +// +// An char attribute and a local variable exist with the same name. Both +// must be writable and readable. +// +// Expected output: JO + +class Ab: + + initializer(): + self.attr := 'J' + Char attr := 'O' + print(self.attr) + print(attr) + + + Char attr + +Ab b := Ab() diff --git a/src/test/resources/testPrograms/classes/ClassMemberChar3.output b/src/test/resources/testPrograms/classes/ClassMemberChar3.output new file mode 100644 index 0000000..444a896 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberChar3.output @@ -0,0 +1 @@ +JO \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/ClassMemberChar4.monty b/src/test/resources/testPrograms/classes/ClassMemberChar4.monty new file mode 100644 index 0000000..7d63975 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberChar4.monty @@ -0,0 +1,16 @@ +// Testing: VariableDeclaration in ClassDeclaration. +// +// The char attribute is written and a copy printed. The access via self +// must work. +// +// Expected output: M + +class Ab: + + initializer(): + self.attr := 'M' + Char copy := self.attr + print(copy) + + + Char attr + +Ab b := Ab() diff --git a/src/test/resources/testPrograms/classes/ClassMemberChar4.output b/src/test/resources/testPrograms/classes/ClassMemberChar4.output new file mode 100644 index 0000000..ef6bce1 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberChar4.output @@ -0,0 +1 @@ +M \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/ClassMemberComplex1.monty b/src/test/resources/testPrograms/classes/ClassMemberComplex1.monty new file mode 100644 index 0000000..1fc7ea3 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberComplex1.monty @@ -0,0 +1,33 @@ +// Testing: VariableDeclaration in ClassDeclaration. +// +// The attributes of a class with multiple attributes of different types are +// written and read from within the initializer and outside the class. +// +// Expected output: 18Paul119Paula0 + +class Person: + + initializer(): + self.isMale := false + self.age := 0 + self.name := "" + + + Bool isMale + + Int age + + String name + +Person person := Person() +person.age := 18 +person.name := "Paul" +person.isMale := true + +print(person.age) +print(person.name) +print(person.isMale) + +person.age := 19 +person.name := "Paula" +person.isMale := false + +print(person.age) +print(person.name) +print(person.isMale) diff --git a/src/test/resources/testPrograms/classes/ClassMemberComplex1.output b/src/test/resources/testPrograms/classes/ClassMemberComplex1.output new file mode 100644 index 0000000..bacc5d5 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberComplex1.output @@ -0,0 +1 @@ +18Paul119Paula0 \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/ClassMemberComplex2.monty b/src/test/resources/testPrograms/classes/ClassMemberComplex2.monty new file mode 100644 index 0000000..b59d4da --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberComplex2.monty @@ -0,0 +1,20 @@ +// Testing: VariableDeclaration in ClassDeclaration. +// +// A complex expression of chained attributes must be accessible and readable. +// +// Expected output: Hallo Welt + +class Ab: + + String attr + + + initializer(): + self.attr := "Hallo Welt" + +class Ba: + + Ab attr + + + initializer(): + self.attr := Ab() + +Ba inst := Ba() +print(inst.attr.attr) diff --git a/src/test/resources/testPrograms/classes/ClassMemberComplex2.output b/src/test/resources/testPrograms/classes/ClassMemberComplex2.output new file mode 100644 index 0000000..a92550c --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberComplex2.output @@ -0,0 +1 @@ +Hallo Welt \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/ClassMemberComplex3.monty b/src/test/resources/testPrograms/classes/ClassMemberComplex3.monty new file mode 100644 index 0000000..6cd2cc4 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberComplex3.monty @@ -0,0 +1,22 @@ +// Testing: VariableDeclaration in ClassDeclaration. +// +// A complex expression of chained attributes must be accessible, writable and +// readable. +// +// Expected output: Hallo Welt + +class Ab: + + String attr + + + initializer(): + self.attr := "Nope" + +class Ba: + + Ab attr + + + initializer(): + self.attr := Ab() + +Ba inst := Ba() +inst.attr.attr := "Hallo Welt" +print(inst.attr.attr) diff --git a/src/test/resources/testPrograms/classes/ClassMemberComplex3.output b/src/test/resources/testPrograms/classes/ClassMemberComplex3.output new file mode 100644 index 0000000..a92550c --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberComplex3.output @@ -0,0 +1 @@ +Hallo Welt \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/ClassMemberFloat1.monty b/src/test/resources/testPrograms/classes/ClassMemberFloat1.monty new file mode 100644 index 0000000..fd2f01e --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberFloat1.monty @@ -0,0 +1,15 @@ +// Testing: VariableDeclaration in ClassDeclaration. +// +// The float attribute is written and printed. The access via self must +// work. +// +// Expected output: 1.3 + +class Ab: + + initializer(): + self.attr := 1.3 + print(self.attr) + + + Float attr + +Ab b := Ab() diff --git a/src/test/resources/testPrograms/classes/ClassMemberFloat1.output b/src/test/resources/testPrograms/classes/ClassMemberFloat1.output new file mode 100644 index 0000000..a58941b --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberFloat1.output @@ -0,0 +1 @@ +1.3 \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/ClassMemberFloat2.monty b/src/test/resources/testPrograms/classes/ClassMemberFloat2.monty new file mode 100644 index 0000000..2c95c59 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberFloat2.monty @@ -0,0 +1,15 @@ +// Testing: VariableDeclaration in ClassDeclaration. +// +// The float attribute is written and printed from outside the class. The +// access via self and the member access must work. +// +// Expected output: 1.3 + +class Ab: + + initializer(): + self.attr := 1.3 + + + Float attr + +Ab b := Ab() +print(b.attr) diff --git a/src/test/resources/testPrograms/classes/ClassMemberFloat2.output b/src/test/resources/testPrograms/classes/ClassMemberFloat2.output new file mode 100644 index 0000000..a58941b --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberFloat2.output @@ -0,0 +1 @@ +1.3 \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/ClassMemberFloat3.monty b/src/test/resources/testPrograms/classes/ClassMemberFloat3.monty new file mode 100644 index 0000000..01547ab --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberFloat3.monty @@ -0,0 +1,17 @@ +// Testing: VariableDeclaration in ClassDeclaration. +// +// A float attribute and a local variable exist with the same name. Both +// must be writable and readable. +// +// Expected output: 1.33.1 + +class Ab: + + initializer(): + self.attr := 1.3 + Float attr := 3.1 + print(self.attr) + print(attr) + + + Float attr + +Ab b := Ab() diff --git a/src/test/resources/testPrograms/classes/ClassMemberFloat3.output b/src/test/resources/testPrograms/classes/ClassMemberFloat3.output new file mode 100644 index 0000000..9e9fac3 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberFloat3.output @@ -0,0 +1 @@ +1.33.1 \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/ClassMemberFloat4.monty b/src/test/resources/testPrograms/classes/ClassMemberFloat4.monty new file mode 100644 index 0000000..348c267 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberFloat4.monty @@ -0,0 +1,16 @@ +// Testing: VariableDeclaration in ClassDeclaration. +// +// The float attribute is written and a copy printed. The access via self +// must work. +// +// Expected output: 1.3 + +class Ab: + + initializer(): + self.attr := 1.3 + Float copy := self.attr + print(copy) + + + Float attr + +Ab b := Ab() diff --git a/src/test/resources/testPrograms/classes/ClassMemberFloat4.output b/src/test/resources/testPrograms/classes/ClassMemberFloat4.output new file mode 100644 index 0000000..a58941b --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberFloat4.output @@ -0,0 +1 @@ +1.3 \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/ClassMemberInt1.monty b/src/test/resources/testPrograms/classes/ClassMemberInt1.monty new file mode 100644 index 0000000..5d47486 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberInt1.monty @@ -0,0 +1,15 @@ +// Testing: VariableDeclaration in ClassDeclaration. +// +// The int attribute is written and printed. The access via self must +// work. +// +// Expected output: 1 + +class Ab: + + initializer(): + self.attr := 1 + print(self.attr) + + + Int attr + +Ab b := Ab() diff --git a/src/test/resources/testPrograms/classes/ClassMemberInt1.output b/src/test/resources/testPrograms/classes/ClassMemberInt1.output new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberInt1.output @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/ClassMemberInt2.monty b/src/test/resources/testPrograms/classes/ClassMemberInt2.monty new file mode 100644 index 0000000..52e4dae --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberInt2.monty @@ -0,0 +1,15 @@ +// Testing: VariableDeclaration in ClassDeclaration. +// +// The int attribute is written and printed from outside the class. The +// access via self and the member access must work. +// +// Expected output: 1 + +class Ab: + + initializer(): + self.attr := 1 + + + Int attr + +Ab b := Ab() +print(b.attr) diff --git a/src/test/resources/testPrograms/classes/ClassMemberInt2.output b/src/test/resources/testPrograms/classes/ClassMemberInt2.output new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberInt2.output @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/ClassMemberInt3.monty b/src/test/resources/testPrograms/classes/ClassMemberInt3.monty new file mode 100644 index 0000000..5b44911 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberInt3.monty @@ -0,0 +1,17 @@ +// Testing: VariableDeclaration in ClassDeclaration. +// +// An int attribute and a local variable exist with the same name. Both +// must be writable and readable. +// +// Expected output: 10 + +class Ab: + + initializer(): + self.attr := 1 + Int attr := 0 + print(self.attr) + print(attr) + + + Int attr + +Ab b := Ab() diff --git a/src/test/resources/testPrograms/classes/ClassMemberInt3.output b/src/test/resources/testPrograms/classes/ClassMemberInt3.output new file mode 100644 index 0000000..9a03714 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberInt3.output @@ -0,0 +1 @@ +10 \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/ClassMemberInt4.monty b/src/test/resources/testPrograms/classes/ClassMemberInt4.monty new file mode 100644 index 0000000..4462ca3 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberInt4.monty @@ -0,0 +1,16 @@ +// Testing: VariableDeclaration in ClassDeclaration. +// +// The int attribute is written and a copy printed. The access via self +// must work. +// +// Expected output: 1 + +class Ab: + + initializer(): + self.attr := 1 + Int copy := self.attr + print(copy) + + + Int attr + +Ab b := Ab() diff --git a/src/test/resources/testPrograms/classes/ClassMemberInt4.output b/src/test/resources/testPrograms/classes/ClassMemberInt4.output new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberInt4.output @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/ClassMemberString1.monty b/src/test/resources/testPrograms/classes/ClassMemberString1.monty new file mode 100644 index 0000000..b836a7b --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberString1.monty @@ -0,0 +1,15 @@ +// Testing: VariableDeclaration in ClassDeclaration. +// +// The string attribute is written and printed. The access via self must +// work. +// +// Expected output: Hallo + +class Ab: + + initializer(): + self.attr := "Hallo" + print(self.attr) + + + String attr + +Ab b := Ab() diff --git a/src/test/resources/testPrograms/classes/ClassMemberString1.output b/src/test/resources/testPrograms/classes/ClassMemberString1.output new file mode 100644 index 0000000..53f5007 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberString1.output @@ -0,0 +1 @@ +Hallo \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/ClassMemberString2.monty b/src/test/resources/testPrograms/classes/ClassMemberString2.monty new file mode 100644 index 0000000..c3f6125 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberString2.monty @@ -0,0 +1,15 @@ +// Testing: VariableDeclaration in ClassDeclaration. +// +// The string attribute is written and printed from outside the class. The +// access via self and the member access must work. +// +// Expected output: Hallo + +class Ab: + + initializer(): + self.attr := "Hallo" + + + String attr + +Ab b := Ab() +print(b.attr) diff --git a/src/test/resources/testPrograms/classes/ClassMemberString2.output b/src/test/resources/testPrograms/classes/ClassMemberString2.output new file mode 100644 index 0000000..53f5007 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberString2.output @@ -0,0 +1 @@ +Hallo \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/ClassMemberString3.monty b/src/test/resources/testPrograms/classes/ClassMemberString3.monty new file mode 100644 index 0000000..3f1bb48 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberString3.monty @@ -0,0 +1,17 @@ +// Testing: VariableDeclaration in ClassDeclaration. +// +// A string attribute and a local variable exist with the same name. Both +// must be writable and readable. +// +// Expected output: HalloWelt + +class Ab: + + initializer(): + self.attr := "Hallo" + String attr := "Welt" + print(self.attr) + print(attr) + + + String attr + +Ab b := Ab() diff --git a/src/test/resources/testPrograms/classes/ClassMemberString3.output b/src/test/resources/testPrograms/classes/ClassMemberString3.output new file mode 100644 index 0000000..b7b7804 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberString3.output @@ -0,0 +1 @@ +HalloWelt \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/ClassMemberString4.monty b/src/test/resources/testPrograms/classes/ClassMemberString4.monty new file mode 100644 index 0000000..bb1c138 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberString4.monty @@ -0,0 +1,16 @@ +// Testing: VariableDeclaration in ClassDeclaration. +// +// The string attribute is written and a copy printed. The access via self +// must work. +// +// Expected output: Hallo + +class Ab: + + initializer(): + self.attr := "Hallo" + String copy := self.attr + print(copy) + + + String attr + +Ab b := Ab() diff --git a/src/test/resources/testPrograms/classes/ClassMemberString4.output b/src/test/resources/testPrograms/classes/ClassMemberString4.output new file mode 100644 index 0000000..53f5007 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassMemberString4.output @@ -0,0 +1 @@ +Hallo \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/ClassPointer1.monty b/src/test/resources/testPrograms/classes/ClassPointer1.monty new file mode 100644 index 0000000..47ee295 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassPointer1.monty @@ -0,0 +1,31 @@ +// Testing: VariableDeclaration of type ClassDeclaration. +// +// The variable 'person' is a reference to an instance of Person. Passing this +// reference arround must work. Storing it under alternative names and +// altering the attribute must be visible under all references. +// +// Expected output: PeterPaulPetraPetraPaulaPaula + +class Person: + + initializer(String name): + self.name := name + + + String name + +Person alterPerson(Person per): + per.name := "Petra" + return per + +Person person := Person("Peter") +print(person.name) + +person.name := "Paul" +print(person.name) + +Person new := alterPerson(person) +print(person.name) +print(new.name) + +person.name := "Paula" +print(person.name) +print(new.name) diff --git a/src/test/resources/testPrograms/classes/ClassPointer1.output b/src/test/resources/testPrograms/classes/ClassPointer1.output new file mode 100644 index 0000000..25dcdef --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassPointer1.output @@ -0,0 +1 @@ +PeterPaulPetraPetraPaulaPaula \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/ClassPointer2.monty b/src/test/resources/testPrograms/classes/ClassPointer2.monty new file mode 100644 index 0000000..c26121d --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassPointer2.monty @@ -0,0 +1,26 @@ +// Testing: VariableDeclaration of type ClassDeclaration. +// +// The function buildPerson() returns a reference to a heap allocated Person. +// The procedure stackDestroyer() would override the stack memory if objects +// are allocated on the stack. +// +// Expected output: Peter + +class Person: + + initializer(String name): + self.name := name + + + String name + +Person buildPerson(): + Person person := Person("Peter") + return person + +stackDestroyer(): + Person person1 := Person("Stack") + Person person2 := Person("Des") + Person person3 := Person("Troyer") + +Person person := buildPerson() +stackDestroyer() +print(person.name) diff --git a/src/test/resources/testPrograms/classes/ClassPointer2.output b/src/test/resources/testPrograms/classes/ClassPointer2.output new file mode 100644 index 0000000..9cd89b6 --- /dev/null +++ b/src/test/resources/testPrograms/classes/ClassPointer2.output @@ -0,0 +1 @@ +Peter \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/constructor/Constructor1.monty b/src/test/resources/testPrograms/classes/constructor/Constructor1.monty new file mode 100644 index 0000000..4b1eb73 --- /dev/null +++ b/src/test/resources/testPrograms/classes/constructor/Constructor1.monty @@ -0,0 +1,13 @@ +// Testing: ClassDeclaration +// +// The simple initializer call must work. +// +// Expected output: Hi + +class Ab: + + String someAttr + + + initializer(): + print("Hi") + +Ab x := Ab() diff --git a/src/test/resources/testPrograms/classes/constructor/Constructor1.output b/src/test/resources/testPrograms/classes/constructor/Constructor1.output new file mode 100644 index 0000000..40816a2 --- /dev/null +++ b/src/test/resources/testPrograms/classes/constructor/Constructor1.output @@ -0,0 +1 @@ +Hi \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/constructor/Constructor2.monty b/src/test/resources/testPrograms/classes/constructor/Constructor2.monty new file mode 100644 index 0000000..f0105b3 --- /dev/null +++ b/src/test/resources/testPrograms/classes/constructor/Constructor2.monty @@ -0,0 +1,11 @@ +// Testing: ClassDeclaration +// +// The simple initializer call with a parameter must work. +// +// Expected output: HALLO + +class Ab: + + initializer(String a): + print(a) + +Ab x := Ab("HALLO") diff --git a/src/test/resources/testPrograms/classes/constructor/Constructor2.output b/src/test/resources/testPrograms/classes/constructor/Constructor2.output new file mode 100644 index 0000000..d3327f7 --- /dev/null +++ b/src/test/resources/testPrograms/classes/constructor/Constructor2.output @@ -0,0 +1 @@ +HALLO \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/constructor/Constructor3.monty b/src/test/resources/testPrograms/classes/constructor/Constructor3.monty new file mode 100644 index 0000000..84b7c79 --- /dev/null +++ b/src/test/resources/testPrograms/classes/constructor/Constructor3.monty @@ -0,0 +1,12 @@ +// Testing: ClassDeclaration +// +// The simple initializer call with a variable as parameter must work. +// +// Expected output: HALLO + +class Ab: + + initializer(String a): + print(a) + +String hallo := "HALLO" +Ab x := Ab(hallo) diff --git a/src/test/resources/testPrograms/classes/constructor/Constructor3.output b/src/test/resources/testPrograms/classes/constructor/Constructor3.output new file mode 100644 index 0000000..d3327f7 --- /dev/null +++ b/src/test/resources/testPrograms/classes/constructor/Constructor3.output @@ -0,0 +1 @@ +HALLO \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/constructor/Constructor4.monty b/src/test/resources/testPrograms/classes/constructor/Constructor4.monty new file mode 100644 index 0000000..4f2d452 --- /dev/null +++ b/src/test/resources/testPrograms/classes/constructor/Constructor4.monty @@ -0,0 +1,15 @@ +// Testing: ClassDeclaration +// +// The simple initializer call with a variable as parameter and an assignment +// to an attribute must work. +// +// Expected output: HALLO + +class Ab: + + String someAttr + + + initializer(String a): + self.someAttr := a + +Ab x := Ab("HALLO") +print(x.someAttr) diff --git a/src/test/resources/testPrograms/classes/constructor/Constructor4.output b/src/test/resources/testPrograms/classes/constructor/Constructor4.output new file mode 100644 index 0000000..d3327f7 --- /dev/null +++ b/src/test/resources/testPrograms/classes/constructor/Constructor4.output @@ -0,0 +1 @@ +HALLO \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/constructor/Constructor5.monty b/src/test/resources/testPrograms/classes/constructor/Constructor5.monty new file mode 100644 index 0000000..ee3176a --- /dev/null +++ b/src/test/resources/testPrograms/classes/constructor/Constructor5.monty @@ -0,0 +1,15 @@ +// Testing: ClassDeclaration, default initializer +// +// The default initializer must be created when no initializer is given and do +// all class attribute assignments. +// +// Expected output: reifenschubser + +class MyClass: + + String baum := "schubser" + + String auto := "reifen" + +MyClass clazz := MyClass() + +print(clazz.auto) +print(clazz.baum) diff --git a/src/test/resources/testPrograms/classes/constructor/Constructor5.output b/src/test/resources/testPrograms/classes/constructor/Constructor5.output new file mode 100644 index 0000000..91ba2ac --- /dev/null +++ b/src/test/resources/testPrograms/classes/constructor/Constructor5.output @@ -0,0 +1 @@ +reifenschubser \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/constructor/Constructor6.monty b/src/test/resources/testPrograms/classes/constructor/Constructor6.monty new file mode 100644 index 0000000..c6e052f --- /dev/null +++ b/src/test/resources/testPrograms/classes/constructor/Constructor6.monty @@ -0,0 +1,16 @@ +// Testing: ClassDeclaration, default initializer / attr assignments +// +// The initializer must first execute the class attribute assignments and then +// execute its own body. +// +// Expected output: HalloBernd + +class Ab: + + initializer(): + print(self.attr) + self.attr := "Bernd" + + + String attr := "Hallo" + +Ab b := Ab() +print(b.attr) \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/constructor/Constructor6.output b/src/test/resources/testPrograms/classes/constructor/Constructor6.output new file mode 100644 index 0000000..2d4c760 --- /dev/null +++ b/src/test/resources/testPrograms/classes/constructor/Constructor6.output @@ -0,0 +1 @@ +HalloBernd \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/constructor/Constructor7.monty b/src/test/resources/testPrograms/classes/constructor/Constructor7.monty new file mode 100644 index 0000000..f6cb58b --- /dev/null +++ b/src/test/resources/testPrograms/classes/constructor/Constructor7.monty @@ -0,0 +1,24 @@ +// Testing: ClassDeclaration, default initializer / attr assignments +// +// The assignments of member attributes of the class must be executed in all +// given initializers. +// +// Expected output: null!eins!zwei! + +class MyClass: + + String null := "null!" + + String eins := "eins!" + + String zwei := "zwei!" + + + initializer(): + print(self.null) + + + initializer(String egal): + print(self.eins) + + + initializer(String egal, String auchunwichtig): + print(self.zwei) + +MyClass clazz0 := MyClass() +MyClass clazz1 := MyClass("1") +MyClass clazz2 := MyClass("1", "2") \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/constructor/Constructor7.output b/src/test/resources/testPrograms/classes/constructor/Constructor7.output new file mode 100644 index 0000000..bba4b81 --- /dev/null +++ b/src/test/resources/testPrograms/classes/constructor/Constructor7.output @@ -0,0 +1 @@ +null!eins!zwei! \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/methods/Methods1.monty b/src/test/resources/testPrograms/classes/methods/Methods1.monty new file mode 100644 index 0000000..d547a6e --- /dev/null +++ b/src/test/resources/testPrograms/classes/methods/Methods1.monty @@ -0,0 +1,29 @@ +// Testing: Methods of classes +// +// The methods (functions and procedures) of a class must be called correctly. +// +// Expected output: Stoehn Aechz Keuch + +class Laute: + + initializer(): + pass + + + printSpace(): + print(" ") + + + String stoehn(): + return "Stoehn" + + + String aechz(): + return "Aechz" + + + String keuch(): + return "Keuch" + +Laute laut := Laute() + +print(laut.stoehn()) +laut.printSpace() +print(laut.aechz()) +laut.printSpace() +print(laut.keuch()) diff --git a/src/test/resources/testPrograms/classes/methods/Methods1.output b/src/test/resources/testPrograms/classes/methods/Methods1.output new file mode 100644 index 0000000..bc757d7 --- /dev/null +++ b/src/test/resources/testPrograms/classes/methods/Methods1.output @@ -0,0 +1 @@ +Stoehn Aechz Keuch \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/methods/Methods2.monty b/src/test/resources/testPrograms/classes/methods/Methods2.monty new file mode 100644 index 0000000..693f845 --- /dev/null +++ b/src/test/resources/testPrograms/classes/methods/Methods2.monty @@ -0,0 +1,20 @@ +// Testing: Methods of classes +// +// The methods (functions and procedures) of a class with parameters must be +// called correctly. +// +// Expected output: BAUM FAELLT!uiuiui + +class Laute: + + initializer(): + pass + + + String gibLaut(String ausruf): + return ausruf + + + printLaut(String ausruf): + print(ausruf) + +Laute laut := Laute() +print(laut.gibLaut("BAUM FAELLT!")) +laut.printLaut("uiuiui") diff --git a/src/test/resources/testPrograms/classes/methods/Methods2.output b/src/test/resources/testPrograms/classes/methods/Methods2.output new file mode 100644 index 0000000..a297a72 --- /dev/null +++ b/src/test/resources/testPrograms/classes/methods/Methods2.output @@ -0,0 +1 @@ +BAUM FAELLT!uiuiui \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/methods/Methods3.monty b/src/test/resources/testPrograms/classes/methods/Methods3.monty new file mode 100644 index 0000000..52001c1 --- /dev/null +++ b/src/test/resources/testPrograms/classes/methods/Methods3.monty @@ -0,0 +1,23 @@ +// Testing: Methods of classes +// +// The methods (functions and procedures) of a class must be called correctly +// with the class as a reference to an instance. +// +// Expected output: Wuff + +class Dog: + + initializer(): + pass + + + bark(): + print("Wuff") + +Dog buildDog(): + Dog dog := Dog() + return dog + +bark(Dog dogy): + dogy.bark() + +Dog dog := Dog() +bark(dog) diff --git a/src/test/resources/testPrograms/classes/methods/Methods3.output b/src/test/resources/testPrograms/classes/methods/Methods3.output new file mode 100644 index 0000000..4aa6ca2 --- /dev/null +++ b/src/test/resources/testPrograms/classes/methods/Methods3.output @@ -0,0 +1 @@ +Wuff \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/methods/Methods4.monty b/src/test/resources/testPrograms/classes/methods/Methods4.monty new file mode 100644 index 0000000..93d5510 --- /dev/null +++ b/src/test/resources/testPrograms/classes/methods/Methods4.monty @@ -0,0 +1,22 @@ +// Testing: Methods of classes +// +// The methods (functions and procedures) of multiple classes must work +// together. +// +// Expected output: 123 + +class Node: + + initializer(String id): + self.id := id + + - String id + + String getId(): + return self.id + + setId(String value): + self.id := value + +Node node := Node("") +Node node2 := Node("123") + +node.setId(node2.getId()) +print(node.getId()) diff --git a/src/test/resources/testPrograms/classes/methods/Methods4.output b/src/test/resources/testPrograms/classes/methods/Methods4.output new file mode 100644 index 0000000..d800886 --- /dev/null +++ b/src/test/resources/testPrograms/classes/methods/Methods4.output @@ -0,0 +1 @@ +123 \ No newline at end of file diff --git a/src/test/resources/testPrograms/classes/methods/Methods5.monty b/src/test/resources/testPrograms/classes/methods/Methods5.monty new file mode 100644 index 0000000..a1689b4 --- /dev/null +++ b/src/test/resources/testPrograms/classes/methods/Methods5.monty @@ -0,0 +1,36 @@ +// Testing: Methods of classes +// +// The methods (functions and procedures) of multiple classes must work +// together if classes are passed as arguments and return values. +// +// Expected output: 12 + +class Edge: + + Node start + + Node end + + + initializer(Node start, Node end): + self.start := start + self.end := end + + + Node getStart(): + return self.start + + + Node getEnd(): + return self.end + +class Node: + + Int id + + + initializer(Int id): + self.id := id + + + Int getId(): + return self.id + +Node s := Node(1) +Node e := Node(2) +Edge edge := Edge(s,e) + +print(edge.getStart().getId()) +print(edge.getEnd().getId()) diff --git a/src/test/resources/testPrograms/classes/methods/Methods5.output b/src/test/resources/testPrograms/classes/methods/Methods5.output new file mode 100644 index 0000000..3cacc0b --- /dev/null +++ b/src/test/resources/testPrograms/classes/methods/Methods5.output @@ -0,0 +1 @@ +12 \ No newline at end of file diff --git a/src/test/resources/testPrograms/compoundAssignments/Div.monty b/src/test/resources/testPrograms/compoundAssignments/Div.monty new file mode 100644 index 0000000..2d9664a --- /dev/null +++ b/src/test/resources/testPrograms/compoundAssignments/Div.monty @@ -0,0 +1,9 @@ +// Testing: CompoundAssignment +// +// Using the CompoundAssignment Div +// +// Expected output: 4 + +Int a := 8 +a /= 2 +print(a) diff --git a/src/test/resources/testPrograms/compoundAssignments/Div.output b/src/test/resources/testPrograms/compoundAssignments/Div.output new file mode 100644 index 0000000..bf0d87a --- /dev/null +++ b/src/test/resources/testPrograms/compoundAssignments/Div.output @@ -0,0 +1 @@ +4 \ No newline at end of file diff --git a/src/test/resources/testPrograms/compoundAssignments/Div1.monty b/src/test/resources/testPrograms/compoundAssignments/Div1.monty new file mode 100644 index 0000000..3bf4b19 --- /dev/null +++ b/src/test/resources/testPrograms/compoundAssignments/Div1.monty @@ -0,0 +1,10 @@ +// Testing: CompoundAssignment +// +// Using the CompoundAssignment Div with a slightly +// more complicated right hand expression +// +// Expected output: 13 + +Int a := 452 +a /= 3 + 2 * 15 +print(a) diff --git a/src/test/resources/testPrograms/compoundAssignments/Div1.output b/src/test/resources/testPrograms/compoundAssignments/Div1.output new file mode 100644 index 0000000..ca7bf83 --- /dev/null +++ b/src/test/resources/testPrograms/compoundAssignments/Div1.output @@ -0,0 +1 @@ +13 \ No newline at end of file diff --git a/src/test/resources/testPrograms/compoundAssignments/Minus.monty b/src/test/resources/testPrograms/compoundAssignments/Minus.monty new file mode 100644 index 0000000..3c477bb --- /dev/null +++ b/src/test/resources/testPrograms/compoundAssignments/Minus.monty @@ -0,0 +1,9 @@ +// Testing: CompoundAssignment +// +// Using the CompoundAssignment Minus +// +// Expected output: 3 + +Int a := 5 +a -= 2 +print(a) diff --git a/src/test/resources/testPrograms/compoundAssignments/Minus.output b/src/test/resources/testPrograms/compoundAssignments/Minus.output new file mode 100644 index 0000000..e440e5c --- /dev/null +++ b/src/test/resources/testPrograms/compoundAssignments/Minus.output @@ -0,0 +1 @@ +3 \ No newline at end of file diff --git a/src/test/resources/testPrograms/compoundAssignments/Minus1.monty b/src/test/resources/testPrograms/compoundAssignments/Minus1.monty new file mode 100644 index 0000000..95de524 --- /dev/null +++ b/src/test/resources/testPrograms/compoundAssignments/Minus1.monty @@ -0,0 +1,9 @@ +// Testing: CompoundAssignment +// +// Using the CompoundAssignment Minus +// +// Expected output: -19 + +Int a := 5 * 3 + 5 +a -= 13 * (4 - 1) +print(a) diff --git a/src/test/resources/testPrograms/compoundAssignments/Minus1.output b/src/test/resources/testPrograms/compoundAssignments/Minus1.output new file mode 100644 index 0000000..940cd43 --- /dev/null +++ b/src/test/resources/testPrograms/compoundAssignments/Minus1.output @@ -0,0 +1 @@ +-19 \ No newline at end of file diff --git a/src/test/resources/testPrograms/compoundAssignments/Mod.monty b/src/test/resources/testPrograms/compoundAssignments/Mod.monty new file mode 100644 index 0000000..d865bd5 --- /dev/null +++ b/src/test/resources/testPrograms/compoundAssignments/Mod.monty @@ -0,0 +1,9 @@ +// Testing: CompoundAssignment +// +// Using the CompoundAssignment Mod +// +// Expected output: 1 + +Int a := 5 +a %= 2 +print(a) diff --git a/src/test/resources/testPrograms/compoundAssignments/Mod.output b/src/test/resources/testPrograms/compoundAssignments/Mod.output new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/src/test/resources/testPrograms/compoundAssignments/Mod.output @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/src/test/resources/testPrograms/compoundAssignments/Mod1.monty b/src/test/resources/testPrograms/compoundAssignments/Mod1.monty new file mode 100644 index 0000000..e9f0933 --- /dev/null +++ b/src/test/resources/testPrograms/compoundAssignments/Mod1.monty @@ -0,0 +1,10 @@ +// Testing: CompoundAssignment +// +// Using the CompoundAssignment Mod with a slightly +// more complicated right hand expression +// +// Expected output: 2 + +Int a := 11 +a %= 2 * 4 - 5 +print(a) diff --git a/src/test/resources/testPrograms/compoundAssignments/Mod1.output b/src/test/resources/testPrograms/compoundAssignments/Mod1.output new file mode 100644 index 0000000..d8263ee --- /dev/null +++ b/src/test/resources/testPrograms/compoundAssignments/Mod1.output @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/src/test/resources/testPrograms/compoundAssignments/Mult.monty b/src/test/resources/testPrograms/compoundAssignments/Mult.monty new file mode 100644 index 0000000..a144b81 --- /dev/null +++ b/src/test/resources/testPrograms/compoundAssignments/Mult.monty @@ -0,0 +1,9 @@ +// Testing: CompoundAssignment +// +// Using the CompoundAssignment Mult +// +// Expected output: 10 + +Int a := 5 +a *= 2 +print(a) diff --git a/src/test/resources/testPrograms/compoundAssignments/Mult.output b/src/test/resources/testPrograms/compoundAssignments/Mult.output new file mode 100644 index 0000000..9a03714 --- /dev/null +++ b/src/test/resources/testPrograms/compoundAssignments/Mult.output @@ -0,0 +1 @@ +10 \ No newline at end of file diff --git a/src/test/resources/testPrograms/compoundAssignments/Mult1.monty b/src/test/resources/testPrograms/compoundAssignments/Mult1.monty new file mode 100644 index 0000000..ff703d3 --- /dev/null +++ b/src/test/resources/testPrograms/compoundAssignments/Mult1.monty @@ -0,0 +1,10 @@ +// Testing: CompoundAssignment +// +// Using the CompoundAssignment Mult with a slightly +// more complicated right hand expression +// +// Expected output: 33 + +Int a := 5 + 2 * 3 +a *= 3 +print(a) diff --git a/src/test/resources/testPrograms/compoundAssignments/Mult1.output b/src/test/resources/testPrograms/compoundAssignments/Mult1.output new file mode 100644 index 0000000..dc7b54a --- /dev/null +++ b/src/test/resources/testPrograms/compoundAssignments/Mult1.output @@ -0,0 +1 @@ +33 \ No newline at end of file diff --git a/src/test/resources/testPrograms/compoundAssignments/Plus.monty b/src/test/resources/testPrograms/compoundAssignments/Plus.monty new file mode 100644 index 0000000..403d502 --- /dev/null +++ b/src/test/resources/testPrograms/compoundAssignments/Plus.monty @@ -0,0 +1,9 @@ +// Testing: CompoundAssignment +// +// Using the CompoundAssignment Plus +// +// Expected output: 7 + +Int a := 5 +a += 2 +print(a) diff --git a/src/test/resources/testPrograms/compoundAssignments/Plus.output b/src/test/resources/testPrograms/compoundAssignments/Plus.output new file mode 100644 index 0000000..c793025 --- /dev/null +++ b/src/test/resources/testPrograms/compoundAssignments/Plus.output @@ -0,0 +1 @@ +7 \ No newline at end of file diff --git a/src/test/resources/testPrograms/compoundAssignments/Plus1.monty b/src/test/resources/testPrograms/compoundAssignments/Plus1.monty new file mode 100644 index 0000000..d45cc96 --- /dev/null +++ b/src/test/resources/testPrograms/compoundAssignments/Plus1.monty @@ -0,0 +1,10 @@ +// Testing: CompoundAssignment +// +// Using the CompoundAssignment Plus with a slightly +// more complicated right hand expression +// +// Expected output: 42 + +Int a := 12 +a += 7 * 4 + (1 * 2) +print(a) diff --git a/src/test/resources/testPrograms/compoundAssignments/Plus1.output b/src/test/resources/testPrograms/compoundAssignments/Plus1.output new file mode 100644 index 0000000..f70d7bb --- /dev/null +++ b/src/test/resources/testPrograms/compoundAssignments/Plus1.output @@ -0,0 +1 @@ +42 \ No newline at end of file diff --git a/src/test/resources/testPrograms/compoundAssignments/Power.monty.ignore b/src/test/resources/testPrograms/compoundAssignments/Power.monty.ignore new file mode 100644 index 0000000..15c16bd --- /dev/null +++ b/src/test/resources/testPrograms/compoundAssignments/Power.monty.ignore @@ -0,0 +1,9 @@ +// Testing: CompoundAssignment +// +// Using the CompoundAssignment Power +// +// Expected output: 64 + +Int a := 8 +a ^= 2 +print(a) diff --git a/src/test/resources/testPrograms/compoundAssignments/Power.output b/src/test/resources/testPrograms/compoundAssignments/Power.output new file mode 100644 index 0000000..4b6f9c3 --- /dev/null +++ b/src/test/resources/testPrograms/compoundAssignments/Power.output @@ -0,0 +1 @@ +64 \ No newline at end of file diff --git a/src/test/resources/testPrograms/compoundAssignments/Power1.monty.ignore b/src/test/resources/testPrograms/compoundAssignments/Power1.monty.ignore new file mode 100644 index 0000000..d774b6e --- /dev/null +++ b/src/test/resources/testPrograms/compoundAssignments/Power1.monty.ignore @@ -0,0 +1,10 @@ +// Testing: CompoundAssignment +// +// Using the CompoundAssignment Power with a slightly +// more complicated right hand expression +// +// Expected output: 243 + +Int a := 3 +a ^= 2 + 1 * 3 +print(a) diff --git a/src/test/resources/testPrograms/compoundAssignments/Power1.output b/src/test/resources/testPrograms/compoundAssignments/Power1.output new file mode 100644 index 0000000..104fcf5 --- /dev/null +++ b/src/test/resources/testPrograms/compoundAssignments/Power1.output @@ -0,0 +1 @@ +243 \ No newline at end of file diff --git a/src/test/resources/testPrograms/controlflow/ConditionalStatementComplex.monty b/src/test/resources/testPrograms/controlflow/ConditionalStatementComplex.monty new file mode 100644 index 0000000..3dbd60c --- /dev/null +++ b/src/test/resources/testPrograms/controlflow/ConditionalStatementComplex.monty @@ -0,0 +1,13 @@ +// Testing: ConditionalStatement +// +// The if-elif-else nesting should be converted into simple if-else +// statements. +// +// Expected output: 1 + +if false: + print(3) +elif false: + print(2) +else: + print(1) diff --git a/src/test/resources/testPrograms/controlflow/ConditionalStatementComplex.output b/src/test/resources/testPrograms/controlflow/ConditionalStatementComplex.output new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/src/test/resources/testPrograms/controlflow/ConditionalStatementComplex.output @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/src/test/resources/testPrograms/controlflow/ConditionalStatementFalse.monty b/src/test/resources/testPrograms/controlflow/ConditionalStatementFalse.monty new file mode 100644 index 0000000..f9b5777 --- /dev/null +++ b/src/test/resources/testPrograms/controlflow/ConditionalStatementFalse.monty @@ -0,0 +1,10 @@ +// Testing: ConditionalStatement +// +// The condition is false, so the print() shall never be called. +// +// Expected output: + +Bool value2 := false + +if value2: + print(0) diff --git a/src/test/resources/testPrograms/controlflow/ConditionalStatementFalse.output b/src/test/resources/testPrograms/controlflow/ConditionalStatementFalse.output new file mode 100644 index 0000000..e69de29 diff --git a/src/test/resources/testPrograms/controlflow/ConditionalStatementTrue.monty b/src/test/resources/testPrograms/controlflow/ConditionalStatementTrue.monty new file mode 100644 index 0000000..1457fbb --- /dev/null +++ b/src/test/resources/testPrograms/controlflow/ConditionalStatementTrue.monty @@ -0,0 +1,10 @@ +// Testing: ConditionalStatement +// +// The condition is true, so the print() must be called. +// +// Expected output: 1 + +Bool value := true + +if value: + print(1) diff --git a/src/test/resources/testPrograms/controlflow/ConditionalStatementTrue.output b/src/test/resources/testPrograms/controlflow/ConditionalStatementTrue.output new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/src/test/resources/testPrograms/controlflow/ConditionalStatementTrue.output @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/src/test/resources/testPrograms/controlflow/Ifelse1.monty b/src/test/resources/testPrograms/controlflow/Ifelse1.monty new file mode 100644 index 0000000..739aa45 --- /dev/null +++ b/src/test/resources/testPrograms/controlflow/Ifelse1.monty @@ -0,0 +1,19 @@ +// Testing: ConditionalStatement +// +// The if-elif-else nesting should be converted into simple if-else +// statements. +// +// Expected output: 2020 + +Int a := 20 + +if a = 10: + print(10) +else: + print(a) + +if a = 10: + print(10) +else: + if a = 20: + print(a) \ No newline at end of file diff --git a/src/test/resources/testPrograms/controlflow/Ifelse1.output b/src/test/resources/testPrograms/controlflow/Ifelse1.output new file mode 100644 index 0000000..145262f --- /dev/null +++ b/src/test/resources/testPrograms/controlflow/Ifelse1.output @@ -0,0 +1 @@ +2020 \ No newline at end of file diff --git a/src/test/resources/testPrograms/controlflow/Ifelse2.monty b/src/test/resources/testPrograms/controlflow/Ifelse2.monty new file mode 100644 index 0000000..af06176 --- /dev/null +++ b/src/test/resources/testPrograms/controlflow/Ifelse2.monty @@ -0,0 +1,33 @@ +// Testing: ConditionalStatement +// +// The if-elif-else nesting should be converted into simple if-else +// statements. +// +// Expected output: 2020 + +Int a := 20 + +if a = 10: + print(10) +else: + if a = 5: + print("no") + elif a = 20: + print(a) + else: + print("no") + +if a = 10: + print(10) +else: + if a = 5: + print("no") + elif a = 20: + if a = 5: + print("no") + elif a = 10: + print("no") + else: + print(a) + else: + print("no") \ No newline at end of file diff --git a/src/test/resources/testPrograms/controlflow/Ifelse2.output b/src/test/resources/testPrograms/controlflow/Ifelse2.output new file mode 100644 index 0000000..145262f --- /dev/null +++ b/src/test/resources/testPrograms/controlflow/Ifelse2.output @@ -0,0 +1 @@ +2020 \ No newline at end of file diff --git a/src/test/resources/testPrograms/controlflow/WhileLoopBreak1.monty b/src/test/resources/testPrograms/controlflow/WhileLoopBreak1.monty new file mode 100644 index 0000000..0070355 --- /dev/null +++ b/src/test/resources/testPrograms/controlflow/WhileLoopBreak1.monty @@ -0,0 +1,12 @@ +// Testing: WhileLoop with BreakStatement. +// +// The control-flow enters the loop-body, the break leaves it immediately so +// the print("Should not print") never gets called. +// +// Expected output: Ok + +while true: + break + print("Should not print") + +print("Ok") diff --git a/src/test/resources/testPrograms/controlflow/WhileLoopBreak1.output b/src/test/resources/testPrograms/controlflow/WhileLoopBreak1.output new file mode 100644 index 0000000..077fd65 --- /dev/null +++ b/src/test/resources/testPrograms/controlflow/WhileLoopBreak1.output @@ -0,0 +1 @@ +Ok \ No newline at end of file diff --git a/src/test/resources/testPrograms/controlflow/WhileLoopFalse.monty b/src/test/resources/testPrograms/controlflow/WhileLoopFalse.monty new file mode 100644 index 0000000..4b53c6e --- /dev/null +++ b/src/test/resources/testPrograms/controlflow/WhileLoopFalse.monty @@ -0,0 +1,11 @@ +// Testing: WhileLoop +// +// The control-flow never enters the loop-body so the print("Should not +// print") never gets called. +// +// Expected output: Ok + +while false: + print("Should not print") + +print("Ok") diff --git a/src/test/resources/testPrograms/controlflow/WhileLoopFalse.output b/src/test/resources/testPrograms/controlflow/WhileLoopFalse.output new file mode 100644 index 0000000..077fd65 --- /dev/null +++ b/src/test/resources/testPrograms/controlflow/WhileLoopFalse.output @@ -0,0 +1 @@ +Ok \ No newline at end of file diff --git a/src/test/resources/testPrograms/controlflow/WhileLoopSimple.monty b/src/test/resources/testPrograms/controlflow/WhileLoopSimple.monty new file mode 100644 index 0000000..d75f538 --- /dev/null +++ b/src/test/resources/testPrograms/controlflow/WhileLoopSimple.monty @@ -0,0 +1,13 @@ +// Testing: WhileLoop with simple expression. +// +// The loop-body gets executed while the condition is true. The condition +// should always load the variable for the evaluation of the expression. +// +// Expected output: 16 + +Int counter := 1 + +while counter < 15: + counter := counter * 2 + +print(counter) diff --git a/src/test/resources/testPrograms/controlflow/WhileLoopSimple.output b/src/test/resources/testPrograms/controlflow/WhileLoopSimple.output new file mode 100644 index 0000000..19c7bdb --- /dev/null +++ b/src/test/resources/testPrograms/controlflow/WhileLoopSimple.output @@ -0,0 +1 @@ +16 \ No newline at end of file diff --git a/src/test/resources/testPrograms/controlflow/WhileLoopSkip1.monty b/src/test/resources/testPrograms/controlflow/WhileLoopSkip1.monty new file mode 100644 index 0000000..57927a0 --- /dev/null +++ b/src/test/resources/testPrograms/controlflow/WhileLoopSkip1.monty @@ -0,0 +1,17 @@ +// Testing: WhileLoop with SkipStatement. +// +// The control-flow enters the loop-body, the skip jumpes back to the +// evaluation of the condition so the print("Should not print") never gets +// called. +// +// Expected output: Ok16 + +Int counter := 1 + +while counter < 15: + counter := counter * 2 + skip + print("Should not print") + +print("Ok") +print(counter) diff --git a/src/test/resources/testPrograms/controlflow/WhileLoopSkip1.output b/src/test/resources/testPrograms/controlflow/WhileLoopSkip1.output new file mode 100644 index 0000000..d0c9add --- /dev/null +++ b/src/test/resources/testPrograms/controlflow/WhileLoopSkip1.output @@ -0,0 +1 @@ +Ok16 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorAdd1.monty b/src/test/resources/testPrograms/expressions/BinaryOperatorAdd1.monty new file mode 100644 index 0000000..7534486 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorAdd1.monty @@ -0,0 +1,11 @@ +// Testing: The operator + on int. +// +// The result of an addition should be an int. +// +// Expected output: 54 + +Int b := 2+3 +print(b) +Int a := 3 +print(a+1) + diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorAdd1.output b/src/test/resources/testPrograms/expressions/BinaryOperatorAdd1.output new file mode 100644 index 0000000..43c451e --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorAdd1.output @@ -0,0 +1 @@ +54 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorAdd2.monty b/src/test/resources/testPrograms/expressions/BinaryOperatorAdd2.monty new file mode 100644 index 0000000..ec1a322 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorAdd2.monty @@ -0,0 +1,10 @@ +// Testing: The operator + on float. +// +// The result of an addition should be an float. +// +// Expected output: 3.15 + +Float b := 2.3+0.8 +print(b) +Float a := 4.25 +print(a+0.75) diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorAdd2.output b/src/test/resources/testPrograms/expressions/BinaryOperatorAdd2.output new file mode 100644 index 0000000..230693c --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorAdd2.output @@ -0,0 +1 @@ +3.15 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorAnd1.monty b/src/test/resources/testPrograms/expressions/BinaryOperatorAnd1.monty new file mode 100644 index 0000000..5413746 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorAnd1.monty @@ -0,0 +1,11 @@ +// Testing: The operator 'and' on bool. +// +// The result of an 'and' should be an bool. +// +// Expected output: 1000 + +Bool b := true and true +print(b) +print(true and false) +print(false and true) +print(false and false) diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorAnd1.output b/src/test/resources/testPrograms/expressions/BinaryOperatorAnd1.output new file mode 100644 index 0000000..e37d32a --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorAnd1.output @@ -0,0 +1 @@ +1000 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorDiv1.monty b/src/test/resources/testPrograms/expressions/BinaryOperatorDiv1.monty new file mode 100644 index 0000000..d665582 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorDiv1.monty @@ -0,0 +1,10 @@ +// Testing: The operator / on int. +// +// The result of a division should be an int. +// +// Expected output: 17 + +Int b := 3/2 +print(b) +Int a := 35 +print(a/5) diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorDiv1.output b/src/test/resources/testPrograms/expressions/BinaryOperatorDiv1.output new file mode 100644 index 0000000..8e2afd3 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorDiv1.output @@ -0,0 +1 @@ +17 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorDiv2.monty b/src/test/resources/testPrograms/expressions/BinaryOperatorDiv2.monty new file mode 100644 index 0000000..8f9d645 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorDiv2.monty @@ -0,0 +1,10 @@ +// Testing: The operator / on float. +// +// The result of a division should be an float. +// +// Expected output: 1.57 + +Float b := 3.0/2.0 +print(b) +Float a := 35.0 +print(a/5.0) diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorDiv2.output b/src/test/resources/testPrograms/expressions/BinaryOperatorDiv2.output new file mode 100644 index 0000000..aa6cc3f --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorDiv2.output @@ -0,0 +1 @@ +1.57 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorEquals1.monty b/src/test/resources/testPrograms/expressions/BinaryOperatorEquals1.monty new file mode 100644 index 0000000..a12030a --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorEquals1.monty @@ -0,0 +1,11 @@ +// Testing: The operator '=' on bool. +// +// The result of an '=' should be an bool. +// +// Expected output: 1001 + +Bool b := true = true +print(b) +print(true = false) +print(false = true) +print(false = false) diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorEquals1.output b/src/test/resources/testPrograms/expressions/BinaryOperatorEquals1.output new file mode 100644 index 0000000..7cebf7d --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorEquals1.output @@ -0,0 +1 @@ +1001 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorEquals2.monty b/src/test/resources/testPrograms/expressions/BinaryOperatorEquals2.monty new file mode 100644 index 0000000..0a2ec17 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorEquals2.monty @@ -0,0 +1,12 @@ +// Testing: The operator '=' on int. +// +// The result of an '=' should be an bool. +// +// Expected output: 101 + +Bool b := 20 = 20 +print(b) +print(3 = 4) +Int x := 5 +Int y := 5 +print(x=y) diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorEquals2.output b/src/test/resources/testPrograms/expressions/BinaryOperatorEquals2.output new file mode 100644 index 0000000..97a55e1 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorEquals2.output @@ -0,0 +1 @@ +101 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorEquals3.monty b/src/test/resources/testPrograms/expressions/BinaryOperatorEquals3.monty new file mode 100644 index 0000000..00c7eb5 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorEquals3.monty @@ -0,0 +1,13 @@ +// Testing: The operator '=' on float. +// +// The result of an '=' should be an bool. +// +// Expected output: 1110 + +Bool b := 20.0 = 20.0 +print(b) +print(3.3 = 3.3) +Float x := 8.125 +Float y := 8.125 +print(x=y) +print(x=8.124) diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorEquals3.output b/src/test/resources/testPrograms/expressions/BinaryOperatorEquals3.output new file mode 100644 index 0000000..96e38be --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorEquals3.output @@ -0,0 +1 @@ +1110 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorEqualsNot1.monty b/src/test/resources/testPrograms/expressions/BinaryOperatorEqualsNot1.monty new file mode 100644 index 0000000..8db72bd --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorEqualsNot1.monty @@ -0,0 +1,11 @@ +// Testing: The operator '!=' on bool. +// +// The result of an '!=' should be an bool. +// +// Expected output: 0110 + +Bool b := true != true +print(b) +print(true != false) +print(false != true) +print(false != false) diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorEqualsNot1.output b/src/test/resources/testPrograms/expressions/BinaryOperatorEqualsNot1.output new file mode 100644 index 0000000..f4396d0 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorEqualsNot1.output @@ -0,0 +1 @@ +0110 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorEqualsNot2.monty b/src/test/resources/testPrograms/expressions/BinaryOperatorEqualsNot2.monty new file mode 100644 index 0000000..6f4f111 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorEqualsNot2.monty @@ -0,0 +1,11 @@ +// Testing: The operator '!=' on int. +// +// The result of an '!=' should be an bool. +// +// Expected output: 1010 + +Bool b := 51 != 21 +print(b) +print(10 != 10) +print(-10 != 30) +print(-18 != -18) diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorEqualsNot2.output b/src/test/resources/testPrograms/expressions/BinaryOperatorEqualsNot2.output new file mode 100644 index 0000000..028ead5 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorEqualsNot2.output @@ -0,0 +1 @@ +1010 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorEqualsNot3.monty b/src/test/resources/testPrograms/expressions/BinaryOperatorEqualsNot3.monty new file mode 100644 index 0000000..091dbf6 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorEqualsNot3.monty @@ -0,0 +1,13 @@ +// Testing: The operator '!=' on float. +// +// The result of an '!=' should be an bool. +// +// Expected output: 0001 + +Bool b := 20.0 != 20.0 +print(b) +print(3.3 != 3.3) +Float x := 8.125 +Float y := 8.125 +print(x != y) +print(x != 8.124) diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorEqualsNot3.output b/src/test/resources/testPrograms/expressions/BinaryOperatorEqualsNot3.output new file mode 100644 index 0000000..741d32c --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorEqualsNot3.output @@ -0,0 +1 @@ +0001 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorGreater1.monty b/src/test/resources/testPrograms/expressions/BinaryOperatorGreater1.monty new file mode 100644 index 0000000..bf4e238 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorGreater1.monty @@ -0,0 +1,9 @@ +// Testing: The operator > on int. +// +// The result of a comparison should be a bool. +// +// Expected output: 01 + +print(2>3) +Int a := 3 +print(a>1) diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorGreater1.output b/src/test/resources/testPrograms/expressions/BinaryOperatorGreater1.output new file mode 100644 index 0000000..a616ad4 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorGreater1.output @@ -0,0 +1 @@ +01 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorGreater2.monty b/src/test/resources/testPrograms/expressions/BinaryOperatorGreater2.monty new file mode 100644 index 0000000..fdf8e4f --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorGreater2.monty @@ -0,0 +1,10 @@ +// Testing: The operator > on float. +// +// The result of a comparison should be a bool. +// +// Expected output: 001 + +print(2.0>3.0) +Float a := 4.9 +print(a>5.0) +print(3.0 > -2.3) diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorGreater2.output b/src/test/resources/testPrograms/expressions/BinaryOperatorGreater2.output new file mode 100644 index 0000000..0f30166 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorGreater2.output @@ -0,0 +1 @@ +001 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorGreaterEqual1.monty b/src/test/resources/testPrograms/expressions/BinaryOperatorGreaterEqual1.monty new file mode 100644 index 0000000..9c938f6 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorGreaterEqual1.monty @@ -0,0 +1,9 @@ +// Testing: The operator >= on int. +// +// The result of a comparison should be a bool. +// +// Expected output: 11 + +print(3>=2) +Int a := 3 +print(a>=3) diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorGreaterEqual1.output b/src/test/resources/testPrograms/expressions/BinaryOperatorGreaterEqual1.output new file mode 100644 index 0000000..9d60796 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorGreaterEqual1.output @@ -0,0 +1 @@ +11 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorGreaterEqual2.monty b/src/test/resources/testPrograms/expressions/BinaryOperatorGreaterEqual2.monty new file mode 100644 index 0000000..34e1099 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorGreaterEqual2.monty @@ -0,0 +1,9 @@ +// Testing: The operator >= on float. +// +// The result of a comparison should be a bool. +// +// Expected output: 11 + +print(3.3>=1.0) +Float a := 3.789 +print(a>=3.789) diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorGreaterEqual2.output b/src/test/resources/testPrograms/expressions/BinaryOperatorGreaterEqual2.output new file mode 100644 index 0000000..9d60796 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorGreaterEqual2.output @@ -0,0 +1 @@ +11 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorLess1.monty b/src/test/resources/testPrograms/expressions/BinaryOperatorLess1.monty new file mode 100644 index 0000000..33132d4 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorLess1.monty @@ -0,0 +1,9 @@ +// Testing: The operator < on int. +// +// The result of a comparison should be a bool. +// +// Expected output: 10 + +print(2<3) +Int a := 3 +print(a<1) diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorLess1.output b/src/test/resources/testPrograms/expressions/BinaryOperatorLess1.output new file mode 100644 index 0000000..9a03714 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorLess1.output @@ -0,0 +1 @@ +10 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorLess2.monty b/src/test/resources/testPrograms/expressions/BinaryOperatorLess2.monty new file mode 100644 index 0000000..aa7e194 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorLess2.monty @@ -0,0 +1,10 @@ +// Testing: The operator < on float. +// +// The result of a comparison should be a bool. +// +// Expected output: 110 + +print(2.0<3.0) +Float a := 4.9 +print(a<5.0) +print(3.0 < -2.3) diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorLess2.output b/src/test/resources/testPrograms/expressions/BinaryOperatorLess2.output new file mode 100644 index 0000000..97e3504 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorLess2.output @@ -0,0 +1 @@ +110 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorLessEqual1.monty b/src/test/resources/testPrograms/expressions/BinaryOperatorLessEqual1.monty new file mode 100644 index 0000000..5f44c5e --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorLessEqual1.monty @@ -0,0 +1,9 @@ +// Testing: The operator <= on int. +// +// The result of a comparison should be a bool. +// +// Expected output: 11 + +print(2<=3) +Int a := 3 +print(a<=3) diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorLessEqual1.output b/src/test/resources/testPrograms/expressions/BinaryOperatorLessEqual1.output new file mode 100644 index 0000000..9d60796 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorLessEqual1.output @@ -0,0 +1 @@ +11 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorLessEqual2.monty b/src/test/resources/testPrograms/expressions/BinaryOperatorLessEqual2.monty new file mode 100644 index 0000000..af4ef28 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorLessEqual2.monty @@ -0,0 +1,9 @@ +// Testing: The operator <= on float. +// +// The result of a comparison should be a bool. +// +// Expected output: 11 + +print(2.0<=3.3) +Float a := 3.789 +print(a<=3.789) diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorLessEqual2.output b/src/test/resources/testPrograms/expressions/BinaryOperatorLessEqual2.output new file mode 100644 index 0000000..9d60796 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorLessEqual2.output @@ -0,0 +1 @@ +11 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorModulo1.monty b/src/test/resources/testPrograms/expressions/BinaryOperatorModulo1.monty new file mode 100644 index 0000000..1c0b61a --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorModulo1.monty @@ -0,0 +1,11 @@ +// Testing: The operator '%' on int. +// +// The result of an '%' should be an int. +// +// Expected output: 1038 + +Int b := 10 % 3 +print(b) +print(9000 % 5) +print(47 % 4) +print(8 % 10) diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorModulo1.output b/src/test/resources/testPrograms/expressions/BinaryOperatorModulo1.output new file mode 100644 index 0000000..0f746c7 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorModulo1.output @@ -0,0 +1 @@ +1038 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorMul1.monty b/src/test/resources/testPrograms/expressions/BinaryOperatorMul1.monty new file mode 100644 index 0000000..2500cbf --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorMul1.monty @@ -0,0 +1,11 @@ +// Testing: The operator * on int. +// +// The result of an multiplication should be an int. +// +// Expected output: 63 + +Int b := 2*3 +print(b) + +Int a := 3 +print(a*1) diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorMul1.output b/src/test/resources/testPrograms/expressions/BinaryOperatorMul1.output new file mode 100644 index 0000000..4e9e288 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorMul1.output @@ -0,0 +1 @@ +63 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorMul2.monty b/src/test/resources/testPrograms/expressions/BinaryOperatorMul2.monty new file mode 100644 index 0000000..126608b --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorMul2.monty @@ -0,0 +1,11 @@ +// Testing: The operator * on float. +// +// The result of an multiplication should be an int. +// +// Expected output: 53.75 + +Float b := 2.5*2.0 +print(b) + +Float a := 1.25 +print(a*3.0) diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorMul2.output b/src/test/resources/testPrograms/expressions/BinaryOperatorMul2.output new file mode 100644 index 0000000..975e6b8 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorMul2.output @@ -0,0 +1 @@ +53.75 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorOr1.monty b/src/test/resources/testPrograms/expressions/BinaryOperatorOr1.monty new file mode 100644 index 0000000..ab271e8 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorOr1.monty @@ -0,0 +1,11 @@ +// Testing: The operator 'or' on bool. +// +// The result of an 'or' should be an bool. +// +// Expected output: 1101 + +Bool b := true or false +print(b) +print(false or true) +print(false or false) +print(true or true) diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorOr1.output b/src/test/resources/testPrograms/expressions/BinaryOperatorOr1.output new file mode 100644 index 0000000..1ea87ef --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorOr1.output @@ -0,0 +1 @@ +1101 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorSub1.monty b/src/test/resources/testPrograms/expressions/BinaryOperatorSub1.monty new file mode 100644 index 0000000..3fdcd76 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorSub1.monty @@ -0,0 +1,10 @@ +// Testing: The operator - on int. +// +// The result of an subtraction should be an int. +// +// Expected output: -51 + +Int b := 3-8 +print(b) +Int a := -1 +print(a+2) \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorSub1.output b/src/test/resources/testPrograms/expressions/BinaryOperatorSub1.output new file mode 100644 index 0000000..f33fb37 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorSub1.output @@ -0,0 +1 @@ +-51 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorSub2.monty b/src/test/resources/testPrograms/expressions/BinaryOperatorSub2.monty new file mode 100644 index 0000000..edbb805 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorSub2.monty @@ -0,0 +1,10 @@ +// Testing: The operator - on float. +// +// The result of an subtraction should be an float. +// +// Expected output: 3-7.275 + +Float b := 3.5-0.5 +print(b) +Float a := 2.725 +print(a-10.0) \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorSub2.output b/src/test/resources/testPrograms/expressions/BinaryOperatorSub2.output new file mode 100644 index 0000000..f52d3b2 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorSub2.output @@ -0,0 +1 @@ +3-7.275 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorXor1.monty b/src/test/resources/testPrograms/expressions/BinaryOperatorXor1.monty new file mode 100644 index 0000000..31e3418 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorXor1.monty @@ -0,0 +1,11 @@ +// Testing: The operator 'xor' on bool. +// +// The result of an 'xor' should be an bool. +// +// Expected output: 0110 + +Bool b := false xor false +print(b) +print(false xor true) +print(true xor false) +print(true xor true) diff --git a/src/test/resources/testPrograms/expressions/BinaryOperatorXor1.output b/src/test/resources/testPrograms/expressions/BinaryOperatorXor1.output new file mode 100644 index 0000000..f4396d0 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/BinaryOperatorXor1.output @@ -0,0 +1 @@ +0110 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/ConditionalExpressionComplex.monty b/src/test/resources/testPrograms/expressions/ConditionalExpressionComplex.monty new file mode 100644 index 0000000..99c4aa9 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/ConditionalExpressionComplex.monty @@ -0,0 +1,27 @@ +// Testing: ConditionalExpression with functions with side effects. +// +// The function dontPrint() should never be called, function doPrint() two +// times. +// +// Expected output: OkOkOk + +Bool functionTrue(): + return true + +Bool functionFalse(): + return false + +String dontPrint(): + print("Nope") + return "Nope" + +String doPrint(): + print("Ok") + return "Ok" + +output(): + String var1 := doPrint() if functionTrue() else dontPrint() + String var2 := dontPrint() if functionFalse() else doPrint() + print(var1 if true else var2) + +output() diff --git a/src/test/resources/testPrograms/expressions/ConditionalExpressionComplex.output b/src/test/resources/testPrograms/expressions/ConditionalExpressionComplex.output new file mode 100644 index 0000000..9d604ae --- /dev/null +++ b/src/test/resources/testPrograms/expressions/ConditionalExpressionComplex.output @@ -0,0 +1 @@ +OkOkOk \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/ConditionalExpressionFalse1.monty b/src/test/resources/testPrograms/expressions/ConditionalExpressionFalse1.monty new file mode 100644 index 0000000..ba74504 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/ConditionalExpressionFalse1.monty @@ -0,0 +1,7 @@ +// Testing: ConditionalExpression with simple expressions. +// +// The condition is false, so the else part should be returned. +// +// Expected output: 24 + +print(42 if false else 24) diff --git a/src/test/resources/testPrograms/expressions/ConditionalExpressionFalse1.output b/src/test/resources/testPrograms/expressions/ConditionalExpressionFalse1.output new file mode 100644 index 0000000..cabf43b --- /dev/null +++ b/src/test/resources/testPrograms/expressions/ConditionalExpressionFalse1.output @@ -0,0 +1 @@ +24 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/ConditionalExpressionFalse2.monty b/src/test/resources/testPrograms/expressions/ConditionalExpressionFalse2.monty new file mode 100644 index 0000000..9acd37e --- /dev/null +++ b/src/test/resources/testPrograms/expressions/ConditionalExpressionFalse2.monty @@ -0,0 +1,9 @@ +// Testing: ConditionalExpression with variable accesses as expressions. +// +// The condition is false, so the else part should be returned. +// +// Expected output: Welt + +String hallo := "Hallo" +String welt := "Welt" +print(hallo if 5 < 4 else welt) diff --git a/src/test/resources/testPrograms/expressions/ConditionalExpressionFalse2.output b/src/test/resources/testPrograms/expressions/ConditionalExpressionFalse2.output new file mode 100644 index 0000000..934937a --- /dev/null +++ b/src/test/resources/testPrograms/expressions/ConditionalExpressionFalse2.output @@ -0,0 +1 @@ +Welt \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/ConditionalExpressionFalse3.monty b/src/test/resources/testPrograms/expressions/ConditionalExpressionFalse3.monty new file mode 100644 index 0000000..a5d1860 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/ConditionalExpressionFalse3.monty @@ -0,0 +1,9 @@ +// Testing: ConditionalExpression with complex expressions. +// +// The condition is false, so the else part should be returned. +// +// Expected output: 42 + +Int a := 12 +Int b := 21 +print((a * 2) if false else (b * 2)) diff --git a/src/test/resources/testPrograms/expressions/ConditionalExpressionFalse3.output b/src/test/resources/testPrograms/expressions/ConditionalExpressionFalse3.output new file mode 100644 index 0000000..f70d7bb --- /dev/null +++ b/src/test/resources/testPrograms/expressions/ConditionalExpressionFalse3.output @@ -0,0 +1 @@ +42 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/ConditionalExpressionTrue1.monty b/src/test/resources/testPrograms/expressions/ConditionalExpressionTrue1.monty new file mode 100644 index 0000000..0b8dac1 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/ConditionalExpressionTrue1.monty @@ -0,0 +1,7 @@ +// Testing: ConditionalExpression with simple expressions. +// +// The condition is true, so the first part should be returned. +// +// Expected output: 42 + +print(42 if true else 24) diff --git a/src/test/resources/testPrograms/expressions/ConditionalExpressionTrue1.output b/src/test/resources/testPrograms/expressions/ConditionalExpressionTrue1.output new file mode 100644 index 0000000..f70d7bb --- /dev/null +++ b/src/test/resources/testPrograms/expressions/ConditionalExpressionTrue1.output @@ -0,0 +1 @@ +42 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/ConditionalExpressionTrue2.monty b/src/test/resources/testPrograms/expressions/ConditionalExpressionTrue2.monty new file mode 100644 index 0000000..7fca568 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/ConditionalExpressionTrue2.monty @@ -0,0 +1,9 @@ +// Testing: ConditionalExpression with variable accesses as expressions. +// +// The condition is true, so the first part should be returned. +// +// Expected output: Hallo + +String hallo := "Hallo" +String welt := "Welt" +print(hallo if 3 < 4 else welt) diff --git a/src/test/resources/testPrograms/expressions/ConditionalExpressionTrue2.output b/src/test/resources/testPrograms/expressions/ConditionalExpressionTrue2.output new file mode 100644 index 0000000..53f5007 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/ConditionalExpressionTrue2.output @@ -0,0 +1 @@ +Hallo \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/ConditionalExpressionTrue3.monty b/src/test/resources/testPrograms/expressions/ConditionalExpressionTrue3.monty new file mode 100644 index 0000000..93ee8ca --- /dev/null +++ b/src/test/resources/testPrograms/expressions/ConditionalExpressionTrue3.monty @@ -0,0 +1,9 @@ +// Testing: ConditionalExpression with complex expressions. +// +// The condition is true, so the first part should be returned. +// +// Expected output: 24 + +Int a := 12 +Int b := 21 +print((a * 2) if true else (b * 2)) diff --git a/src/test/resources/testPrograms/expressions/ConditionalExpressionTrue3.output b/src/test/resources/testPrograms/expressions/ConditionalExpressionTrue3.output new file mode 100644 index 0000000..cabf43b --- /dev/null +++ b/src/test/resources/testPrograms/expressions/ConditionalExpressionTrue3.output @@ -0,0 +1 @@ +24 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/SelfDefinedOperators.monty b/src/test/resources/testPrograms/expressions/SelfDefinedOperators.monty new file mode 100644 index 0000000..15e4a4c --- /dev/null +++ b/src/test/resources/testPrograms/expressions/SelfDefinedOperators.monty @@ -0,0 +1,93 @@ +// Testing: User defined operators. +// +// The user must be able to define operators on some class. +// +// Expected output: operator_unary-operator+operator-operator*operator/ +// operator%operatoroperator<=operator>=operator= +// operator!=operator_notoperator_xoroperator_andoperator_or + +class SomeClass: + + SomeClass operator-(): + print("operator_unary-") + return self + + + SomeClass operator+(SomeClass other): + print("operator+") + return self + + + SomeClass operator-(SomeClass other): + print("operator-") + return self + + + SomeClass operator*(SomeClass other): + print("operator*") + return self + + + SomeClass operator/(SomeClass other): + print("operator/") + return self + + + SomeClass operator%(SomeClass other): + print("operator%") + return self + + + SomeClass operator<(SomeClass other): + print("operator<") + return self + + + SomeClass operator>(SomeClass other): + print("operator>") + return self + + + SomeClass operator<=(SomeClass other): + print("operator<=") + return self + + + SomeClass operator>=(SomeClass other): + print("operator>=") + return self + + + SomeClass operator=(SomeClass other): + print("operator=") + return self + + + SomeClass operator!=(SomeClass other): + print("operator!=") + return self + + + SomeClass operator_not(): + print("operator_not") + return self + + + SomeClass operator_xor(SomeClass other): + print("operator_xor") + return self + + + SomeClass operator_and(SomeClass other): + print("operator_and") + return self + + + SomeClass operator_or(SomeClass other): + print("operator_or") + return self + +SomeClass foo := SomeClass() +SomeClass bar := SomeClass() +SomeClass result := SomeClass() + +result := -bar +result := foo + bar +result := foo - bar +result := foo * bar +result := foo / bar +result := foo % bar +result := foo < bar +result := foo > bar +result := foo <= bar +result := foo >= bar +result := foo = bar +result := foo != bar +result := not bar +result := foo xor bar +result := foo and bar +result := foo or bar diff --git a/src/test/resources/testPrograms/expressions/SelfDefinedOperators.output b/src/test/resources/testPrograms/expressions/SelfDefinedOperators.output new file mode 100644 index 0000000..eb7d66a --- /dev/null +++ b/src/test/resources/testPrograms/expressions/SelfDefinedOperators.output @@ -0,0 +1 @@ +operator_unary-operator+operator-operator*operator/operator%operatoroperator<=operator>=operator=operator!=operator_notoperator_xoroperator_andoperator_or \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/UnaryOperatorMinus1.monty b/src/test/resources/testPrograms/expressions/UnaryOperatorMinus1.monty new file mode 100644 index 0000000..be21bcf --- /dev/null +++ b/src/test/resources/testPrograms/expressions/UnaryOperatorMinus1.monty @@ -0,0 +1,11 @@ +// Testing: The unary operator '-" on Int. +// +// The expression should be negated. +// +// Expected output: -5510 + +Int a := -5 +print(a) +print(-a) +Int b := -(-10) +print(b) \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/UnaryOperatorMinus1.output b/src/test/resources/testPrograms/expressions/UnaryOperatorMinus1.output new file mode 100644 index 0000000..86fb0c4 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/UnaryOperatorMinus1.output @@ -0,0 +1 @@ +-5510 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/UnaryOperatorMinus2.monty b/src/test/resources/testPrograms/expressions/UnaryOperatorMinus2.monty new file mode 100644 index 0000000..dd99d9a --- /dev/null +++ b/src/test/resources/testPrograms/expressions/UnaryOperatorMinus2.monty @@ -0,0 +1,11 @@ +// Testing: The unary operator '-" on Float. +// +// The expression should be negated. +// +// Expected output: -1.751.7512.34 + +Float a := -1.75 +print(a) +print(-a) +Float b := -(-12.34) +print(b) \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/UnaryOperatorMinus2.output b/src/test/resources/testPrograms/expressions/UnaryOperatorMinus2.output new file mode 100644 index 0000000..2dca2c9 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/UnaryOperatorMinus2.output @@ -0,0 +1 @@ +-1.751.7512.34 \ No newline at end of file diff --git a/src/test/resources/testPrograms/expressions/UnaryOperatorNot1.monty b/src/test/resources/testPrograms/expressions/UnaryOperatorNot1.monty new file mode 100644 index 0000000..1dfa210 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/UnaryOperatorNot1.monty @@ -0,0 +1,8 @@ +// Testing: UnaryExpression. +// +// The expression should be negated. +// +// Expected output: 10 + +print(not false) +print(not true) diff --git a/src/test/resources/testPrograms/expressions/UnaryOperatorNot1.output b/src/test/resources/testPrograms/expressions/UnaryOperatorNot1.output new file mode 100644 index 0000000..9a03714 --- /dev/null +++ b/src/test/resources/testPrograms/expressions/UnaryOperatorNot1.output @@ -0,0 +1 @@ +10 \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/casting/ClassInheritedCast1.monty b/src/test/resources/testPrograms/inheritance/casting/ClassInheritedCast1.monty new file mode 100644 index 0000000..b808c7f --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/casting/ClassInheritedCast1.monty @@ -0,0 +1,20 @@ +// Testing: ClassDeclaration with single inheritance and casting. +// +// The compiler must cast the expression and call the right method. +// +// Expected output: Ok + +class Ab: + + initializer(): + pass + +class Ba inherits Ab: + + initializer(): + pass + + + methodB(): + print("Ok") + +Ab a := Ba() +Ba b := a as Ba +b.methodB() diff --git a/src/test/resources/testPrograms/inheritance/casting/ClassInheritedCast1.output b/src/test/resources/testPrograms/inheritance/casting/ClassInheritedCast1.output new file mode 100644 index 0000000..077fd65 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/casting/ClassInheritedCast1.output @@ -0,0 +1 @@ +Ok \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/casting/ClassInheritedCast2.error b/src/test/resources/testPrograms/inheritance/casting/ClassInheritedCast2.error new file mode 100644 index 0000000..e69de29 diff --git a/src/test/resources/testPrograms/inheritance/casting/ClassInheritedCast2.monty b/src/test/resources/testPrograms/inheritance/casting/ClassInheritedCast2.monty new file mode 100644 index 0000000..e0a4b10 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/casting/ClassInheritedCast2.monty @@ -0,0 +1,21 @@ +// Testing: ClassDeclaration with single inheritance and casting. +// +// The program must fail casting the expression as the expression was never an +// instance of B. The program fails before printing. +// +// Expected output: + +class Ab: + + initializer(): + pass + +class Ba inherits Ab: + + initializer(): + pass + + + methodB(): + print("Nope") + +Ab a := Ab() +Ba b := a as Ba +b.methodB() diff --git a/src/test/resources/testPrograms/inheritance/casting/ClassInheritedUpcast1.monty b/src/test/resources/testPrograms/inheritance/casting/ClassInheritedUpcast1.monty new file mode 100644 index 0000000..c265ebb --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/casting/ClassInheritedUpcast1.monty @@ -0,0 +1,21 @@ +// Testing: ClassDeclaration with single inheritance and upcasting. +// +// The compiler must upcast automatically at an assignment. +// +// Expected output: 1 + +class Ab: + + initializer(Bool value): + self.attr := value + + + Bool attr + + + printIt(): + print(self.attr) + +class Ba inherits Ab: + + initializer(): + parent(Ab).initializer(true) + +Ab b := Ba() +b.printIt() diff --git a/src/test/resources/testPrograms/inheritance/casting/ClassInheritedUpcast1.output b/src/test/resources/testPrograms/inheritance/casting/ClassInheritedUpcast1.output new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/casting/ClassInheritedUpcast1.output @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/casting/ClassInheritedUpcast2.monty b/src/test/resources/testPrograms/inheritance/casting/ClassInheritedUpcast2.monty new file mode 100644 index 0000000..ac133e0 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/casting/ClassInheritedUpcast2.monty @@ -0,0 +1,24 @@ +// Testing: ClassDeclaration with single inheritance and upcasting. +// +// The compiler must upcast automatically at a function call. +// +// Expected output: 1 + +class Ab: + + initializer(Bool value): + self.attr := value + + + Bool attr + + + printIt(): + print(self.attr) + +class Ba inherits Ab: + + initializer(): + parent(Ab).initializer(true) + +printIt(Ab a): + a.printIt() + +Ba b := Ba() +printIt(b) diff --git a/src/test/resources/testPrograms/inheritance/casting/ClassInheritedUpcast2.output b/src/test/resources/testPrograms/inheritance/casting/ClassInheritedUpcast2.output new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/casting/ClassInheritedUpcast2.output @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/casting/ClassInheritedUpcast3.monty b/src/test/resources/testPrograms/inheritance/casting/ClassInheritedUpcast3.monty new file mode 100644 index 0000000..840bf4e --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/casting/ClassInheritedUpcast3.monty @@ -0,0 +1,25 @@ +// Testing: ClassDeclaration with single inheritance and upcasting. +// +// The compiler must upcast automatically at a return statement. +// +// Expected output: 1 + +class Ab: + + initializer(Bool value): + self.attr := value + + + Bool attr + + + printIt(): + print(self.attr) + +class Ba inherits Ab: + + initializer(): + parent(Ab).initializer(true) + +Ab createIt(): + Ba b := Ba() + return b + +Ab b := createIt() +b.printIt() diff --git a/src/test/resources/testPrograms/inheritance/casting/ClassInheritedUpcast3.output b/src/test/resources/testPrograms/inheritance/casting/ClassInheritedUpcast3.output new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/casting/ClassInheritedUpcast3.output @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance1.monty b/src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance1.monty new file mode 100644 index 0000000..6a2b87a --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance1.monty @@ -0,0 +1,17 @@ +// Testing: ClassDeclaration +// +// The simple initializer call of an inherited class must work. +// +// Expected output: Hi + +class Ab: + + String someAttr + + + initializer(): + print("Hi") + +class Ba inherits Ab: + + initializer(): + parent(Ab).initializer() + +Ba x := Ba() diff --git a/src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance1.output b/src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance1.output new file mode 100644 index 0000000..40816a2 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance1.output @@ -0,0 +1 @@ +Hi \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance2.monty b/src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance2.monty new file mode 100644 index 0000000..0c7d11e --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance2.monty @@ -0,0 +1,16 @@ +// Testing: ClassDeclaration +// +// The simple initializer call of an inherited class with a parameter must +// work. +// +// Expected output: HALLO + +class Ab: + + initializer(String a): + print(a) + +class Ba inherits Ab: + + initializer(String a): + parent(Ab).initializer(a) + +Ba x := Ba("HALLO") diff --git a/src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance2.output b/src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance2.output new file mode 100644 index 0000000..d3327f7 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance2.output @@ -0,0 +1 @@ +HALLO \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance3.monty b/src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance3.monty new file mode 100644 index 0000000..a76bfd8 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance3.monty @@ -0,0 +1,17 @@ +// Testing: ClassDeclaration +// +// The simple initializer call of an inherited class with a variable as +// parameter must work. +// +// Expected output: HALLO + +class Ab: + + initializer(String a): + print(a) + +class Ba inherits Ab: + + initializer(String a): + parent(Ab).initializer(a) + +String hallo := "HALLO" +Ba x := Ba(hallo) diff --git a/src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance3.output b/src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance3.output new file mode 100644 index 0000000..d3327f7 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance3.output @@ -0,0 +1 @@ +HALLO \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance4.monty b/src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance4.monty new file mode 100644 index 0000000..eeb9992 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance4.monty @@ -0,0 +1,19 @@ +// Testing: ClassDeclaration +// +// The simple initializer call of an inherited class with a variable as +// parameter and an assignment to an attribute must work. +// +// Expected output: HALLO + +class Ab: + + String someAttr + + + initializer(String a): + self.someAttr := a + +class Ba inherits Ab: + + initializer(String a): + parent(Ab).initializer(a) + +Ba x := Ba("HALLO") +print(x.someAttr) diff --git a/src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance4.output b/src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance4.output new file mode 100644 index 0000000..d3327f7 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/constructor/ConstructorInheritance4.output @@ -0,0 +1 @@ +HALLO \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/is/ClassInheritedIs1.monty b/src/test/resources/testPrograms/inheritance/is/ClassInheritedIs1.monty new file mode 100644 index 0000000..0da4b63 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/is/ClassInheritedIs1.monty @@ -0,0 +1,15 @@ +// Testing: ClassDeclaration with single inheritance and inheritance check. +// +// The type-check of an instance of A bound to a variable of type A must be +// true. +// +// Expected output: Ok + +class Ab: + pass + +Ab a := Ab() +if (a is Ab): + print("Ok") +else: + print("No") diff --git a/src/test/resources/testPrograms/inheritance/is/ClassInheritedIs1.output b/src/test/resources/testPrograms/inheritance/is/ClassInheritedIs1.output new file mode 100644 index 0000000..077fd65 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/is/ClassInheritedIs1.output @@ -0,0 +1 @@ +Ok \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/is/ClassInheritedIs2.monty b/src/test/resources/testPrograms/inheritance/is/ClassInheritedIs2.monty new file mode 100644 index 0000000..61a6dce --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/is/ClassInheritedIs2.monty @@ -0,0 +1,18 @@ +// Testing: ClassDeclaration with single inheritance and inheritance check. +// +// The type-check of an instance of B bound to a variable of type A must be +// true as B inherits A. +// +// Expected output: Ok + +class Ab: + pass + +class Ba inherits Ab: + pass + +Ab a := Ba() +if (a is Ba): + print("Ok") +else: + print("No") diff --git a/src/test/resources/testPrograms/inheritance/is/ClassInheritedIs2.output b/src/test/resources/testPrograms/inheritance/is/ClassInheritedIs2.output new file mode 100644 index 0000000..077fd65 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/is/ClassInheritedIs2.output @@ -0,0 +1 @@ +Ok \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/is/ClassInheritedIs3.monty b/src/test/resources/testPrograms/inheritance/is/ClassInheritedIs3.monty new file mode 100644 index 0000000..cea3b6e --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/is/ClassInheritedIs3.monty @@ -0,0 +1,18 @@ +// Testing: ClassDeclaration with single inheritance and inheritance check. +// +// The type-check of an instance of B bound to a variable of type A must be +// false. +// +// Expected output: Ok + +class Ab: + pass + +class Ba: + pass + +Ab a := Ab() +if (a is Ba): + print("No") +else: + print("Ok") diff --git a/src/test/resources/testPrograms/inheritance/is/ClassInheritedIs3.output b/src/test/resources/testPrograms/inheritance/is/ClassInheritedIs3.output new file mode 100644 index 0000000..077fd65 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/is/ClassInheritedIs3.output @@ -0,0 +1 @@ +Ok \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool1.monty b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool1.monty new file mode 100644 index 0000000..5ccc12c --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool1.monty @@ -0,0 +1,19 @@ +// Testing: VariableDeclaration in ClassDeclaration with single inheritance. +// +// The boolean inherited attribute is written and printed. The access via self +// must work. +// +// Expected output: 1 + +class Ab: + + initializer(): + self.attr := true + + + Bool attr + +class Ba inherits Ab: + + initializer(): + parent(Ab).initializer() + print(self.attr) + +Ba b := Ba() diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool1.output b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool1.output new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool1.output @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool2.monty b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool2.monty new file mode 100644 index 0000000..b84f692 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool2.monty @@ -0,0 +1,19 @@ +// Testing: VariableDeclaration in ClassDeclaration with single inheritance. +// +// The boolean inherited attribute is written and printed from outside the +// class. The access via self and the member access must work. +// +// Expected output: 1 + +class Ab: + + initializer(): + self.attr := true + + + Bool attr + +class Ba inherits Ab: + + initializer(): + parent(Ab).initializer() + +Ba b := Ba() +print(b.attr) diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool2.output b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool2.output new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool2.output @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool3.monty b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool3.monty new file mode 100644 index 0000000..d6e8c86 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool3.monty @@ -0,0 +1,21 @@ +// Testing: VariableDeclaration in ClassDeclaration with single inheritance. +// +// A boolean inherited attribute and a local variable exist with the same +// name. Both must be writable and readable. +// +// Expected output: 10 + +class Ab: + + initializer(): + self.attr := true + + + Bool attr + +class Ba inherits Ab: + + initializer(): + parent(Ab).initializer() + Bool attr := false + print(self.attr) + print(attr) + +Ba b := Ba() diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool3.output b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool3.output new file mode 100644 index 0000000..9a03714 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool3.output @@ -0,0 +1 @@ +10 \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool4.monty b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool4.monty new file mode 100644 index 0000000..3afe1ab --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool4.monty @@ -0,0 +1,20 @@ +// Testing: VariableDeclaration in ClassDeclaration with single inheritance. +// +// The boolean inherited attribute is written and a copy printed. The access +// via self must work. +// +// Expected output: 1 + +class Ab: + + initializer(): + self.attr := true + + + Bool attr + +class Ba inherits Ab: + + initializer(): + parent(Ab).initializer() + Bool copy := self.attr + print(copy) + +Ba b := Ba() diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool4.output b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool4.output new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberBool4.output @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar1.monty b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar1.monty new file mode 100644 index 0000000..06d6f98 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar1.monty @@ -0,0 +1,19 @@ +// Testing: VariableDeclaration in ClassDeclaration with single inheritance. +// +// The char inherited attribute is written and printed. The access via self +// must work. +// +// Expected output: M + +class Ab: + + initializer(): + self.attr := 'M' + + + Char attr + +class Ba inherits Ab: + + initializer(): + parent(Ab).initializer() + print(self.attr) + +Ba b := Ba() diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar1.output b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar1.output new file mode 100644 index 0000000..ef6bce1 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar1.output @@ -0,0 +1 @@ +M \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar2.monty b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar2.monty new file mode 100644 index 0000000..df44695 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar2.monty @@ -0,0 +1,19 @@ +// Testing: VariableDeclaration in ClassDeclaration with single inheritance. +// +// The char inherited attribute is written and printed from outside the +// class. The access via self and the member access must work. +// +// Expected output: M + +class Ab: + + initializer(): + self.attr := 'M' + + + Char attr + +class Ba inherits Ab: + + initializer(): + parent(Ab).initializer() + +Ba b := Ba() +print(b.attr) diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar2.output b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar2.output new file mode 100644 index 0000000..ef6bce1 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar2.output @@ -0,0 +1 @@ +M \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar3.monty b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar3.monty new file mode 100644 index 0000000..9bab333 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar3.monty @@ -0,0 +1,21 @@ +// Testing: VariableDeclaration in ClassDeclaration with single inheritance. +// +// A boolean inherited attribute and a local variable exist with the same +// name. Both must be writable and readable. +// +// Expected output: JO + +class Ab: + + initializer(): + self.attr := 'J' + + + Char attr + +class Ba inherits Ab: + + initializer(): + parent(Ab).initializer() + Char attr := 'O' + print(self.attr) + print(attr) + +Ba b := Ba() diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar3.output b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar3.output new file mode 100644 index 0000000..444a896 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar3.output @@ -0,0 +1 @@ +JO \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar4.monty b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar4.monty new file mode 100644 index 0000000..fbdaf3f --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar4.monty @@ -0,0 +1,20 @@ +// Testing: VariableDeclaration in ClassDeclaration with single inheritance. +// +// The boolean inherited attribute is written and a copy printed. The access +// via self must work. +// +// Expected output: M + +class Ab: + + initializer(): + self.attr := 'M' + + + Char attr + +class Ba inherits Ab: + + initializer(): + parent(Ab).initializer() + Char copy := self.attr + print(copy) + +Ba b := Ba() diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar4.output b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar4.output new file mode 100644 index 0000000..ef6bce1 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberChar4.output @@ -0,0 +1 @@ +M \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberComplex1.monty b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberComplex1.monty new file mode 100644 index 0000000..2304f10 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberComplex1.monty @@ -0,0 +1,25 @@ +// Testing: VariableDeclaration in ClassDeclaration with single inheritance. +// +// A complex expression of chained inherited attributes must be accessible and +// readable. +// +// Expected output: Hallo Welt + +class Ab: + + String attr + + + initializer(): + self.attr := "Hallo Welt" + +class Ba inherits Ab: + + initializer(): + parent(Ab).initializer() + +class Ca: + + Ba attr + + + initializer(): + self.attr := Ba() + +Ca inst := Ca() +print(inst.attr.attr) diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberComplex1.output b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberComplex1.output new file mode 100644 index 0000000..a92550c --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberComplex1.output @@ -0,0 +1 @@ +Hallo Welt \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberComplex2.monty b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberComplex2.monty new file mode 100644 index 0000000..20b004d --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberComplex2.monty @@ -0,0 +1,26 @@ +// Testing: VariableDeclaration in ClassDeclaration with single inheritance. +// +// A complex expression of chained inherited attributes must be accessible, +// writable and readable. +// +// Expected output: Hallo Welt + +class Ab: + + String attr + + + initializer(): + self.attr := "Nope" + +class Ba inherits Ab: + + initializer(): + parent(Ab).initializer() + +class Ca: + + Ba attr + + + initializer(): + self.attr := Ba() + +Ca inst := Ca() +inst.attr.attr := "Hallo Welt" +print(inst.attr.attr) diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberComplex2.output b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberComplex2.output new file mode 100644 index 0000000..a92550c --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberComplex2.output @@ -0,0 +1 @@ +Hallo Welt \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat1.monty b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat1.monty new file mode 100644 index 0000000..9cbbaa9 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat1.monty @@ -0,0 +1,19 @@ +// Testing: VariableDeclaration in ClassDeclaration with single inheritance. +// +// The float inherited attribute is written and printed. The access via self +// must work. +// +// Expected output: 1.3 + +class Ab: + + initializer(): + self.attr := 1.3 + + + Float attr + +class Ba inherits Ab: + + initializer(): + parent(Ab).initializer() + print(self.attr) + +Ba b := Ba() diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat1.output b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat1.output new file mode 100644 index 0000000..a58941b --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat1.output @@ -0,0 +1 @@ +1.3 \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat2.monty b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat2.monty new file mode 100644 index 0000000..83a4fe1 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat2.monty @@ -0,0 +1,19 @@ +// Testing: VariableDeclaration in ClassDeclaration with single inheritance. +// +// The float inherited attribute is written and printed from outside the +// class. The access via self and the member access must work. +// +// Expected output: 1.3 + +class Ab: + + initializer(): + self.attr := 1.3 + + + Float attr + +class Ba inherits Ab: + + initializer(): + parent(Ab).initializer() + +Ba b := Ba() +print(b.attr) diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat2.output b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat2.output new file mode 100644 index 0000000..a58941b --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat2.output @@ -0,0 +1 @@ +1.3 \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat3.monty b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat3.monty new file mode 100644 index 0000000..e76a81e --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat3.monty @@ -0,0 +1,21 @@ +// Testing: VariableDeclaration in ClassDeclaration with single inheritance. +// +// A float inherited attribute and a local variable exist with the same name. +// Both must be writable and readable. +// +// Expected output: 1.33.1 + +class Ab: + + initializer(): + self.attr := 1.3 + + + Float attr + +class Ba inherits Ab: + + initializer(): + parent(Ab).initializer() + Float attr := 3.1 + print(self.attr) + print(attr) + +Ba b := Ba() diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat3.output b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat3.output new file mode 100644 index 0000000..9e9fac3 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat3.output @@ -0,0 +1 @@ +1.33.1 \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat4.monty b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat4.monty new file mode 100644 index 0000000..1d18245 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat4.monty @@ -0,0 +1,20 @@ +// Testing: VariableDeclaration in ClassDeclaration with single inheritance. +// +// The float attribute is written and a copy printed. The access via self +// must work. +// +// Expected output: 1.3 + +class Ab: + + initializer(): + self.attr := 1.3 + + + Float attr + +class Ba inherits Ab: + + initializer(): + parent(Ab).initializer() + Float copy := self.attr + print(copy) + +Ba b := Ba() diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat4.output b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat4.output new file mode 100644 index 0000000..a58941b --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberFloat4.output @@ -0,0 +1 @@ +1.3 \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt1.monty b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt1.monty new file mode 100644 index 0000000..72d39cc --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt1.monty @@ -0,0 +1,19 @@ +// Testing: VariableDeclaration in ClassDeclaration with single inheritance. +// +// The int inherited attribute is written and printed. The access via self +// must work. +// +// Expected output: 1 + +class Ab: + + initializer(): + self.attr := 1 + + + Int attr + +class Ba inherits Ab: + + initializer(): + parent(Ab).initializer() + print(self.attr) + +Ba b := Ba() diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt1.output b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt1.output new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt1.output @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt2.monty b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt2.monty new file mode 100644 index 0000000..b52c6a3 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt2.monty @@ -0,0 +1,19 @@ +// Testing: VariableDeclaration in ClassDeclaration with single inheritance. +// +// The int inherited attribute is written and printed from outside the class. +// The access via self and the member access must work. +// +// Expected output: 1 + +class Ab: + + initializer(): + self.attr := 1 + + + Int attr + +class Ba inherits Ab: + + initializer(): + parent(Ab).initializer() + +Ba b := Ba() +print(b.attr) diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt2.output b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt2.output new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt2.output @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt3.monty b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt3.monty new file mode 100644 index 0000000..71291dc --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt3.monty @@ -0,0 +1,21 @@ +// Testing: VariableDeclaration in ClassDeclaration with single inheritance. +// +// An int inherited attribute and a local variable exist with the same name. +// Both must be writable and readable. +// +// Expected output: 10 + +class Ab: + + initializer(): + self.attr := 1 + + + Int attr + +class Ba inherits Ab: + + initializer(): + parent(Ab).initializer() + Int attr := 0 + print(self.attr) + print(attr) + +Ba b := Ba() diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt3.output b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt3.output new file mode 100644 index 0000000..9a03714 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt3.output @@ -0,0 +1 @@ +10 \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt4.monty b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt4.monty new file mode 100644 index 0000000..4e31485 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt4.monty @@ -0,0 +1,20 @@ +// Testing: VariableDeclaration in ClassDeclaration with single inheritance. +// +// The int inherited attribute is written and a copy printed. The access via +// self must work. +// +// Expected output: 1 + +class Ab: + + initializer(): + self.attr := 1 + + + Int attr + +class Ba inherits Ab: + + initializer(): + parent(Ab).initializer() + Int copy := self.attr + print(copy) + +Ba b := Ba() diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt4.output b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt4.output new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberInt4.output @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString1.monty b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString1.monty new file mode 100644 index 0000000..8940d37 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString1.monty @@ -0,0 +1,19 @@ +// Testing: VariableDeclaration in ClassDeclaration with single inheritance. +// +// The string inherited attribute is written and printed. The access via self +// must work. +// +// Expected output: Hallo + +class Ab: + + initializer(): + self.attr := "Hallo" + + + String attr + +class Ba inherits Ab: + + initializer(): + parent(Ab).initializer() + print(self.attr) + +Ba b := Ba() diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString1.output b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString1.output new file mode 100644 index 0000000..53f5007 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString1.output @@ -0,0 +1 @@ +Hallo \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString2.monty b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString2.monty new file mode 100644 index 0000000..9b515f1 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString2.monty @@ -0,0 +1,19 @@ +// Testing: VariableDeclaration in ClassDeclaration with single inheritance. +// +// The string inherited attribute is written and printed from outside the +// class. The access via self and the member access must work. +// +// Expected output: Hallo + +class Ab: + + initializer(): + self.attr := "Hallo" + + + String attr + +class Ba inherits Ab: + + initializer(): + parent(Ab).initializer() + +Ba b := Ba() +print(b.attr) diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString2.output b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString2.output new file mode 100644 index 0000000..53f5007 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString2.output @@ -0,0 +1 @@ +Hallo \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString3.monty b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString3.monty new file mode 100644 index 0000000..d47f3c2 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString3.monty @@ -0,0 +1,21 @@ +// Testing: VariableDeclaration in ClassDeclaration with single inheritance. +// +// A string inherited attribute and a local variable exist with the same name. +// Both must be writable and readable. +// +// Expected output: HalloWelt + +class Ab: + + initializer(): + self.attr := "Hallo" + + + String attr + +class Ba inherits Ab: + + initializer(): + parent(Ab).initializer() + String attr := "Welt" + print(self.attr) + print(attr) + +Ba b := Ba() diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString3.output b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString3.output new file mode 100644 index 0000000..b7b7804 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString3.output @@ -0,0 +1 @@ +HalloWelt \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString4.monty b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString4.monty new file mode 100644 index 0000000..fd33ada --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString4.monty @@ -0,0 +1,20 @@ +// Testing: VariableDeclaration in ClassDeclaration with single inheritance. +// +// The string inherited attribute is written and a copy printed. The access +// via self must work. +// +// Expected output: Hallo + +class Ab: + + initializer(): + self.attr := "Hallo" + + + String attr + +class Ba inherits Ab: + + initializer(): + parent(Ab).initializer() + String copy := self.attr + print(copy) + +Ba b := Ba() diff --git a/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString4.output b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString4.output new file mode 100644 index 0000000..53f5007 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/member/ClassInheritedMemberString4.output @@ -0,0 +1 @@ +Hallo \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/methods/InheritanceMethods1.monty b/src/test/resources/testPrograms/inheritance/methods/InheritanceMethods1.monty new file mode 100644 index 0000000..364add1 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/methods/InheritanceMethods1.monty @@ -0,0 +1,26 @@ +// Testing: FunctionCall in ClassDeclaration with single inheritance. +// +// The inherited methods (procedure/function) must be callable and do/return +// the right stuff. +// +// Expected output: HelloWorldHelloWorld + +class Ab: + + printHello(): + print("Hello") + + + String returnHello(): + return "Hello" + +class Ba inherits Ab: + + printWorld(): + print("World") + + + String returnWorld(): + return "World" + +Ba b := Ba() +b.printHello() +b.printWorld() +print(b.returnHello()) +print(b.returnWorld()) diff --git a/src/test/resources/testPrograms/inheritance/methods/InheritanceMethods1.output b/src/test/resources/testPrograms/inheritance/methods/InheritanceMethods1.output new file mode 100644 index 0000000..1b52879 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/methods/InheritanceMethods1.output @@ -0,0 +1 @@ +HelloWorldHelloWorld \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/methods/InheritanceMethods2.monty b/src/test/resources/testPrograms/inheritance/methods/InheritanceMethods2.monty new file mode 100644 index 0000000..b201a2d --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/methods/InheritanceMethods2.monty @@ -0,0 +1,24 @@ +// Testing: FunctionCall in ClassDeclaration with single inheritance. +// +// The inherited overriden methods (procedure/function) must be callable and +// do/return the right stuff. +// +// Expected output: HelloWorldHelloWorld + +class Ab: + + printHelloWorld(): + print("WorldHello") + + + String returnHelloWorld(): + return "WorldHello" + +class Ba inherits Ab: + + printHelloWorld(): + print("HelloWorld") + + + String returnHelloWorld(): + return "HelloWorld" + +Ab b := Ba() +b.printHelloWorld() +print(b.returnHelloWorld()) diff --git a/src/test/resources/testPrograms/inheritance/methods/InheritanceMethods2.output b/src/test/resources/testPrograms/inheritance/methods/InheritanceMethods2.output new file mode 100644 index 0000000..1b52879 --- /dev/null +++ b/src/test/resources/testPrograms/inheritance/methods/InheritanceMethods2.output @@ -0,0 +1 @@ +HelloWorldHelloWorld \ No newline at end of file diff --git a/src/test/resources/testPrograms/literals/BoolAsObject.monty b/src/test/resources/testPrograms/literals/BoolAsObject.monty new file mode 100644 index 0000000..bf5c268 --- /dev/null +++ b/src/test/resources/testPrograms/literals/BoolAsObject.monty @@ -0,0 +1,11 @@ +// Testing: Bool as Object +// +// A bool object must be castable to an Bool +// +// Expected output: 10 + +Object t := true +Object f := false + +print(t as Bool) +print(f as Bool) diff --git a/src/test/resources/testPrograms/literals/BoolAsObject.output b/src/test/resources/testPrograms/literals/BoolAsObject.output new file mode 100644 index 0000000..9a03714 --- /dev/null +++ b/src/test/resources/testPrograms/literals/BoolAsObject.output @@ -0,0 +1 @@ +10 \ No newline at end of file diff --git a/src/test/resources/testPrograms/literals/BoolConstructor.monty b/src/test/resources/testPrograms/literals/BoolConstructor.monty new file mode 100644 index 0000000..3bd4c9e --- /dev/null +++ b/src/test/resources/testPrograms/literals/BoolConstructor.monty @@ -0,0 +1,11 @@ +// Testing: Bool as Object +// +// A bool-initializer call must work. +// +// Expected output: 10 + +Bool t := Bool(true) +Bool f := Bool(false) + +print(t) +print(f) diff --git a/src/test/resources/testPrograms/literals/BoolConstructor.output b/src/test/resources/testPrograms/literals/BoolConstructor.output new file mode 100644 index 0000000..9a03714 --- /dev/null +++ b/src/test/resources/testPrograms/literals/BoolConstructor.output @@ -0,0 +1 @@ +10 \ No newline at end of file diff --git a/src/test/resources/testPrograms/literals/BoolIsObject.monty b/src/test/resources/testPrograms/literals/BoolIsObject.monty new file mode 100644 index 0000000..6b16b76 --- /dev/null +++ b/src/test/resources/testPrograms/literals/BoolIsObject.monty @@ -0,0 +1,17 @@ +// Testing: Bool as Object +// +// A bool must be an Object +// +// Expected output: Ok(Bool)Ok(Bool) + +Object b := true + +if b is Bool: + print("Ok(Bool)") +else: + print("Nope(Bool)") + +if true is Object: + print("Ok(Bool)") +else: + print("Nope(Bool)") diff --git a/src/test/resources/testPrograms/literals/BoolIsObject.output b/src/test/resources/testPrograms/literals/BoolIsObject.output new file mode 100644 index 0000000..7d17351 --- /dev/null +++ b/src/test/resources/testPrograms/literals/BoolIsObject.output @@ -0,0 +1 @@ +Ok(Bool)Ok(Bool) \ No newline at end of file diff --git a/src/test/resources/testPrograms/literals/CharAsObject.monty b/src/test/resources/testPrograms/literals/CharAsObject.monty new file mode 100644 index 0000000..b39e40a --- /dev/null +++ b/src/test/resources/testPrograms/literals/CharAsObject.monty @@ -0,0 +1,10 @@ +// Testing: Char as Object +// +// A char object must be castable to an Char +// +// Expected output: a + +Object c := 'a' + +print(c as Char) + diff --git a/src/test/resources/testPrograms/literals/CharAsObject.output b/src/test/resources/testPrograms/literals/CharAsObject.output new file mode 100644 index 0000000..2e65efe --- /dev/null +++ b/src/test/resources/testPrograms/literals/CharAsObject.output @@ -0,0 +1 @@ +a \ No newline at end of file diff --git a/src/test/resources/testPrograms/literals/CharConstructor.monty b/src/test/resources/testPrograms/literals/CharConstructor.monty new file mode 100644 index 0000000..a673179 --- /dev/null +++ b/src/test/resources/testPrograms/literals/CharConstructor.monty @@ -0,0 +1,9 @@ +// Testing: Char as Object +// +// A char-initializer call must work. +// +// Expected output: a + +Char c := Char('a') + +print(c) diff --git a/src/test/resources/testPrograms/literals/CharConstructor.output b/src/test/resources/testPrograms/literals/CharConstructor.output new file mode 100644 index 0000000..2e65efe --- /dev/null +++ b/src/test/resources/testPrograms/literals/CharConstructor.output @@ -0,0 +1 @@ +a \ No newline at end of file diff --git a/src/test/resources/testPrograms/literals/CharIsObject.monty b/src/test/resources/testPrograms/literals/CharIsObject.monty new file mode 100644 index 0000000..0bada09 --- /dev/null +++ b/src/test/resources/testPrograms/literals/CharIsObject.monty @@ -0,0 +1,17 @@ +// Testing: Char as Object +// +// A char must be an Object +// +// Expected output: Ok(Char)Ok(Char) + +Object c := 'a' + +if c is Char: + print("Ok(Char)") +else: + print("Nope(Char)") + +if 'a' is Object: + print("Ok(Char)") +else: + print("Nope(Char)") diff --git a/src/test/resources/testPrograms/literals/CharIsObject.output b/src/test/resources/testPrograms/literals/CharIsObject.output new file mode 100644 index 0000000..60924ae --- /dev/null +++ b/src/test/resources/testPrograms/literals/CharIsObject.output @@ -0,0 +1 @@ +Ok(Char)Ok(Char) \ No newline at end of file diff --git a/src/test/resources/testPrograms/literals/FloatAsObject.monty b/src/test/resources/testPrograms/literals/FloatAsObject.monty new file mode 100644 index 0000000..29c456e --- /dev/null +++ b/src/test/resources/testPrograms/literals/FloatAsObject.monty @@ -0,0 +1,12 @@ +// Testing: Float as Object +// +// A float object must be castable to an Float +// +// Expected output: 01.3 + +Object z := 0.0 +Object f := 1.3 + +print(z as Float) +print(f as Float) + diff --git a/src/test/resources/testPrograms/literals/FloatAsObject.output b/src/test/resources/testPrograms/literals/FloatAsObject.output new file mode 100644 index 0000000..7056186 --- /dev/null +++ b/src/test/resources/testPrograms/literals/FloatAsObject.output @@ -0,0 +1 @@ +01.3 \ No newline at end of file diff --git a/src/test/resources/testPrograms/literals/FloatConstructor.monty b/src/test/resources/testPrograms/literals/FloatConstructor.monty new file mode 100644 index 0000000..ddba9bd --- /dev/null +++ b/src/test/resources/testPrograms/literals/FloatConstructor.monty @@ -0,0 +1,11 @@ +// Testing: Float as Object +// +// A float-initializer call must work. +// +// Expected output: 01.3 + +Float z := Float(0.0) +Float f := Float(1.3) + +print(z) +print(f) diff --git a/src/test/resources/testPrograms/literals/FloatConstructor.output b/src/test/resources/testPrograms/literals/FloatConstructor.output new file mode 100644 index 0000000..7056186 --- /dev/null +++ b/src/test/resources/testPrograms/literals/FloatConstructor.output @@ -0,0 +1 @@ +01.3 \ No newline at end of file diff --git a/src/test/resources/testPrograms/literals/FloatIsObject.monty b/src/test/resources/testPrograms/literals/FloatIsObject.monty new file mode 100644 index 0000000..efe5f29 --- /dev/null +++ b/src/test/resources/testPrograms/literals/FloatIsObject.monty @@ -0,0 +1,17 @@ +// Testing: Float as Object +// +// A float must be an Object +// +// Expected output: Ok(Float)Ok(Float) + +Object f := 1.3 + +if f is Float: + print("Ok(Float)") +else: + print("Nope(Float)") + +if 0.0 is Object: + print("Ok(Float)") +else: + print("Nope(Float)") diff --git a/src/test/resources/testPrograms/literals/FloatIsObject.output b/src/test/resources/testPrograms/literals/FloatIsObject.output new file mode 100644 index 0000000..f074bff --- /dev/null +++ b/src/test/resources/testPrograms/literals/FloatIsObject.output @@ -0,0 +1 @@ +Ok(Float)Ok(Float) \ No newline at end of file diff --git a/src/test/resources/testPrograms/literals/IntAsObject.monty b/src/test/resources/testPrograms/literals/IntAsObject.monty new file mode 100644 index 0000000..603561e --- /dev/null +++ b/src/test/resources/testPrograms/literals/IntAsObject.monty @@ -0,0 +1,12 @@ +// Testing: Int as Object +// +// An int object must be castable to an Int +// +// Expected output: 042 + +Object z := 0 +Object i := 42 + +print(z as Int) +print(i as Int) + diff --git a/src/test/resources/testPrograms/literals/IntAsObject.output b/src/test/resources/testPrograms/literals/IntAsObject.output new file mode 100644 index 0000000..9f73fc0 --- /dev/null +++ b/src/test/resources/testPrograms/literals/IntAsObject.output @@ -0,0 +1 @@ +042 \ No newline at end of file diff --git a/src/test/resources/testPrograms/literals/IntConstructor.monty b/src/test/resources/testPrograms/literals/IntConstructor.monty new file mode 100644 index 0000000..9160a01 --- /dev/null +++ b/src/test/resources/testPrograms/literals/IntConstructor.monty @@ -0,0 +1,11 @@ +// Testing: Int as Object +// +// An int-initializer call must work. +// +// Expected output: 042 + +Int z := Int(0) +Int i := Int(42) + +print(z) +print(i) diff --git a/src/test/resources/testPrograms/literals/IntConstructor.output b/src/test/resources/testPrograms/literals/IntConstructor.output new file mode 100644 index 0000000..9f73fc0 --- /dev/null +++ b/src/test/resources/testPrograms/literals/IntConstructor.output @@ -0,0 +1 @@ +042 \ No newline at end of file diff --git a/src/test/resources/testPrograms/literals/IntIsObject.monty b/src/test/resources/testPrograms/literals/IntIsObject.monty new file mode 100644 index 0000000..d55f503 --- /dev/null +++ b/src/test/resources/testPrograms/literals/IntIsObject.monty @@ -0,0 +1,17 @@ +// Testing: Int as Object +// +// An int must be an Object +// +// Expected output: Ok(Int)Ok(Int) + +Object i := 42 + +if i is Int: + print("Ok(Int)") +else: + print("Nope(Int)") + +if 0 is Object: + print("Ok(Int)") +else: + print("Nope(Int)") diff --git a/src/test/resources/testPrograms/literals/IntIsObject.output b/src/test/resources/testPrograms/literals/IntIsObject.output new file mode 100644 index 0000000..8bd5ff8 --- /dev/null +++ b/src/test/resources/testPrograms/literals/IntIsObject.output @@ -0,0 +1 @@ +Ok(Int)Ok(Int) \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/IdentifierNotDefined.error b/src/test/resources/testPrograms/negativ/IdentifierNotDefined.error new file mode 100644 index 0000000..3f092fe --- /dev/null +++ b/src/test/resources/testPrograms/negativ/IdentifierNotDefined.error @@ -0,0 +1 @@ +ResolveVisitor caught error in null: Identifier is not defined: x \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/IdentifierNotDefined.monty b/src/test/resources/testPrograms/negativ/IdentifierNotDefined.monty new file mode 100644 index 0000000..137b95f --- /dev/null +++ b/src/test/resources/testPrograms/negativ/IdentifierNotDefined.monty @@ -0,0 +1,7 @@ +// Testing: Access to undefined variable +// +// Calls the print function with undefined variable x +// +// Expected output: Error + +print(x) \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/callable/neg_Function1.error b/src/test/resources/testPrograms/negativ/callable/neg_Function1.error new file mode 100644 index 0000000..ce0d4a5 --- /dev/null +++ b/src/test/resources/testPrograms/negativ/callable/neg_Function1.error @@ -0,0 +1 @@ +ResolveVisitor caught error in null: Identifier is not defined: square \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/callable/neg_Function1.monty b/src/test/resources/testPrograms/negativ/callable/neg_Function1.monty new file mode 100644 index 0000000..1983e7c --- /dev/null +++ b/src/test/resources/testPrograms/negativ/callable/neg_Function1.monty @@ -0,0 +1,10 @@ +// Testing: FunctionCall with wrong Paramaters +// +// The function is not called correctly in the print statement. +// +// Expected output: Error + +Int square(Int value): + return value * value + +print(square) \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/callable/neg_Function2.error b/src/test/resources/testPrograms/negativ/callable/neg_Function2.error new file mode 100644 index 0000000..4ab72c2 --- /dev/null +++ b/src/test/resources/testPrograms/negativ/callable/neg_Function2.error @@ -0,0 +1 @@ +ResolveVisitor caught error in null: Type is not defined: Boolean \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/callable/neg_Function2.monty b/src/test/resources/testPrograms/negativ/callable/neg_Function2.monty new file mode 100644 index 0000000..7fa38f9 --- /dev/null +++ b/src/test/resources/testPrograms/negativ/callable/neg_Function2.monty @@ -0,0 +1,8 @@ +// Testing: FunctionDeclaration +// +// The function is declared with the undefined type 'Boolean'. +// +// Expected output: Error + +Boolean square(Int value): + return value * value \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/callable/neg_Function3.error b/src/test/resources/testPrograms/negativ/callable/neg_Function3.error new file mode 100644 index 0000000..aff6352 --- /dev/null +++ b/src/test/resources/testPrograms/negativ/callable/neg_Function3.error @@ -0,0 +1 @@ +TypeCheckVisitor caught error in ReturnStatement at file: neg_Function3.monty, line: 9, char: 1: Expected to return Int: \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/callable/neg_Function3.monty b/src/test/resources/testPrograms/negativ/callable/neg_Function3.monty new file mode 100644 index 0000000..744adf0 --- /dev/null +++ b/src/test/resources/testPrograms/negativ/callable/neg_Function3.monty @@ -0,0 +1,9 @@ +// Testing: FunctionDeclaration +// +// The function is missing a declaration type. +// +// Expected output: Error + +Int square(Int value): + String str := "I will cause a TypeMisMatch!" + return str \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/callable/neg_Function4.error b/src/test/resources/testPrograms/negativ/callable/neg_Function4.error new file mode 100644 index 0000000..760589c --- /dev/null +++ b/src/test/resources/testPrograms/negativ/callable/neg_Function4.error @@ -0,0 +1 @@ +error \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/callable/neg_Function4.monty.ignore b/src/test/resources/testPrograms/negativ/callable/neg_Function4.monty.ignore new file mode 100644 index 0000000..b998577 --- /dev/null +++ b/src/test/resources/testPrograms/negativ/callable/neg_Function4.monty.ignore @@ -0,0 +1,17 @@ +// Testing: FunctionDeclaration & Return +// +// A function must contain a return in every branch of conditional +// statement. +// +// Expected output: Error + +String branch(Int x): + String y + if x = 10: + y := "10" + return y + else: + y := "2" + + +print(branch(1)) \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/callable/neg_Procedure1.error b/src/test/resources/testPrograms/negativ/callable/neg_Procedure1.error new file mode 100644 index 0000000..8c09dbb --- /dev/null +++ b/src/test/resources/testPrograms/negativ/callable/neg_Procedure1.error @@ -0,0 +1 @@ +TypeCheckVisitor caught error in ReturnStatement at file: neg_Procedure1.monty, line: 9, char: 1: Expected to return void. \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/callable/neg_Procedure1.monty b/src/test/resources/testPrograms/negativ/callable/neg_Procedure1.monty new file mode 100644 index 0000000..4df1380 --- /dev/null +++ b/src/test/resources/testPrograms/negativ/callable/neg_Procedure1.monty @@ -0,0 +1,9 @@ +// Testing: ProcedureDeclaration and ProcedureCall +// +// Procedures can't have return types so they mustn't return +// an expression that evaluates to a type. +// +// Expected output: Error + +square(Int value): + return value \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/callable/neg_Procedure2.error b/src/test/resources/testPrograms/negativ/callable/neg_Procedure2.error new file mode 100644 index 0000000..a779e71 --- /dev/null +++ b/src/test/resources/testPrograms/negativ/callable/neg_Procedure2.error @@ -0,0 +1 @@ +TypeCheckVisitor caught error in FunctionCall at file: neg_Procedure2.monty, line: 13, char: 0: Arguments of function call do not match declaration. \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/callable/neg_Procedure2.monty b/src/test/resources/testPrograms/negativ/callable/neg_Procedure2.monty new file mode 100644 index 0000000..0b4bc76 --- /dev/null +++ b/src/test/resources/testPrograms/negativ/callable/neg_Procedure2.monty @@ -0,0 +1,13 @@ +// Testing: ProcedureDeclaration & Return +// +// Printing the result of a procedure should end in an error +// or print emtpy String XXXTODO Currently this tests ends in a +// Java NullPointer Exception. +// +// Expected output: Error or Empty String + +calc(Int x): + Int val := x*x + return + +print(calc(2)) \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/scoping/RedeclarationOtherType.error b/src/test/resources/testPrograms/negativ/scoping/RedeclarationOtherType.error new file mode 100644 index 0000000..ad6d505 --- /dev/null +++ b/src/test/resources/testPrograms/negativ/scoping/RedeclarationOtherType.error @@ -0,0 +1 @@ +DeclarationVisitor caught error in VariableDeclaration at file: RedeclarationOtherType.monty, line: 9, char: 0: greeting \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/scoping/RedeclarationOtherType.monty b/src/test/resources/testPrograms/negativ/scoping/RedeclarationOtherType.monty new file mode 100644 index 0000000..9f7fb3a --- /dev/null +++ b/src/test/resources/testPrograms/negativ/scoping/RedeclarationOtherType.monty @@ -0,0 +1,9 @@ +// Testing: Scope +// +// A Variable must not be redeclarable within the same Scope, +// even if it has a different type. +// +// Expected output: Error + +String greeting := "Guten Morgen" +Bool greeting := true \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/scoping/RedeclarationSameType.error b/src/test/resources/testPrograms/negativ/scoping/RedeclarationSameType.error new file mode 100644 index 0000000..56e49a3 --- /dev/null +++ b/src/test/resources/testPrograms/negativ/scoping/RedeclarationSameType.error @@ -0,0 +1 @@ +DeclarationVisitor caught error in VariableDeclaration at file: RedeclarationSameType.monty, line: 8, char: 0: greeting \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/scoping/RedeclarationSameType.monty b/src/test/resources/testPrograms/negativ/scoping/RedeclarationSameType.monty new file mode 100644 index 0000000..e135734 --- /dev/null +++ b/src/test/resources/testPrograms/negativ/scoping/RedeclarationSameType.monty @@ -0,0 +1,8 @@ +// Testing: Scope +// +// A Variable must not be redeclarable within the same Scope. +// +// Expected output: Error + +String greeting := "Guten Morgen" +String greeting := "Guten Tag" \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/scoping/VariableAccess.error b/src/test/resources/testPrograms/negativ/scoping/VariableAccess.error new file mode 100644 index 0000000..227affb --- /dev/null +++ b/src/test/resources/testPrograms/negativ/scoping/VariableAccess.error @@ -0,0 +1 @@ +ResolveVisitor caught error in null: Identifier is not defined: b \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/scoping/VariableAccess.monty b/src/test/resources/testPrograms/negativ/scoping/VariableAccess.monty new file mode 100644 index 0000000..87af7a7 --- /dev/null +++ b/src/test/resources/testPrograms/negativ/scoping/VariableAccess.monty @@ -0,0 +1,9 @@ +// Testing: Lexical scoping +// +// B must not be writable if it is not declared yet. +// +// Expected output: Error + +Int a := 3 +b := a +Int b \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/scoping/VariableAccess2.error b/src/test/resources/testPrograms/negativ/scoping/VariableAccess2.error new file mode 100644 index 0000000..ca5a8d9 --- /dev/null +++ b/src/test/resources/testPrograms/negativ/scoping/VariableAccess2.error @@ -0,0 +1 @@ +ResolveVisitor caught error in null: Identifier is not defined: var \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/scoping/VariableAccess2.monty b/src/test/resources/testPrograms/negativ/scoping/VariableAccess2.monty new file mode 100644 index 0000000..e4e94d3 --- /dev/null +++ b/src/test/resources/testPrograms/negativ/scoping/VariableAccess2.monty @@ -0,0 +1,13 @@ +// Testing: Lexical scoping +// +// var must be declared & initialized before it can be used in function's decl. +// +// Expected output: Error + +Int function(): + Int copy := var + return copy + +Int var := 42 + +print(function()) diff --git a/src/test/resources/testPrograms/negativ/scoping/VariableAccess3.error b/src/test/resources/testPrograms/negativ/scoping/VariableAccess3.error new file mode 100644 index 0000000..227affb --- /dev/null +++ b/src/test/resources/testPrograms/negativ/scoping/VariableAccess3.error @@ -0,0 +1 @@ +ResolveVisitor caught error in null: Identifier is not defined: b \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/scoping/VariableAccess3.monty b/src/test/resources/testPrograms/negativ/scoping/VariableAccess3.monty new file mode 100644 index 0000000..6f3d838 --- /dev/null +++ b/src/test/resources/testPrograms/negativ/scoping/VariableAccess3.monty @@ -0,0 +1,8 @@ +// Testing: Lexical scoping +// +// B must not be writable if it is not declared. +// +// Expected output: Error + +Int a := 3 +b := a \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/scoping/VariableAccess4.error b/src/test/resources/testPrograms/negativ/scoping/VariableAccess4.error new file mode 100644 index 0000000..ca5a8d9 --- /dev/null +++ b/src/test/resources/testPrograms/negativ/scoping/VariableAccess4.error @@ -0,0 +1 @@ +ResolveVisitor caught error in null: Identifier is not defined: var \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/scoping/VariableAccess4.monty b/src/test/resources/testPrograms/negativ/scoping/VariableAccess4.monty new file mode 100644 index 0000000..a259ebb --- /dev/null +++ b/src/test/resources/testPrograms/negativ/scoping/VariableAccess4.monty @@ -0,0 +1,8 @@ +// Testing: Lexical scoping +// +// var must not be readable if it is not declared yet. +// +// Expected output: Error + +print(var) +Int var := 42 \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/scoping/VariableAccess5.error b/src/test/resources/testPrograms/negativ/scoping/VariableAccess5.error new file mode 100644 index 0000000..8a75026 --- /dev/null +++ b/src/test/resources/testPrograms/negativ/scoping/VariableAccess5.error @@ -0,0 +1 @@ +some useful error message. \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/scoping/VariableAccess5.monty.ignore b/src/test/resources/testPrograms/negativ/scoping/VariableAccess5.monty.ignore new file mode 100644 index 0000000..e356f1d --- /dev/null +++ b/src/test/resources/testPrograms/negativ/scoping/VariableAccess5.monty.ignore @@ -0,0 +1,12 @@ +// Testing: Lexical scoping +// +// var must not be readable if it is not initialized yet. +// +// Expected output: Error +// +// This test is ignored atm, since a lot more contextual analysis is needed, in +// order to correclty ensure only access of already initialized variables. + +Int var +print(var) +var := 42 \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/scoping/VariableAccess6.error b/src/test/resources/testPrograms/negativ/scoping/VariableAccess6.error new file mode 100644 index 0000000..46b12b7 --- /dev/null +++ b/src/test/resources/testPrograms/negativ/scoping/VariableAccess6.error @@ -0,0 +1 @@ +ResolveVisitor caught error in null: Identifier is not defined: answer \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/scoping/VariableAccess6.monty b/src/test/resources/testPrograms/negativ/scoping/VariableAccess6.monty new file mode 100644 index 0000000..1558991 --- /dev/null +++ b/src/test/resources/testPrograms/negativ/scoping/VariableAccess6.monty @@ -0,0 +1,15 @@ +// Testing: Lexical scoping vs simultaneous visibility +// +// answer within calcAnswerToLifeAndStuff shadows the outer scope one. +// But since we do not have simultaneous visibility within procedures, +// answers must not be accessible, when accessed prior to declaration. +// +// Expected output: Error + +Int answer := 42 + +calcAnswerToLifeAndStuff(): + print(answer) + Int answer := 43 + +calcAnswerToLifeAndStuff() \ No newline at end of file diff --git a/src/test/resources/testPrograms/object/Object1.monty b/src/test/resources/testPrograms/object/Object1.monty new file mode 100644 index 0000000..5bac744 --- /dev/null +++ b/src/test/resources/testPrograms/object/Object1.monty @@ -0,0 +1,7 @@ +// Testing: The monty baseclass Object. +// +// Object must be instantiable. +// +// Expected output: + +Object b := Object() diff --git a/src/test/resources/testPrograms/object/Object1.output b/src/test/resources/testPrograms/object/Object1.output new file mode 100644 index 0000000..e69de29 diff --git a/src/test/resources/testPrograms/object/Object2.monty b/src/test/resources/testPrograms/object/Object2.monty new file mode 100644 index 0000000..97bcee6 --- /dev/null +++ b/src/test/resources/testPrograms/object/Object2.monty @@ -0,0 +1,10 @@ +// Testing: The monty baseclass Object. +// +// Object must be usable as normal Object (e.g. pass it arround). +// +// Expected output: + +Object returnsObject(Object o): + return o + +Object o := returnsObject(Object()) diff --git a/src/test/resources/testPrograms/object/Object2.output b/src/test/resources/testPrograms/object/Object2.output new file mode 100644 index 0000000..e69de29 diff --git a/src/test/resources/testPrograms/object/Object3.monty b/src/test/resources/testPrograms/object/Object3.monty new file mode 100644 index 0000000..5438354 --- /dev/null +++ b/src/test/resources/testPrograms/object/Object3.monty @@ -0,0 +1,10 @@ +// Testing: The monty baseclass Object. +// +// A class inheriting nothing must inherit Object. +// +// Expected output: + +class Ab: + pass + +Object a := Ab() diff --git a/src/test/resources/testPrograms/object/Object3.output b/src/test/resources/testPrograms/object/Object3.output new file mode 100644 index 0000000..e69de29 diff --git a/src/test/resources/testPrograms/object/Object4.monty b/src/test/resources/testPrograms/object/Object4.monty new file mode 100644 index 0000000..3d9e9e1 --- /dev/null +++ b/src/test/resources/testPrograms/object/Object4.monty @@ -0,0 +1,12 @@ +// Testing: The monty baseclass Object. +// +// A class inheriting nothing must inherit Object and be castable.. +// +// Expected output: 42 + +class Ab: + + Int attr := 42 + +Object o := Ab() +Ab a := o as Ab +print(a.attr) diff --git a/src/test/resources/testPrograms/object/Object4.output b/src/test/resources/testPrograms/object/Object4.output new file mode 100644 index 0000000..f70d7bb --- /dev/null +++ b/src/test/resources/testPrograms/object/Object4.output @@ -0,0 +1 @@ +42 \ No newline at end of file diff --git a/src/test/resources/testPrograms/overloading/OverloadingConstructor1.monty b/src/test/resources/testPrograms/overloading/OverloadingConstructor1.monty new file mode 100644 index 0000000..e09d2b3 --- /dev/null +++ b/src/test/resources/testPrograms/overloading/OverloadingConstructor1.monty @@ -0,0 +1,50 @@ +// Testing: Overloading of initializers +// +// The correct overloaded initializer must be called. +// +// Expected output: :empty:i:f:s:b:ii:ff:ss:bb + +class Ab: + + String attr + + + initializer(): + self.attr := ":empty" + print(self.attr) + + + initializer(Int x): + self.attr := ":i" + print(self.attr) + + initializer(Float x): + self.attr := ":f" + print(self.attr) + + initializer(String x): + self.attr := ":s" + print(self.attr) + + initializer(Bool x): + self.attr := ":b" + print(self.attr) + + + initializer(Int x1, Int x2): + self.attr := ":ii" + print(self.attr) + + initializer(Float x1, Float x2): + self.attr := ":ff" + print(self.attr) + + initializer(String x1, String x2): + self.attr := ":ss" + print(self.attr) + + initializer(Bool x1, Bool x2): + self.attr := ":bb" + print(self.attr) + +Ab empty := Ab() + +Ab i := Ab(42) +Ab f := Ab(1.3) +Ab s := Ab("Hallo") +Ab b := Ab(true) + +Ab ii := Ab(42, 24) +Ab ff := Ab(1.3, 3.1) +Ab ss := Ab("Hallo", "Welt") +Ab bb := Ab(true, false) diff --git a/src/test/resources/testPrograms/overloading/OverloadingConstructor1.output b/src/test/resources/testPrograms/overloading/OverloadingConstructor1.output new file mode 100644 index 0000000..e6178ca --- /dev/null +++ b/src/test/resources/testPrograms/overloading/OverloadingConstructor1.output @@ -0,0 +1 @@ +:empty:i:f:s:b:ii:ff:ss:bb \ No newline at end of file diff --git a/src/test/resources/testPrograms/overloading/OverloadingFunction1.monty b/src/test/resources/testPrograms/overloading/OverloadingFunction1.monty new file mode 100644 index 0000000..9ff6922 --- /dev/null +++ b/src/test/resources/testPrograms/overloading/OverloadingFunction1.monty @@ -0,0 +1,47 @@ +// Testing: Overloading of functions +// +// The correct overloaded function with predefined types must be called. +// +// Expected output: :No:i:s:f:b:ii:ss:ff:bb + +Bool function(): + print(":No") + return false + +Bool function(Int x): + print(":i") + return false +Bool function(String x): + print(":s") + return false +Bool function(Float x): + print(":f") + return false +Bool function(Bool x): + print(":b") + return false + +Bool function(Int x1, Int x2): + print(":ii") + return false +Bool function(String x1, String x2): + print(":ss") + return false +Bool function(Float x1, Float x2): + print(":ff") + return false +Bool function(Bool x1, Bool x2): + print(":bb") + return false + +function() + +function(42) +function("Hallo") +function(1.3) +function(true) + +function(42, 42) +function("Hallo", "Welt") +function(1.3, 3.1) +function(true, false) diff --git a/src/test/resources/testPrograms/overloading/OverloadingFunction1.output b/src/test/resources/testPrograms/overloading/OverloadingFunction1.output new file mode 100644 index 0000000..893566f --- /dev/null +++ b/src/test/resources/testPrograms/overloading/OverloadingFunction1.output @@ -0,0 +1 @@ +:No:i:s:f:b:ii:ss:ff:bb \ No newline at end of file diff --git a/src/test/resources/testPrograms/overloading/OverloadingFunction2.monty b/src/test/resources/testPrograms/overloading/OverloadingFunction2.monty new file mode 100644 index 0000000..3eb68e2 --- /dev/null +++ b/src/test/resources/testPrograms/overloading/OverloadingFunction2.monty @@ -0,0 +1,37 @@ +// Testing: Overloading of functions +// +// The correct overloaded function in combination with different blocks must +// be called. +// +// Expected output: :No2:i:s:f:b:No1 + +Bool function(): + print(":No1") + return false + +if true: + Bool function(): + print(":No2") + return false + + Bool function(Int x): + print(":i") + return false + Bool function(String x): + print(":s") + return false + Bool function(Float x): + print(":f") + return false + Bool function(Bool x): + print(":b") + return false + + function() + + function(42) + function("Hallo") + function(1.3) + function(true) + +function() diff --git a/src/test/resources/testPrograms/overloading/OverloadingFunction2.output b/src/test/resources/testPrograms/overloading/OverloadingFunction2.output new file mode 100644 index 0000000..a43cf6e --- /dev/null +++ b/src/test/resources/testPrograms/overloading/OverloadingFunction2.output @@ -0,0 +1 @@ +:No2:i:s:f:b:No1 \ No newline at end of file diff --git a/src/test/resources/testPrograms/overloading/OverloadingFunction3.monty b/src/test/resources/testPrograms/overloading/OverloadingFunction3.monty new file mode 100644 index 0000000..214315d --- /dev/null +++ b/src/test/resources/testPrograms/overloading/OverloadingFunction3.monty @@ -0,0 +1,28 @@ +// Testing: Overloading of functions. +// +// The correct overloaded function with user defined types must be called. +// +// Expected output: :A:B + +class Ab: + + Bool attr + + + initializer(): + self.attr := true + +class Ba: + + Bool attr + + + initializer(): + self.attr := true + +Bool function(Ab a): + print(":A") + return false + +Bool function(Ba b): + print(":B") + return false + +function(Ab()) +function(Ba()) diff --git a/src/test/resources/testPrograms/overloading/OverloadingFunction3.output b/src/test/resources/testPrograms/overloading/OverloadingFunction3.output new file mode 100644 index 0000000..996964b --- /dev/null +++ b/src/test/resources/testPrograms/overloading/OverloadingFunction3.output @@ -0,0 +1 @@ +:A:B \ No newline at end of file diff --git a/src/test/resources/testPrograms/overloading/OverloadingProcedure1.monty b/src/test/resources/testPrograms/overloading/OverloadingProcedure1.monty new file mode 100644 index 0000000..7b10435 --- /dev/null +++ b/src/test/resources/testPrograms/overloading/OverloadingProcedure1.monty @@ -0,0 +1,38 @@ +// Testing: Overloading of procedures +// +// The correct overloaded procedure with predefined types must be called. +// +// Expected output: :No:i:s:f:b:ii:ss:ff:bb + +procedure(): + print(":No") + +procedure(Int x): + print(":i") +procedure(String x): + print(":s") +procedure(Float x): + print(":f") +procedure(Bool x): + print(":b") + +procedure(Int x1, Int x2): + print(":ii") +procedure(String x1, String x2): + print(":ss") +procedure(Float x1, Float x2): + print(":ff") +procedure(Bool x1, Bool x2): + print(":bb") + +procedure() + +procedure(42) +procedure("Hallo") +procedure(1.3) +procedure(true) + +procedure(42, 42) +procedure("Hallo", "Welt") +procedure(1.3, 3.1) +procedure(true, false) diff --git a/src/test/resources/testPrograms/overloading/OverloadingProcedure1.output b/src/test/resources/testPrograms/overloading/OverloadingProcedure1.output new file mode 100644 index 0000000..893566f --- /dev/null +++ b/src/test/resources/testPrograms/overloading/OverloadingProcedure1.output @@ -0,0 +1 @@ +:No:i:s:f:b:ii:ss:ff:bb \ No newline at end of file diff --git a/src/test/resources/testPrograms/overloading/OverloadingProcedure2.monty b/src/test/resources/testPrograms/overloading/OverloadingProcedure2.monty new file mode 100644 index 0000000..e488ddb --- /dev/null +++ b/src/test/resources/testPrograms/overloading/OverloadingProcedure2.monty @@ -0,0 +1,31 @@ +// Testing: Overloading of procedures +// +// The correct overloaded procedure in combination with different blocks must +// be called. +// +// Expected output: :No2:i:s:f:b:No1 + +procedure(): + print(":No1") + +if true: + procedure(): + print(":No2") + + procedure(Int x): + print(":i") + procedure(String x): + print(":s") + procedure(Float x): + print(":f") + procedure(Bool x): + print(":b") + + procedure() + + procedure(42) + procedure("Hallo") + procedure(1.3) + procedure(true) + +procedure() diff --git a/src/test/resources/testPrograms/overloading/OverloadingProcedure2.output b/src/test/resources/testPrograms/overloading/OverloadingProcedure2.output new file mode 100644 index 0000000..a43cf6e --- /dev/null +++ b/src/test/resources/testPrograms/overloading/OverloadingProcedure2.output @@ -0,0 +1 @@ +:No2:i:s:f:b:No1 \ No newline at end of file diff --git a/src/test/resources/testPrograms/overloading/OverloadingProcedure3.monty b/src/test/resources/testPrograms/overloading/OverloadingProcedure3.monty new file mode 100644 index 0000000..b95be50 --- /dev/null +++ b/src/test/resources/testPrograms/overloading/OverloadingProcedure3.monty @@ -0,0 +1,26 @@ +// Testing: Overloading of procedures +// +// The correct overloaded procedure with user defined types must be called. +// +// Expected output: :A:B + +class Ab: + + Bool attr + + + initializer(): + self.attr := true + +class Ba: + + Bool attr + + + initializer(): + self.attr := true + +procedure(Ab a): + print(":A") + +procedure(Ba b): + print(":B") + +procedure(Ab()) +procedure(Ba()) diff --git a/src/test/resources/testPrograms/overloading/OverloadingProcedure3.output b/src/test/resources/testPrograms/overloading/OverloadingProcedure3.output new file mode 100644 index 0000000..996964b --- /dev/null +++ b/src/test/resources/testPrograms/overloading/OverloadingProcedure3.output @@ -0,0 +1 @@ +:A:B \ No newline at end of file diff --git a/src/test/resources/testPrograms/print/PrintBoolean.monty b/src/test/resources/testPrograms/print/PrintBoolean.monty new file mode 100644 index 0000000..8cf642e --- /dev/null +++ b/src/test/resources/testPrograms/print/PrintBoolean.monty @@ -0,0 +1,6 @@ +// Testing: The print function with boolean. +// +// Expected output: 10 + +print(true) +print(false) diff --git a/src/test/resources/testPrograms/print/PrintBoolean.output b/src/test/resources/testPrograms/print/PrintBoolean.output new file mode 100644 index 0000000..9a03714 --- /dev/null +++ b/src/test/resources/testPrograms/print/PrintBoolean.output @@ -0,0 +1 @@ +10 \ No newline at end of file diff --git a/src/test/resources/testPrograms/print/PrintChar.monty b/src/test/resources/testPrograms/print/PrintChar.monty new file mode 100644 index 0000000..8847cc9 --- /dev/null +++ b/src/test/resources/testPrograms/print/PrintChar.monty @@ -0,0 +1,8 @@ +// Testing: The print function with char. +// +// Expected output: HAHA + +print('H') +print('A') +print('H') +print('A') diff --git a/src/test/resources/testPrograms/print/PrintChar.output b/src/test/resources/testPrograms/print/PrintChar.output new file mode 100644 index 0000000..05f97d0 --- /dev/null +++ b/src/test/resources/testPrograms/print/PrintChar.output @@ -0,0 +1 @@ +HAHA \ No newline at end of file diff --git a/src/test/resources/testPrograms/print/PrintFloat.monty b/src/test/resources/testPrograms/print/PrintFloat.monty new file mode 100644 index 0000000..618fc86 --- /dev/null +++ b/src/test/resources/testPrograms/print/PrintFloat.monty @@ -0,0 +1,6 @@ +// Testing: The print function with float. +// +// Expected output: 01.3 + +print(0.0) +print(1.3) diff --git a/src/test/resources/testPrograms/print/PrintFloat.output b/src/test/resources/testPrograms/print/PrintFloat.output new file mode 100644 index 0000000..7056186 --- /dev/null +++ b/src/test/resources/testPrograms/print/PrintFloat.output @@ -0,0 +1 @@ +01.3 \ No newline at end of file diff --git a/src/test/resources/testPrograms/print/PrintInt.monty b/src/test/resources/testPrograms/print/PrintInt.monty new file mode 100644 index 0000000..ea8a6d4 --- /dev/null +++ b/src/test/resources/testPrograms/print/PrintInt.monty @@ -0,0 +1,6 @@ +// Testing: The print function with int. +// +// Expected output: 042 + +print(0) +print(42) diff --git a/src/test/resources/testPrograms/print/PrintInt.output b/src/test/resources/testPrograms/print/PrintInt.output new file mode 100644 index 0000000..9f73fc0 --- /dev/null +++ b/src/test/resources/testPrograms/print/PrintInt.output @@ -0,0 +1 @@ +042 \ No newline at end of file diff --git a/src/test/resources/testPrograms/print/PrintString.monty b/src/test/resources/testPrograms/print/PrintString.monty new file mode 100644 index 0000000..f2cff49 --- /dev/null +++ b/src/test/resources/testPrograms/print/PrintString.monty @@ -0,0 +1,6 @@ +// Testing: The print function with string. +// +// Expected output: Hallo + +print("") +print("Hallo") diff --git a/src/test/resources/testPrograms/print/PrintString.output b/src/test/resources/testPrograms/print/PrintString.output new file mode 100644 index 0000000..53f5007 --- /dev/null +++ b/src/test/resources/testPrograms/print/PrintString.output @@ -0,0 +1 @@ +Hallo \ No newline at end of file diff --git a/src/test/resources/testPrograms/print/PrintVariableBoolean.monty b/src/test/resources/testPrograms/print/PrintVariableBoolean.monty new file mode 100644 index 0000000..8274e22 --- /dev/null +++ b/src/test/resources/testPrograms/print/PrintVariableBoolean.monty @@ -0,0 +1,6 @@ +// Testing: The print function with a boolean variable. +// +// Expected output: 1 + +Bool var := true +print(var) diff --git a/src/test/resources/testPrograms/print/PrintVariableBoolean.output b/src/test/resources/testPrograms/print/PrintVariableBoolean.output new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/src/test/resources/testPrograms/print/PrintVariableBoolean.output @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/src/test/resources/testPrograms/print/PrintVariableChar.monty b/src/test/resources/testPrograms/print/PrintVariableChar.monty new file mode 100644 index 0000000..faafb99 --- /dev/null +++ b/src/test/resources/testPrograms/print/PrintVariableChar.monty @@ -0,0 +1,6 @@ +// Testing: The print function with a char variable. +// +// Expected output: M + +Char var := 'M' +print(var) diff --git a/src/test/resources/testPrograms/print/PrintVariableChar.output b/src/test/resources/testPrograms/print/PrintVariableChar.output new file mode 100644 index 0000000..ef6bce1 --- /dev/null +++ b/src/test/resources/testPrograms/print/PrintVariableChar.output @@ -0,0 +1 @@ +M \ No newline at end of file diff --git a/src/test/resources/testPrograms/print/PrintVariableFloat.monty b/src/test/resources/testPrograms/print/PrintVariableFloat.monty new file mode 100644 index 0000000..384d41e --- /dev/null +++ b/src/test/resources/testPrograms/print/PrintVariableFloat.monty @@ -0,0 +1,6 @@ +// Testing: The print function with a float variable. +// +// Expected output: 1.3 + +Float var := 1.3 +print(var) diff --git a/src/test/resources/testPrograms/print/PrintVariableFloat.output b/src/test/resources/testPrograms/print/PrintVariableFloat.output new file mode 100644 index 0000000..a58941b --- /dev/null +++ b/src/test/resources/testPrograms/print/PrintVariableFloat.output @@ -0,0 +1 @@ +1.3 \ No newline at end of file diff --git a/src/test/resources/testPrograms/print/PrintVariableInt.monty b/src/test/resources/testPrograms/print/PrintVariableInt.monty new file mode 100644 index 0000000..5ec4eee --- /dev/null +++ b/src/test/resources/testPrograms/print/PrintVariableInt.monty @@ -0,0 +1,6 @@ +// Testing: The print function with an int variable. +// +// Expected output: 42 + +Int var := 42 +print(var) diff --git a/src/test/resources/testPrograms/print/PrintVariableInt.output b/src/test/resources/testPrograms/print/PrintVariableInt.output new file mode 100644 index 0000000..f70d7bb --- /dev/null +++ b/src/test/resources/testPrograms/print/PrintVariableInt.output @@ -0,0 +1 @@ +42 \ No newline at end of file diff --git a/src/test/resources/testPrograms/print/PrintVariableString.monty b/src/test/resources/testPrograms/print/PrintVariableString.monty new file mode 100644 index 0000000..0b1fb3a --- /dev/null +++ b/src/test/resources/testPrograms/print/PrintVariableString.monty @@ -0,0 +1,6 @@ +// Testing: The print function with a string variable. +// +// Expected output: Hallo + +String var := "Hallo" +print(var) diff --git a/src/test/resources/testPrograms/print/PrintVariableString.output b/src/test/resources/testPrograms/print/PrintVariableString.output new file mode 100644 index 0000000..53f5007 --- /dev/null +++ b/src/test/resources/testPrograms/print/PrintVariableString.output @@ -0,0 +1 @@ +Hallo \ No newline at end of file diff --git a/src/test/resources/testPrograms/print/PrintWhitespaces.monty b/src/test/resources/testPrograms/print/PrintWhitespaces.monty new file mode 100644 index 0000000..79288a7 --- /dev/null +++ b/src/test/resources/testPrograms/print/PrintWhitespaces.monty @@ -0,0 +1,11 @@ +// Testing: Printing of Whitespaces +// +// We don't want whitespace in the output to be trimmed or changed in any way. +// To that end we print a series of whitespace characters and test for them +// in order to verify that they haven't been modified. +// +// Expected output: + +String str := " " +print(str) +print(" ") \ No newline at end of file diff --git a/src/test/resources/testPrograms/print/PrintWhitespaces.output b/src/test/resources/testPrograms/print/PrintWhitespaces.output new file mode 100644 index 0000000..a0e231e --- /dev/null +++ b/src/test/resources/testPrograms/print/PrintWhitespaces.output @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/test/resources/testPrograms/print/PrintWhitespaces2.monty.ignore b/src/test/resources/testPrograms/print/PrintWhitespaces2.monty.ignore new file mode 100644 index 0000000..bae7314 --- /dev/null +++ b/src/test/resources/testPrograms/print/PrintWhitespaces2.monty.ignore @@ -0,0 +1,15 @@ +// Testing: Printing of Whitespaces +// +// We don't want whitespace in the output to be trimmed or changed in any way. +// To that end we print a series of whitespace characters and test for them +// in order to verify that they haven't been modified. In addition to ordinary +// whitespace, we have inserted some whitespace characters via escape sequences +// to cater for newlines and tabs. +// +// Expected output: + +String str := " " +print(str) +print("\n") +print("\n") +print(" \t") \ No newline at end of file diff --git a/src/test/resources/testPrograms/print/PrintWhitespaces2.output b/src/test/resources/testPrograms/print/PrintWhitespaces2.output new file mode 100644 index 0000000..d7fe131 --- /dev/null +++ b/src/test/resources/testPrograms/print/PrintWhitespaces2.output @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/test/resources/testPrograms/scoping/Redeclaration.monty b/src/test/resources/testPrograms/scoping/Redeclaration.monty new file mode 100644 index 0000000..562d065 --- /dev/null +++ b/src/test/resources/testPrograms/scoping/Redeclaration.monty @@ -0,0 +1,17 @@ +// Testing: Scope +// +// A Variable must be redeclarable within a new Scope. +// +// Expected output: outerinnerinnerinnerouter + +Int counter := 0 +String ausgabe := "outer" + +print(ausgabe) + +while counter < 3: + String ausgabe := "inner" + print(ausgabe) + counter := counter + 1 + +print(ausgabe) \ No newline at end of file diff --git a/src/test/resources/testPrograms/scoping/Redeclaration.output b/src/test/resources/testPrograms/scoping/Redeclaration.output new file mode 100644 index 0000000..0190767 --- /dev/null +++ b/src/test/resources/testPrograms/scoping/Redeclaration.output @@ -0,0 +1 @@ +outerinnerinnerinnerouter \ No newline at end of file diff --git a/src/test/resources/testPrograms/scoping/SimultaneouslyVisibleFunctions.monty b/src/test/resources/testPrograms/scoping/SimultaneouslyVisibleFunctions.monty new file mode 100644 index 0000000..b5e83c6 --- /dev/null +++ b/src/test/resources/testPrograms/scoping/SimultaneouslyVisibleFunctions.monty @@ -0,0 +1,14 @@ +// Testing: Lexical scoping / Simultaneous visibility +// +// The functions caller and callee must be callable before their declaration, +// because of their simultaneous visibility. +// +// Expected output: reihenfolge ist egal + +caller() + +caller(): + callee() + +callee(): + print("reihenfolge ist egal") \ No newline at end of file diff --git a/src/test/resources/testPrograms/scoping/SimultaneouslyVisibleFunctions.output b/src/test/resources/testPrograms/scoping/SimultaneouslyVisibleFunctions.output new file mode 100644 index 0000000..32c3735 --- /dev/null +++ b/src/test/resources/testPrograms/scoping/SimultaneouslyVisibleFunctions.output @@ -0,0 +1 @@ +reihenfolge ist egal \ No newline at end of file diff --git a/src/test/resources/testPrograms/scoping/SimultaneouslyVisibleObjects.monty b/src/test/resources/testPrograms/scoping/SimultaneouslyVisibleObjects.monty new file mode 100644 index 0000000..8049270 --- /dev/null +++ b/src/test/resources/testPrograms/scoping/SimultaneouslyVisibleObjects.monty @@ -0,0 +1,15 @@ +// Testing: Lexical scoping / Simultaneous visibility +// +// The class attributes einBaum and einAst must be visible before their lexical +// declaration for the reason that their scope is created by class instantiation. +// +// Expected output: reihenfolge ist equal + +Wald einWald := Wald() +print(einWald.einBaum.einAst) + +class Baum: + + String einAst := "reihenfolge ist equal" + +class Wald: + + Baum einBaum := Baum() diff --git a/src/test/resources/testPrograms/scoping/SimultaneouslyVisibleObjects.output b/src/test/resources/testPrograms/scoping/SimultaneouslyVisibleObjects.output new file mode 100644 index 0000000..265301d --- /dev/null +++ b/src/test/resources/testPrograms/scoping/SimultaneouslyVisibleObjects.output @@ -0,0 +1 @@ +reihenfolge ist equal \ No newline at end of file diff --git a/src/test/resources/testPrograms/scoping/VariableAccess.monty b/src/test/resources/testPrograms/scoping/VariableAccess.monty new file mode 100644 index 0000000..3329c88 --- /dev/null +++ b/src/test/resources/testPrograms/scoping/VariableAccess.monty @@ -0,0 +1,13 @@ +// Testing: Lexical scoping +// +// answer is not declared within function calcAnswerToLifeAndStuff, +// so answer from outer scope is accessed. +// +// Expected output: 42 + +Int answer := 42 + +calcAnswerToLifeAndStuff(): + print(answer) + +calcAnswerToLifeAndStuff() \ No newline at end of file diff --git a/src/test/resources/testPrograms/scoping/VariableAccess.output b/src/test/resources/testPrograms/scoping/VariableAccess.output new file mode 100644 index 0000000..f70d7bb --- /dev/null +++ b/src/test/resources/testPrograms/scoping/VariableAccess.output @@ -0,0 +1 @@ +42 \ No newline at end of file diff --git a/src/test/resources/testPrograms/variables/GlobalVariableBoolean1.monty b/src/test/resources/testPrograms/variables/GlobalVariableBoolean1.monty new file mode 100644 index 0000000..3db7cca --- /dev/null +++ b/src/test/resources/testPrograms/variables/GlobalVariableBoolean1.monty @@ -0,0 +1,13 @@ +// Testing: VariableDeclaration and VariableAccess in a ModuleDeclaration. +// +// The boolean variable must be visible and readable inside the procedure +// output(). +// +// Expected output: 1 + +Bool hello := true + +output(): + print(hello) + +output() diff --git a/src/test/resources/testPrograms/variables/GlobalVariableBoolean1.output b/src/test/resources/testPrograms/variables/GlobalVariableBoolean1.output new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/src/test/resources/testPrograms/variables/GlobalVariableBoolean1.output @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/src/test/resources/testPrograms/variables/GlobalVariableBoolean2.monty b/src/test/resources/testPrograms/variables/GlobalVariableBoolean2.monty new file mode 100644 index 0000000..c270251 --- /dev/null +++ b/src/test/resources/testPrograms/variables/GlobalVariableBoolean2.monty @@ -0,0 +1,14 @@ +// Testing: VariableDeclaration and VariableAccess in a ModuleDeclaration. +// +// The boolean variable must be visible, writable and readable inside the +// procedure output(). +// +// Expected output: 1 + +Bool hello + +output(): + hello := true + print(hello) + +output() diff --git a/src/test/resources/testPrograms/variables/GlobalVariableBoolean2.output b/src/test/resources/testPrograms/variables/GlobalVariableBoolean2.output new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/src/test/resources/testPrograms/variables/GlobalVariableBoolean2.output @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/src/test/resources/testPrograms/variables/GlobalVariableChar1.monty b/src/test/resources/testPrograms/variables/GlobalVariableChar1.monty new file mode 100644 index 0000000..626a650 --- /dev/null +++ b/src/test/resources/testPrograms/variables/GlobalVariableChar1.monty @@ -0,0 +1,13 @@ +// Testing: VariableDeclaration and VariableAccess in a ModuleDeclaration. +// +// The char variable must be visible and readable inside the procedure +// output(). +// +// Expected output: M + +Char hello := 'M' + +output(): + print(hello) + +output() diff --git a/src/test/resources/testPrograms/variables/GlobalVariableChar1.output b/src/test/resources/testPrograms/variables/GlobalVariableChar1.output new file mode 100644 index 0000000..ef6bce1 --- /dev/null +++ b/src/test/resources/testPrograms/variables/GlobalVariableChar1.output @@ -0,0 +1 @@ +M \ No newline at end of file diff --git a/src/test/resources/testPrograms/variables/GlobalVariableChar2.monty b/src/test/resources/testPrograms/variables/GlobalVariableChar2.monty new file mode 100644 index 0000000..fdfb746 --- /dev/null +++ b/src/test/resources/testPrograms/variables/GlobalVariableChar2.monty @@ -0,0 +1,14 @@ +// Testing: VariableDeclaration and VariableAccess in a ModuleDeclaration. +// +// The char variable must be visible, writable and readable inside the +// procedure output(). +// +// Expected output: M + +Char hello + +output(): + hello := 'M' + print(hello) + +output() diff --git a/src/test/resources/testPrograms/variables/GlobalVariableChar2.output b/src/test/resources/testPrograms/variables/GlobalVariableChar2.output new file mode 100644 index 0000000..ef6bce1 --- /dev/null +++ b/src/test/resources/testPrograms/variables/GlobalVariableChar2.output @@ -0,0 +1 @@ +M \ No newline at end of file diff --git a/src/test/resources/testPrograms/variables/GlobalVariableFloat1.monty b/src/test/resources/testPrograms/variables/GlobalVariableFloat1.monty new file mode 100644 index 0000000..d674c59 --- /dev/null +++ b/src/test/resources/testPrograms/variables/GlobalVariableFloat1.monty @@ -0,0 +1,13 @@ +// Testing: VariableDeclaration and VariableAccess in a ModuleDeclaration. +// +// The float variable must be visible and readable inside the procedure +// output(). +// +// Expected output: 1.3 + +Float hello := 1.3 + +output(): + print(hello) + +output() diff --git a/src/test/resources/testPrograms/variables/GlobalVariableFloat1.output b/src/test/resources/testPrograms/variables/GlobalVariableFloat1.output new file mode 100644 index 0000000..a58941b --- /dev/null +++ b/src/test/resources/testPrograms/variables/GlobalVariableFloat1.output @@ -0,0 +1 @@ +1.3 \ No newline at end of file diff --git a/src/test/resources/testPrograms/variables/GlobalVariableFloat2.monty b/src/test/resources/testPrograms/variables/GlobalVariableFloat2.monty new file mode 100644 index 0000000..8618f58 --- /dev/null +++ b/src/test/resources/testPrograms/variables/GlobalVariableFloat2.monty @@ -0,0 +1,14 @@ +// Testing: VariableDeclaration and VariableAccess in a ModuleDeclaration. +// +// The float variable must be visible, writable and readable inside the +// procedure output(). +// +// Expected output: 1.3 + +Float hello + +output(): + hello := 1.3 + print(hello) + +output() diff --git a/src/test/resources/testPrograms/variables/GlobalVariableFloat2.output b/src/test/resources/testPrograms/variables/GlobalVariableFloat2.output new file mode 100644 index 0000000..a58941b --- /dev/null +++ b/src/test/resources/testPrograms/variables/GlobalVariableFloat2.output @@ -0,0 +1 @@ +1.3 \ No newline at end of file diff --git a/src/test/resources/testPrograms/variables/GlobalVariableInt1.monty b/src/test/resources/testPrograms/variables/GlobalVariableInt1.monty new file mode 100644 index 0000000..f48e6a2 --- /dev/null +++ b/src/test/resources/testPrograms/variables/GlobalVariableInt1.monty @@ -0,0 +1,13 @@ +// Testing: VariableDeclaration and VariableAccess in a ModuleDeclaration. +// +// The int variable must be visible and readable inside the procedure +// output(). +// +// Expected output: 42 + +Int hello := 42 + +output(): + print(hello) + +output() diff --git a/src/test/resources/testPrograms/variables/GlobalVariableInt1.output b/src/test/resources/testPrograms/variables/GlobalVariableInt1.output new file mode 100644 index 0000000..f70d7bb --- /dev/null +++ b/src/test/resources/testPrograms/variables/GlobalVariableInt1.output @@ -0,0 +1 @@ +42 \ No newline at end of file diff --git a/src/test/resources/testPrograms/variables/GlobalVariableInt2.monty b/src/test/resources/testPrograms/variables/GlobalVariableInt2.monty new file mode 100644 index 0000000..4c13e8e --- /dev/null +++ b/src/test/resources/testPrograms/variables/GlobalVariableInt2.monty @@ -0,0 +1,14 @@ +// Testing: VariableDeclaration and VariableAccess in a ModuleDeclaration. +// +// The int variable must be visible, writable and readable inside the +// procedure output(). +// +// Expected output: 42 + +Int hello + +output(): + hello := 42 + print(hello) + +output() diff --git a/src/test/resources/testPrograms/variables/GlobalVariableInt2.output b/src/test/resources/testPrograms/variables/GlobalVariableInt2.output new file mode 100644 index 0000000..f70d7bb --- /dev/null +++ b/src/test/resources/testPrograms/variables/GlobalVariableInt2.output @@ -0,0 +1 @@ +42 \ No newline at end of file diff --git a/src/test/resources/testPrograms/variables/GlobalVariableString1.monty b/src/test/resources/testPrograms/variables/GlobalVariableString1.monty new file mode 100644 index 0000000..57eb5c0 --- /dev/null +++ b/src/test/resources/testPrograms/variables/GlobalVariableString1.monty @@ -0,0 +1,13 @@ +// Testing: VariableDeclaration and VariableAccess in a ModuleDeclaration. +// +// The string variable must be visible and readable inside the procedure +// output(). +// +// Expected output: Hello + +String hello := "Hello" + +output(): + print(hello) + +output() diff --git a/src/test/resources/testPrograms/variables/GlobalVariableString1.output b/src/test/resources/testPrograms/variables/GlobalVariableString1.output new file mode 100644 index 0000000..5ab2f8a --- /dev/null +++ b/src/test/resources/testPrograms/variables/GlobalVariableString1.output @@ -0,0 +1 @@ +Hello \ No newline at end of file diff --git a/src/test/resources/testPrograms/variables/GlobalVariableString2.monty b/src/test/resources/testPrograms/variables/GlobalVariableString2.monty new file mode 100644 index 0000000..1a48b72 --- /dev/null +++ b/src/test/resources/testPrograms/variables/GlobalVariableString2.monty @@ -0,0 +1,14 @@ +// Testing: VariableDeclaration and VariableAccess in a ModuleDeclaration. +// +// The string variable must be visible, writable and readable inside the +// procedure output(). +// +// Expected output: Hello + +String hello + +output(): + hello := "Hello" + print(hello) + +output() diff --git a/src/test/resources/testPrograms/variables/GlobalVariableString2.output b/src/test/resources/testPrograms/variables/GlobalVariableString2.output new file mode 100644 index 0000000..5ab2f8a --- /dev/null +++ b/src/test/resources/testPrograms/variables/GlobalVariableString2.output @@ -0,0 +1 @@ +Hello \ No newline at end of file