From ba2b23713937a89eca241473dd4f3c700a01beb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mauro=20Balad=C3=A9s?= Date: Thu, 1 Feb 2024 14:25:43 +0000 Subject: [PATCH] Prepared files for rewrite --- app/cli.cc | 276 - app/cli.h | 116 - app/commands/bench.h | 85 - app/commands/build.h | 107 - app/commands/docgen.h | 60 - app/commands/files/EXECUTABLE_MAIN | 7 - app/commands/files/LIBRARY_MAIN | 6 - app/commands/files/LIBRARY_TEST | 12 - app/commands/files/_GITIGNORE | 2 - app/commands/files/assets.h | 38 - app/commands/files/compile_init_files.sh | 10 - app/commands/init.h | 122 - app/commands/pm.h | 29 - app/commands/run.h | 61 - app/commands/test.h | 84 - app/crash_handler.h | 513 - app/main.cc | 69 - build_scripts/build-snowball.sh | 54 - build_scripts/clean.sh | 14 - build_scripts/cross-compile-windows.sh | 18 - build_scripts/dbg.sh | 12 - build_scripts/install_deps.sh | 14 - build_scripts/install_stdlib.sh | 5 - build_scripts/release.sh | 22 - build_scripts/release_build.sh | 61 - build_scripts/toolchains-windows.cmake | 15 - installer/main.nsh | 100 - src/SourceInfo.h | 33 - src/ValueVisitor/Visitor.h | 44 - src/ast/cache/Cache.h | 32 - src/ast/cache/FunctionCache.cc | 92 - src/ast/cache/FunctionCache.h | 81 - src/ast/cache/ModuleCache.cc | 21 - src/ast/cache/ModuleCache.h | 37 - src/ast/cache/TypeCache.cc | 45 - src/ast/cache/TypeCache.h | 75 - src/ast/errors/error.h | 36 - src/ast/syntax/accepts.cc | 14 - src/ast/syntax/common.h | 480 - src/ast/syntax/exprs.cc | 184 - src/ast/syntax/nodes.h | 1455 -- src/ast/syntax/stmts.cc | 111 - src/ast/types/BaseType.cc | 36 - src/ast/types/BaseType.h | 88 - src/ast/types/DefinedType.cc | 157 - src/ast/types/DefinedType.h | 159 - src/ast/types/EnumType.cc | 132 - src/ast/types/EnumType.h | 115 - src/ast/types/FunctionType.cc | 76 - src/ast/types/FunctionType.h | 129 - src/ast/types/Interface.cc | 112 - src/ast/types/Interface.h | 131 - src/ast/types/PointerType.cc | 55 - src/ast/types/PointerType.h | 74 - src/ast/types/PrimitiveTypes.cc | 7 - src/ast/types/PrimitiveTypes.h | 126 - src/ast/types/ReferenceType.cc | 53 - src/ast/types/ReferenceType.h | 74 - src/ast/types/Type.cc | 24 - src/ast/types/Type.h | 118 - src/ast/types/TypeAlias.cc | 45 - src/ast/types/TypeAlias.h | 63 - src/ast/visitor/ASTContext.h | 139 - src/ast/visitor/Visitor.cc | 15 - src/ast/visitor/Visitor.h | 30 - src/builder/linker/Linker.h | 109 - src/builder/linker/common/ld.cc | 46 - src/builder/linker/linux/ld.cc | 131 - src/builder/linker/macos/ld.cc | 55 - src/builder/llvm/DIHelpers.cc | 167 - src/builder/llvm/LLVMBuilder.cc | 306 - src/builder/llvm/LLVMBuilder.h | 525 - src/builder/llvm/LLVMIRChunk.h | 21 - src/builder/llvm/addGlobalVariable.cc | 74 - src/builder/llvm/allocateObject.cc | 18 - src/builder/llvm/buildArgument.cc | 19 - src/builder/llvm/buildBlock.cc | 17 - src/builder/llvm/buildCall.cc | 197 - src/builder/llvm/buildCast.cc | 75 - src/builder/llvm/buildConditional.cc | 32 - src/builder/llvm/buildConstant.cc | 30 - src/builder/llvm/buildDereferenceTo.cc | 21 - src/builder/llvm/buildEnumInit.cc | 17 - src/builder/llvm/buildFunc.cc | 268 - src/builder/llvm/buildIndexExtract.cc | 35 - src/builder/llvm/buildIntrinsic.cc | 52 - src/builder/llvm/buildLLVMFunction.cc | 112 - src/builder/llvm/buildLoopFlow.cc | 25 - src/builder/llvm/buildOperator.cc | 257 - src/builder/llvm/buildReferenceTo.cc | 38 - src/builder/llvm/buildReturn.cc | 64 - src/builder/llvm/buildSwitch.cc | 92 - src/builder/llvm/buildThrow.cc | 22 - src/builder/llvm/buildTryCatch.cc | 142 - src/builder/llvm/buildValueExtract.cc | 31 - src/builder/llvm/buildVariable.cc | 19 - src/builder/llvm/buildVariableDecl.cc | 68 - src/builder/llvm/buildWhileLoop.cc | 65 - src/builder/llvm/call.cc | 25 - src/builder/llvm/createBenchmark.cc | 75 - src/builder/llvm/createCondBr.cc | 22 - src/builder/llvm/createEnumInit.cc | 36 - src/builder/llvm/createException.cc | 27 - src/builder/llvm/createLLVMFunction.cc | 82 - src/builder/llvm/createTests.cc | 156 - src/builder/llvm/createVirtualTable.cc | 54 - src/builder/llvm/getAllocaFunction.cc | 26 - src/builder/llvm/getGlobalCTOR.cc | 55 - src/builder/llvm/getLambdaContextType.cc | 17 - src/builder/llvm/getPrintfFunction.cc | 19 - src/builder/llvm/getSharedLibraryName.cc | 21 - src/builder/llvm/getThrowFunction.cc | 19 - src/builder/llvm/getTypeInfoType.cc | 15 - src/builder/llvm/getVtableType.cc | 21 - src/builder/llvm/helpers/emitObjectFile.cc | 57 - src/builder/llvm/helpers/optimizeModule.cc | 142 - src/builder/llvm/initializeRuntime.cc | 77 - src/builder/llvm/initializeVariable.cc | 48 - src/builder/llvm/llvmTypes.cc | 152 - src/builder/llvm/setDebugInfoLoc.cc | 29 - src/builder/llvm/setPersonalityFunction.cc | 33 - src/builder/llvm/toBool.cc | 30 - src/builder/llvm/utils/typeIdxLookup.cc | 21 - src/builder/llvm/varFetchImpl.h | 37 - src/builder/sn-ir/SnowballIREmitter.cc | 237 - src/builder/sn-ir/SnowballIREmitter.h | 92 - src/common.h | 52 - src/compiler.cc | 287 - src/compiler.h | 119 - src/constants.h | 317 - src/defs/accepts.def | 36 - src/defs/ct.def | 12 - src/defs/operators.def | 48 - src/defs/visits.def | 30 - src/errors.cc | 164 - src/errors.h | 129 - src/export.hpp | 42 - src/ir/IdMixin.cc | 13 - src/ir/ModuleHolder.h | 27 - src/ir/builder/IRBuilder.cc | 209 - src/ir/builder/IRBuilder.h | 223 - src/ir/id.h | 43 - src/ir/module/MainModule.h | 55 - src/ir/module/Module.h | 83 - src/ir/module/Modules.cc | 26 - src/ir/values/Argument.h | 51 - src/ir/values/Body.h | 44 - src/ir/values/Call.h | 108 - src/ir/values/Cast.h | 42 - src/ir/values/Conditional.h | 53 - src/ir/values/Constants.h | 112 - src/ir/values/Dereference.h | 41 - src/ir/values/EnumInit.h | 42 - src/ir/values/Func.cc | 118 - src/ir/values/Func.h | 266 - src/ir/values/IndexExtract.h | 58 - src/ir/values/LoopFlow.h | 41 - src/ir/values/ReferenceTo.h | 41 - src/ir/values/Return.h | 42 - src/ir/values/Switch.h | 72 - src/ir/values/Throw.h | 44 - src/ir/values/TryCatch.h | 55 - src/ir/values/Value.h | 46 - src/ir/values/ValueExtract.h | 38 - src/ir/values/Variable.h | 65 - src/ir/values/VariableDeclaration.h | 54 - src/ir/values/WhileLoop.h | 65 - src/ir/values/all.h | 22 - src/lexer/lexer.cc | 777 - src/lexer/lexer.h | 53 - src/lexer/tokens/token.h | 335 - src/os/Driver.h | 29 - src/os/Driver/getOutputFilename.cc | 55 - src/os/Driver/run.cc | 15 - src/parser/Parser.cc | 47 - src/parser/Parser.h | 387 - src/parser/buildOperatorTree.cc | 158 - src/parser/parseAttributes.cc | 101 - src/parser/parseBlock.cc | 30 - src/parser/parseBlockOrStmt.cc | 23 - src/parser/parseClass.cc | 291 - src/parser/parseComment.cc | 65 - src/parser/parseConditional.cc | 41 - src/parser/parseConstant.cc | 61 - src/parser/parseEnum.cc | 86 - src/parser/parseExpr.cc | 276 - src/parser/parseForLoop.cc | 66 - src/parser/parseFunction.cc | 581 - src/parser/parseFunctionCall.cc | 42 - src/parser/parseGenericExpr.cc | 44 - src/parser/parseGenericParams.cc | 64 - src/parser/parseGlobal.cc | 120 - src/parser/parseIdentifier.cc | 39 - src/parser/parseImportStatement.cc | 80 - src/parser/parseLoopControl.cc | 32 - src/parser/parseMacro.cc | 93 - src/parser/parseNamespace.cc | 29 - src/parser/parseReturn.cc | 21 - src/parser/parseStatement.cc | 114 - src/parser/parseStructure.cc | 78 - src/parser/parseSwitch.cc | 118 - src/parser/parseThrow.cc | 20 - src/parser/parseTryCatch.cc | 36 - src/parser/parseType.cc | 122 - src/parser/parseTypeAlias.cc | 39 - src/parser/parseVariable.cc | 62 - src/parser/parseWhereClause.cc | 22 - src/parser/parseWhile.cc | 41 - src/pm/Manager.cc | 188 - src/pm/Manager.h | 68 - src/services/ImportCache.cc | 29 - src/services/ImportCache.h | 37 - src/services/ImportService.cc | 80 - src/services/ImportService.h | 88 - src/services/OperatorService.cc | 33 - src/services/OperatorService.h | 80 - src/sourceInfo/DBGSourceInfo.cc | 69 - src/sourceInfo/DBGSourceInfo.h | 80 - src/sourceInfo/SourcedObject.h | 35 - src/utils/colors.cc | 83 - src/utils/colors.h | 88 - src/utils/logger.cc | 84 - src/utils/logger.h | 38 - src/utils/utils.cc | 159 - src/utils/utils.h | 163 - src/vendor/pretty_print.hpp | 442 - src/vendor/toml.hpp | 17174 ---------------- src/visitors/Analyzer.h | 76 - src/visitors/MacroInstance.h | 34 - src/visitors/TransformContext.cc | 85 - src/visitors/TransformContext.h | 216 - src/visitors/TransformItem.h | 153 - src/visitors/TransformState.h | 35 - src/visitors/Transformer.cc | 97 - src/visitors/Transformer.h | 571 - src/visitors/TypeChecker.cc | 806 - src/visitors/TypeChecker.h | 125 - src/visitors/analyzers/DAV/Block.cc | 25 - .../DAV/Expression/BinaryOperator.cc | 46 - .../analyzers/DAV/Expression/Identifier.cc | 33 - .../analyzers/DAV/Expression/Index.cc | 39 - .../DAV/Expression/LambdaFunction.cc | 19 - src/visitors/analyzers/DAV/Macro.cc | 18 - src/visitors/analyzers/DAV/MiddlePlace.cc | 37 - .../analyzers/DAV/Statements/Conditional.cc | 38 - .../analyzers/DAV/Statements/ForLoop.cc | 19 - .../analyzers/DAV/Statements/FunctionDef.cc | 56 - .../analyzers/DAV/Statements/Switch.cc | 19 - .../analyzers/DAV/Statements/TryCatch.cc | 21 - .../analyzers/DAV/Statements/VariableDecl.cc | 19 - .../analyzers/DAV/Statements/WhileLoop.cc | 18 - .../DAV/Statements/visitConstructor.cc | 20 - src/visitors/analyzers/DAV/defaults.cc | 18 - src/visitors/analyzers/DAVUtils.cc | 37 - src/visitors/analyzers/DefinitveAssigment.h | 209 - src/visitors/documentation/DocGen.cc | 148 - src/visitors/documentation/DocGen.h | 175 - src/visitors/documentation/DocTemplates.cc | 791 - src/visitors/documentation/DocTemplates.h | 143 - .../transform/utils/assertSizedType.cc | 38 - src/visitors/transform/utils/bodyReturns.cc | 50 - src/visitors/transform/utils/canCast.cc | 46 - .../transform/utils/createIdentifierName.cc | 43 - .../transform/utils/createModuleAliases.cc | 29 - .../utils/createObjectConstructor.cc | 60 - .../transform/utils/deduceFunction.cc | 157 - .../transform/utils/executeGenericTests.cc | 74 - .../transform/utils/generate_equilizers.h | 17 - .../transform/utils/getActualFunction.cc | 20 - .../transform/utils/getBestFittingFunction.cc | 133 - .../transform/utils/getBooleanValue.cc | 19 - .../transform/utils/getBuiltinTypeUUID.cc | 37 - .../transform/utils/getExpansionData.cc | 18 - src/visitors/transform/utils/getFromIndex.cc | 250 - src/visitors/transform/utils/getFunction.cc | 180 - .../transform/utils/getFunctionType.cc | 22 - src/visitors/transform/utils/getLLVMBody.cc | 44 - src/visitors/transform/utils/getMemberList.cc | 48 - .../transform/utils/getNiceBaseName.cc | 35 - src/visitors/transform/utils/getNiceName.cc | 17 - .../transform/utils/implementTypes.cc | 128 - .../transform/utils/initializeCoreRuntime.cc | 28 - .../utils/initializePerModuleMacros.cc | 73 - .../transform/utils/isInClassContext.cc | 29 - .../transform/utils/isInModuleContext.cc | 15 - .../transform/utils/shouldReturnOverload.cc | 28 - .../transform/utils/transformClass.cc | 264 - .../transform/utils/transformConstructor.cc | 75 - src/visitors/transform/utils/transformEnum.cc | 123 - .../transform/utils/transformFunction.cc | 165 - .../transform/utils/transformIdentifier.cc | 110 - .../transform/utils/transformMacro.cc | 167 - .../transform/utils/transformMainFunction.cc | 43 - .../transform/utils/transformSpecialType.cc | 117 - src/visitors/transform/utils/transformType.cc | 199 - .../transform/utils/transformTypeAlias.cc | 83 - .../transform/utils/transformTypeExtension.cc | 198 - .../transform/utils/transformTypeFromBase.cc | 47 - src/visitors/transform/utils/tryCast.cc | 25 - .../transform/utils/typeGenericMatch.cc | 41 - src/visitors/transform/visits/Block.cc | 20 - .../transform/visits/Expression/BinaryOp.cc | 67 - .../transform/visits/Expression/Cast.cc | 19 - .../visits/Expression/ConstantValue.cc | 120 - .../visits/Expression/FunctionCall.cc | 218 - .../visits/Expression/GenericIdentifier.cc | 45 - .../transform/visits/Expression/Identifier.cc | 61 - .../transform/visits/Expression/Index.cc | 104 - .../visits/Expression/LambdaFunction.cc | 73 - .../visits/Expression/NewInstance.cc | 41 - .../visits/Expression/PseudoVariable.cc | 156 - src/visitors/transform/visits/Macro.cc | 37 - .../transform/visits/Statement/Conditional.cc | 21 - .../transform/visits/Statement/DefinedType.cc | 42 - .../transform/visits/Statement/Enum.cc | 34 - .../transform/visits/Statement/ForLoop.cc | 96 - .../transform/visits/Statement/FunctionDef.cc | 126 - .../transform/visits/Statement/ImportStmt.cc | 175 - .../transform/visits/Statement/LoopFlow.cc | 18 - .../transform/visits/Statement/Namespace.cc | 46 - .../transform/visits/Statement/Return.cc | 48 - .../transform/visits/Statement/Switch.cc | 154 - .../transform/visits/Statement/Throw.cc | 16 - .../transform/visits/Statement/TryCatch.cc | 37 - .../transform/visits/Statement/TypeAlias.cc | 39 - .../visits/Statement/VariableDecl.cc | 94 - .../transform/visits/Statement/WhileLoop.cc | 26 - 327 files changed, 47905 deletions(-) delete mode 100644 app/cli.cc delete mode 100644 app/cli.h delete mode 100644 app/commands/bench.h delete mode 100644 app/commands/build.h delete mode 100644 app/commands/docgen.h delete mode 100644 app/commands/files/EXECUTABLE_MAIN delete mode 100644 app/commands/files/LIBRARY_MAIN delete mode 100644 app/commands/files/LIBRARY_TEST delete mode 100644 app/commands/files/_GITIGNORE delete mode 100644 app/commands/files/assets.h delete mode 100644 app/commands/files/compile_init_files.sh delete mode 100644 app/commands/init.h delete mode 100644 app/commands/pm.h delete mode 100644 app/commands/run.h delete mode 100644 app/commands/test.h delete mode 100644 app/crash_handler.h delete mode 100644 app/main.cc delete mode 100644 build_scripts/build-snowball.sh delete mode 100644 build_scripts/clean.sh delete mode 100644 build_scripts/cross-compile-windows.sh delete mode 100755 build_scripts/dbg.sh delete mode 100644 build_scripts/install_deps.sh delete mode 100644 build_scripts/install_stdlib.sh delete mode 100644 build_scripts/release.sh delete mode 100644 build_scripts/release_build.sh delete mode 100644 build_scripts/toolchains-windows.cmake delete mode 100644 installer/main.nsh delete mode 100644 src/SourceInfo.h delete mode 100644 src/ValueVisitor/Visitor.h delete mode 100644 src/ast/cache/Cache.h delete mode 100644 src/ast/cache/FunctionCache.cc delete mode 100644 src/ast/cache/FunctionCache.h delete mode 100644 src/ast/cache/ModuleCache.cc delete mode 100644 src/ast/cache/ModuleCache.h delete mode 100644 src/ast/cache/TypeCache.cc delete mode 100644 src/ast/cache/TypeCache.h delete mode 100644 src/ast/errors/error.h delete mode 100644 src/ast/syntax/accepts.cc delete mode 100644 src/ast/syntax/common.h delete mode 100644 src/ast/syntax/exprs.cc delete mode 100644 src/ast/syntax/nodes.h delete mode 100644 src/ast/syntax/stmts.cc delete mode 100644 src/ast/types/BaseType.cc delete mode 100644 src/ast/types/BaseType.h delete mode 100644 src/ast/types/DefinedType.cc delete mode 100644 src/ast/types/DefinedType.h delete mode 100644 src/ast/types/EnumType.cc delete mode 100644 src/ast/types/EnumType.h delete mode 100644 src/ast/types/FunctionType.cc delete mode 100644 src/ast/types/FunctionType.h delete mode 100644 src/ast/types/Interface.cc delete mode 100644 src/ast/types/Interface.h delete mode 100644 src/ast/types/PointerType.cc delete mode 100644 src/ast/types/PointerType.h delete mode 100644 src/ast/types/PrimitiveTypes.cc delete mode 100644 src/ast/types/PrimitiveTypes.h delete mode 100644 src/ast/types/ReferenceType.cc delete mode 100644 src/ast/types/ReferenceType.h delete mode 100644 src/ast/types/Type.cc delete mode 100644 src/ast/types/Type.h delete mode 100644 src/ast/types/TypeAlias.cc delete mode 100644 src/ast/types/TypeAlias.h delete mode 100644 src/ast/visitor/ASTContext.h delete mode 100644 src/ast/visitor/Visitor.cc delete mode 100644 src/ast/visitor/Visitor.h delete mode 100644 src/builder/linker/Linker.h delete mode 100644 src/builder/linker/common/ld.cc delete mode 100644 src/builder/linker/linux/ld.cc delete mode 100644 src/builder/linker/macos/ld.cc delete mode 100644 src/builder/llvm/DIHelpers.cc delete mode 100644 src/builder/llvm/LLVMBuilder.cc delete mode 100644 src/builder/llvm/LLVMBuilder.h delete mode 100644 src/builder/llvm/LLVMIRChunk.h delete mode 100644 src/builder/llvm/addGlobalVariable.cc delete mode 100644 src/builder/llvm/allocateObject.cc delete mode 100644 src/builder/llvm/buildArgument.cc delete mode 100644 src/builder/llvm/buildBlock.cc delete mode 100644 src/builder/llvm/buildCall.cc delete mode 100644 src/builder/llvm/buildCast.cc delete mode 100644 src/builder/llvm/buildConditional.cc delete mode 100644 src/builder/llvm/buildConstant.cc delete mode 100644 src/builder/llvm/buildDereferenceTo.cc delete mode 100644 src/builder/llvm/buildEnumInit.cc delete mode 100644 src/builder/llvm/buildFunc.cc delete mode 100644 src/builder/llvm/buildIndexExtract.cc delete mode 100644 src/builder/llvm/buildIntrinsic.cc delete mode 100644 src/builder/llvm/buildLLVMFunction.cc delete mode 100644 src/builder/llvm/buildLoopFlow.cc delete mode 100644 src/builder/llvm/buildOperator.cc delete mode 100644 src/builder/llvm/buildReferenceTo.cc delete mode 100644 src/builder/llvm/buildReturn.cc delete mode 100644 src/builder/llvm/buildSwitch.cc delete mode 100644 src/builder/llvm/buildThrow.cc delete mode 100644 src/builder/llvm/buildTryCatch.cc delete mode 100644 src/builder/llvm/buildValueExtract.cc delete mode 100644 src/builder/llvm/buildVariable.cc delete mode 100644 src/builder/llvm/buildVariableDecl.cc delete mode 100644 src/builder/llvm/buildWhileLoop.cc delete mode 100644 src/builder/llvm/call.cc delete mode 100644 src/builder/llvm/createBenchmark.cc delete mode 100644 src/builder/llvm/createCondBr.cc delete mode 100644 src/builder/llvm/createEnumInit.cc delete mode 100644 src/builder/llvm/createException.cc delete mode 100644 src/builder/llvm/createLLVMFunction.cc delete mode 100644 src/builder/llvm/createTests.cc delete mode 100644 src/builder/llvm/createVirtualTable.cc delete mode 100644 src/builder/llvm/getAllocaFunction.cc delete mode 100644 src/builder/llvm/getGlobalCTOR.cc delete mode 100644 src/builder/llvm/getLambdaContextType.cc delete mode 100644 src/builder/llvm/getPrintfFunction.cc delete mode 100644 src/builder/llvm/getSharedLibraryName.cc delete mode 100644 src/builder/llvm/getThrowFunction.cc delete mode 100644 src/builder/llvm/getTypeInfoType.cc delete mode 100644 src/builder/llvm/getVtableType.cc delete mode 100644 src/builder/llvm/helpers/emitObjectFile.cc delete mode 100644 src/builder/llvm/helpers/optimizeModule.cc delete mode 100644 src/builder/llvm/initializeRuntime.cc delete mode 100644 src/builder/llvm/initializeVariable.cc delete mode 100644 src/builder/llvm/llvmTypes.cc delete mode 100644 src/builder/llvm/setDebugInfoLoc.cc delete mode 100644 src/builder/llvm/setPersonalityFunction.cc delete mode 100644 src/builder/llvm/toBool.cc delete mode 100644 src/builder/llvm/utils/typeIdxLookup.cc delete mode 100644 src/builder/llvm/varFetchImpl.h delete mode 100644 src/builder/sn-ir/SnowballIREmitter.cc delete mode 100644 src/builder/sn-ir/SnowballIREmitter.h delete mode 100644 src/common.h delete mode 100644 src/compiler.cc delete mode 100644 src/compiler.h delete mode 100644 src/constants.h delete mode 100644 src/defs/accepts.def delete mode 100644 src/defs/ct.def delete mode 100644 src/defs/operators.def delete mode 100644 src/defs/visits.def delete mode 100644 src/errors.cc delete mode 100644 src/errors.h delete mode 100644 src/export.hpp delete mode 100644 src/ir/IdMixin.cc delete mode 100644 src/ir/ModuleHolder.h delete mode 100644 src/ir/builder/IRBuilder.cc delete mode 100644 src/ir/builder/IRBuilder.h delete mode 100644 src/ir/id.h delete mode 100644 src/ir/module/MainModule.h delete mode 100644 src/ir/module/Module.h delete mode 100644 src/ir/module/Modules.cc delete mode 100644 src/ir/values/Argument.h delete mode 100644 src/ir/values/Body.h delete mode 100644 src/ir/values/Call.h delete mode 100644 src/ir/values/Cast.h delete mode 100644 src/ir/values/Conditional.h delete mode 100644 src/ir/values/Constants.h delete mode 100644 src/ir/values/Dereference.h delete mode 100644 src/ir/values/EnumInit.h delete mode 100644 src/ir/values/Func.cc delete mode 100644 src/ir/values/Func.h delete mode 100644 src/ir/values/IndexExtract.h delete mode 100644 src/ir/values/LoopFlow.h delete mode 100644 src/ir/values/ReferenceTo.h delete mode 100644 src/ir/values/Return.h delete mode 100644 src/ir/values/Switch.h delete mode 100644 src/ir/values/Throw.h delete mode 100644 src/ir/values/TryCatch.h delete mode 100644 src/ir/values/Value.h delete mode 100644 src/ir/values/ValueExtract.h delete mode 100644 src/ir/values/Variable.h delete mode 100644 src/ir/values/VariableDeclaration.h delete mode 100644 src/ir/values/WhileLoop.h delete mode 100644 src/ir/values/all.h delete mode 100644 src/lexer/lexer.cc delete mode 100644 src/lexer/lexer.h delete mode 100644 src/lexer/tokens/token.h delete mode 100644 src/os/Driver.h delete mode 100644 src/os/Driver/getOutputFilename.cc delete mode 100644 src/os/Driver/run.cc delete mode 100644 src/parser/Parser.cc delete mode 100644 src/parser/Parser.h delete mode 100644 src/parser/buildOperatorTree.cc delete mode 100644 src/parser/parseAttributes.cc delete mode 100644 src/parser/parseBlock.cc delete mode 100644 src/parser/parseBlockOrStmt.cc delete mode 100644 src/parser/parseClass.cc delete mode 100644 src/parser/parseComment.cc delete mode 100644 src/parser/parseConditional.cc delete mode 100644 src/parser/parseConstant.cc delete mode 100644 src/parser/parseEnum.cc delete mode 100644 src/parser/parseExpr.cc delete mode 100644 src/parser/parseForLoop.cc delete mode 100644 src/parser/parseFunction.cc delete mode 100644 src/parser/parseFunctionCall.cc delete mode 100644 src/parser/parseGenericExpr.cc delete mode 100644 src/parser/parseGenericParams.cc delete mode 100644 src/parser/parseGlobal.cc delete mode 100644 src/parser/parseIdentifier.cc delete mode 100644 src/parser/parseImportStatement.cc delete mode 100644 src/parser/parseLoopControl.cc delete mode 100644 src/parser/parseMacro.cc delete mode 100644 src/parser/parseNamespace.cc delete mode 100644 src/parser/parseReturn.cc delete mode 100644 src/parser/parseStatement.cc delete mode 100644 src/parser/parseStructure.cc delete mode 100644 src/parser/parseSwitch.cc delete mode 100644 src/parser/parseThrow.cc delete mode 100644 src/parser/parseTryCatch.cc delete mode 100644 src/parser/parseType.cc delete mode 100644 src/parser/parseTypeAlias.cc delete mode 100644 src/parser/parseVariable.cc delete mode 100644 src/parser/parseWhereClause.cc delete mode 100644 src/parser/parseWhile.cc delete mode 100644 src/pm/Manager.cc delete mode 100644 src/pm/Manager.h delete mode 100644 src/services/ImportCache.cc delete mode 100644 src/services/ImportCache.h delete mode 100644 src/services/ImportService.cc delete mode 100644 src/services/ImportService.h delete mode 100644 src/services/OperatorService.cc delete mode 100644 src/services/OperatorService.h delete mode 100644 src/sourceInfo/DBGSourceInfo.cc delete mode 100644 src/sourceInfo/DBGSourceInfo.h delete mode 100644 src/sourceInfo/SourcedObject.h delete mode 100644 src/utils/colors.cc delete mode 100644 src/utils/colors.h delete mode 100644 src/utils/logger.cc delete mode 100644 src/utils/logger.h delete mode 100644 src/utils/utils.cc delete mode 100644 src/utils/utils.h delete mode 100644 src/vendor/pretty_print.hpp delete mode 100644 src/vendor/toml.hpp delete mode 100644 src/visitors/Analyzer.h delete mode 100644 src/visitors/MacroInstance.h delete mode 100644 src/visitors/TransformContext.cc delete mode 100644 src/visitors/TransformContext.h delete mode 100644 src/visitors/TransformItem.h delete mode 100644 src/visitors/TransformState.h delete mode 100644 src/visitors/Transformer.cc delete mode 100644 src/visitors/Transformer.h delete mode 100644 src/visitors/TypeChecker.cc delete mode 100644 src/visitors/TypeChecker.h delete mode 100644 src/visitors/analyzers/DAV/Block.cc delete mode 100644 src/visitors/analyzers/DAV/Expression/BinaryOperator.cc delete mode 100644 src/visitors/analyzers/DAV/Expression/Identifier.cc delete mode 100644 src/visitors/analyzers/DAV/Expression/Index.cc delete mode 100644 src/visitors/analyzers/DAV/Expression/LambdaFunction.cc delete mode 100644 src/visitors/analyzers/DAV/Macro.cc delete mode 100644 src/visitors/analyzers/DAV/MiddlePlace.cc delete mode 100644 src/visitors/analyzers/DAV/Statements/Conditional.cc delete mode 100644 src/visitors/analyzers/DAV/Statements/ForLoop.cc delete mode 100644 src/visitors/analyzers/DAV/Statements/FunctionDef.cc delete mode 100644 src/visitors/analyzers/DAV/Statements/Switch.cc delete mode 100644 src/visitors/analyzers/DAV/Statements/TryCatch.cc delete mode 100644 src/visitors/analyzers/DAV/Statements/VariableDecl.cc delete mode 100644 src/visitors/analyzers/DAV/Statements/WhileLoop.cc delete mode 100644 src/visitors/analyzers/DAV/Statements/visitConstructor.cc delete mode 100644 src/visitors/analyzers/DAV/defaults.cc delete mode 100644 src/visitors/analyzers/DAVUtils.cc delete mode 100644 src/visitors/analyzers/DefinitveAssigment.h delete mode 100644 src/visitors/documentation/DocGen.cc delete mode 100644 src/visitors/documentation/DocGen.h delete mode 100644 src/visitors/documentation/DocTemplates.cc delete mode 100644 src/visitors/documentation/DocTemplates.h delete mode 100644 src/visitors/transform/utils/assertSizedType.cc delete mode 100644 src/visitors/transform/utils/bodyReturns.cc delete mode 100644 src/visitors/transform/utils/canCast.cc delete mode 100644 src/visitors/transform/utils/createIdentifierName.cc delete mode 100644 src/visitors/transform/utils/createModuleAliases.cc delete mode 100644 src/visitors/transform/utils/createObjectConstructor.cc delete mode 100644 src/visitors/transform/utils/deduceFunction.cc delete mode 100644 src/visitors/transform/utils/executeGenericTests.cc delete mode 100644 src/visitors/transform/utils/generate_equilizers.h delete mode 100644 src/visitors/transform/utils/getActualFunction.cc delete mode 100644 src/visitors/transform/utils/getBestFittingFunction.cc delete mode 100644 src/visitors/transform/utils/getBooleanValue.cc delete mode 100644 src/visitors/transform/utils/getBuiltinTypeUUID.cc delete mode 100644 src/visitors/transform/utils/getExpansionData.cc delete mode 100644 src/visitors/transform/utils/getFromIndex.cc delete mode 100644 src/visitors/transform/utils/getFunction.cc delete mode 100644 src/visitors/transform/utils/getFunctionType.cc delete mode 100644 src/visitors/transform/utils/getLLVMBody.cc delete mode 100644 src/visitors/transform/utils/getMemberList.cc delete mode 100644 src/visitors/transform/utils/getNiceBaseName.cc delete mode 100644 src/visitors/transform/utils/getNiceName.cc delete mode 100644 src/visitors/transform/utils/implementTypes.cc delete mode 100644 src/visitors/transform/utils/initializeCoreRuntime.cc delete mode 100644 src/visitors/transform/utils/initializePerModuleMacros.cc delete mode 100644 src/visitors/transform/utils/isInClassContext.cc delete mode 100644 src/visitors/transform/utils/isInModuleContext.cc delete mode 100644 src/visitors/transform/utils/shouldReturnOverload.cc delete mode 100644 src/visitors/transform/utils/transformClass.cc delete mode 100644 src/visitors/transform/utils/transformConstructor.cc delete mode 100644 src/visitors/transform/utils/transformEnum.cc delete mode 100644 src/visitors/transform/utils/transformFunction.cc delete mode 100644 src/visitors/transform/utils/transformIdentifier.cc delete mode 100644 src/visitors/transform/utils/transformMacro.cc delete mode 100644 src/visitors/transform/utils/transformMainFunction.cc delete mode 100644 src/visitors/transform/utils/transformSpecialType.cc delete mode 100644 src/visitors/transform/utils/transformType.cc delete mode 100644 src/visitors/transform/utils/transformTypeAlias.cc delete mode 100644 src/visitors/transform/utils/transformTypeExtension.cc delete mode 100644 src/visitors/transform/utils/transformTypeFromBase.cc delete mode 100644 src/visitors/transform/utils/tryCast.cc delete mode 100644 src/visitors/transform/utils/typeGenericMatch.cc delete mode 100644 src/visitors/transform/visits/Block.cc delete mode 100644 src/visitors/transform/visits/Expression/BinaryOp.cc delete mode 100644 src/visitors/transform/visits/Expression/Cast.cc delete mode 100644 src/visitors/transform/visits/Expression/ConstantValue.cc delete mode 100644 src/visitors/transform/visits/Expression/FunctionCall.cc delete mode 100644 src/visitors/transform/visits/Expression/GenericIdentifier.cc delete mode 100644 src/visitors/transform/visits/Expression/Identifier.cc delete mode 100644 src/visitors/transform/visits/Expression/Index.cc delete mode 100644 src/visitors/transform/visits/Expression/LambdaFunction.cc delete mode 100644 src/visitors/transform/visits/Expression/NewInstance.cc delete mode 100644 src/visitors/transform/visits/Expression/PseudoVariable.cc delete mode 100644 src/visitors/transform/visits/Macro.cc delete mode 100644 src/visitors/transform/visits/Statement/Conditional.cc delete mode 100644 src/visitors/transform/visits/Statement/DefinedType.cc delete mode 100644 src/visitors/transform/visits/Statement/Enum.cc delete mode 100644 src/visitors/transform/visits/Statement/ForLoop.cc delete mode 100644 src/visitors/transform/visits/Statement/FunctionDef.cc delete mode 100644 src/visitors/transform/visits/Statement/ImportStmt.cc delete mode 100644 src/visitors/transform/visits/Statement/LoopFlow.cc delete mode 100644 src/visitors/transform/visits/Statement/Namespace.cc delete mode 100644 src/visitors/transform/visits/Statement/Return.cc delete mode 100644 src/visitors/transform/visits/Statement/Switch.cc delete mode 100644 src/visitors/transform/visits/Statement/Throw.cc delete mode 100644 src/visitors/transform/visits/Statement/TryCatch.cc delete mode 100644 src/visitors/transform/visits/Statement/TypeAlias.cc delete mode 100644 src/visitors/transform/visits/Statement/VariableDecl.cc delete mode 100644 src/visitors/transform/visits/Statement/WhileLoop.cc diff --git a/app/cli.cc b/app/cli.cc deleted file mode 100644 index 1b6debdc..00000000 --- a/app/cli.cc +++ /dev/null @@ -1,276 +0,0 @@ - -#include "cli.h" - -#include "errors.h" -#include "utils/logger.h" - -#include -#include -#include - -namespace snowball { -namespace app { - -using namespace llvm; - -CLI::CLI(int argc, char** argv) : argc(argc), argv(argv) {} - -namespace cli { -namespace modes { - -using EmitType = Options::EmitType; -using Optimization = Options::Optimization; - -void parse_args(argsVector& args) { - cl::ParseCommandLineOptions(args.size(), args.data(), "Snowball Compiler", nullptr, nullptr, true); -} - -void hide_args() { - auto args = cl::getRegisteredOptions(); - for (auto& arg : args) { - arg.getValue()->setHiddenFlag(cl::ReallyHidden); - } -} - -void register_build_opts(Options::BuildOptions& options, std::string mode, argsVector& args) { - cl::OptionCategory buildCategory(mode == "build" ? "Build Options" : "Run Options"); - cl::opt opt( - cl::desc("optimization mode"), - cl::values( - clEnumValN(Optimization::OPTIMIZE_O0, "O0", "No optimization"), - clEnumValN(Optimization::OPTIMIZE_O1, "O1", "Optimization level 1"), - clEnumValN(Optimization::OPTIMIZE_O2, "O2", "Optimization level 2"), - clEnumValN(Optimization::OPTIMIZE_O3, "O3", "Optimization level 3"), - clEnumValN(Optimization::OPTIMIZE_Os, "Os", "Optimization for size"), - clEnumValN(Optimization::OPTIMIZE_Oz, "Oz", "Optimization for size (aggressive)")), - cl::init(Optimization::OPTIMIZE_O1), - cl::cat(buildCategory), - cl::AlwaysPrefix); - cl::opt silent("silent", cl::desc("Silent mode"), cl::cat(buildCategory)); - cl::opt file("file", cl::desc("File to compile"), cl::cat(buildCategory)); - cl::opt no_progress("no-progress", cl::desc("Disable progress bar"), cl::cat(buildCategory)); - cl::alias _silent("s", cl::aliasopt(silent), cl::desc("Alias for -silent"), cl::cat(buildCategory)); - cl::alias _no_progress("np", cl::aliasopt(no_progress), cl::desc("Alias for -no-progress"), cl::cat(buildCategory)); - cl::alias _file("f", cl::aliasopt(file), cl::desc("Alias for -file"), cl::cat(buildCategory)); - if (mode == "build") { - auto test = cl::opt("test", cl::desc("Builds the project for testing"), cl::cat(buildCategory)); - auto bench = cl::opt("bench", cl::desc("Builds the project for benchmarking"), cl::cat(buildCategory)); - auto output = cl::opt("output", cl::desc("Output file"), cl::cat(buildCategory)); - auto emit = cl::opt("emit", - cl::desc("Output type"), - cl::values( - clEnumValN(EmitType::EXECUTABLE, "exe", "Executable"), - clEnumValN(EmitType::OBJECT, "obj", "Object file"), - clEnumValN(EmitType::LLVM_IR, "llvm-ir", "LLVM IR"), - clEnumValN(EmitType::ASSEMBLY, "asm", "Assembly"), - clEnumValN(EmitType::SNOWBALL_IR, "snowball-ir", "Snowball IR")), - cl::init(EmitType::EXECUTABLE), cl::cat(buildCategory)); - cl::alias _test("t", cl::aliasopt(test), cl::desc("Alias for -test"), cl::cat(buildCategory)); - cl::alias _bench("b", cl::aliasopt(bench), cl::desc("Alias for -bench"), cl::cat(buildCategory)); - cl::alias _output("o", cl::aliasopt(output), cl::desc("Alias for -output"), cl::cat(buildCategory)); - cl::alias _emit("e", cl::aliasopt(emit), cl::desc("Alias for -emit"), cl::cat(buildCategory)); - parse_args(args); - options.opt = opt; - options.silent = silent; - options.file = file; - options.no_progress = no_progress; - options.is_test = test; - options.is_bench = bench; - options.output = output; - options.emit_type = emit; - return; - } - parse_args(args); - options.opt = opt; - options.silent = silent; - options.file = file; - options.no_progress = no_progress; -} - -void run(Options& opts, argsVector& args) { - auto& runOpts = opts.run_opts; - cl::OptionCategory runCategory("Extra run Options"); - cl::opt jit("jit", cl::desc("Run the program in JIT mode"), cl::cat(runCategory)); - std::vector progArgs; - bool addToArgs = false; - size_t argIndex = 0; - argsVector usedArgs; - for (auto& arg : args) { - if (addToArgs) { - progArgs.push_back(arg); - } else { - usedArgs.push_back(arg); - } - if (addToArgs || (std::string)arg == "--") { - addToArgs = true; - } - argIndex++; - } - register_build_opts(runOpts, "run", usedArgs); - runOpts.jit = jit; - runOpts.progArgs = progArgs; -} - -void build(Options& opts, argsVector& args) { - auto& buildOpts = opts.build_opts; - register_build_opts(buildOpts, "build", args); -} - -void test(Options& opts, argsVector& args) { - cl::OptionCategory buildCategory("Test Options"); - cl::opt opt( - cl::desc("optimization mode"), - cl::values( - clEnumValN(Optimization::OPTIMIZE_O0, "O0", "No optimization"), - clEnumValN(Optimization::OPTIMIZE_O1, "O1", "Optimization level 1"), - clEnumValN(Optimization::OPTIMIZE_O2, "O2", "Optimization level 2"), - clEnumValN(Optimization::OPTIMIZE_O3, "O3", "Optimization level 3"), - clEnumValN(Optimization::OPTIMIZE_Os, "Os", "Optimization for size"), - clEnumValN(Optimization::OPTIMIZE_Oz, "Oz", "Optimization for size (aggressive)"), - clEnumValN(Optimization::OPTIMIZE_O0, "Debug", "Debug mode (no optimization)"), - clEnumValN(Optimization::OPTIMIZE_O3, "Release", "Release mode (optimization level 3)") - ), - cl::init(Optimization::OPTIMIZE_O3), - cl::cat(buildCategory), cl::AlwaysPrefix); - cl::opt silent("silent", cl::desc("Silent mode"), cl::cat(buildCategory)); - cl::opt no_progress("no-progress", cl::desc("Disable progress bar"), cl::cat(buildCategory)); - cl::alias _silent("s", cl::aliasopt(silent), cl::desc("Alias for -silent"), cl::cat(buildCategory)); - cl::alias _no_progress("np", cl::aliasopt(no_progress), cl::desc("Alias for -no-progress"), cl::cat(buildCategory)); - parse_args(args); - opts.test_opts.opt = opt; - opts.test_opts.silent = silent; - opts.test_opts.no_progress = no_progress; -} - -void init(Options& opts, argsVector& args) { - hide_args(); - cl::OptionCategory initCategory("Init Options"); - cl::opt cfg("cfg", cl::desc("Create a snowball configuration file"), cl::cat(initCategory)); - cl::opt lib("lib", cl::desc("Create a snowball library"), cl::cat(initCategory)); - cl::opt yes("yes", cl::desc("Skip confirmation"), cl::cat(initCategory)); - cl::opt skip_cfg("skip-cfg", cl::desc("Skip configuration"), cl::cat(initCategory)); - cl::opt name("name", cl::desc("Project name"), cl::cat(initCategory), cl::Required); - cl::alias _yes("y", cl::aliasopt(yes), cl::desc("Alias for -yes"), cl::cat(initCategory)); - parse_args(args); - opts.init_opts.cfg = cfg; - opts.init_opts.lib = lib; - opts.init_opts.yes = yes; - opts.init_opts.skip_cfg = skip_cfg; - opts.init_opts.name = name; -} - -void docs(Options& opts, argsVector& args) { - hide_args(); - cl::OptionCategory docsCategory("Docs Options"); - cl::opt silent("silent", cl::desc("Silent mode"), cl::cat(docsCategory)); - cl::opt no_progress("no-progress", cl::desc("Disable progress bar"), cl::cat(docsCategory)); - cl::opt base("base", cl::desc("Base URL"), cl::cat(docsCategory)); - cl::alias _silent("s", cl::aliasopt(silent), cl::desc("Alias for -silent"), cl::cat(docsCategory)); - cl::alias _no_progress("np", cl::aliasopt(no_progress), cl::desc("Alias for -no-progress"), cl::cat(docsCategory)); - cl::alias _base("b", cl::aliasopt(base), cl::desc("Alias for -base"), cl::cat(docsCategory)); - parse_args(args); - opts.docs_opts.silent = silent; - opts.docs_opts.no_progress = no_progress; - opts.docs_opts.base = base; -} - -void bench(Options& opts, argsVector& args) { - cl::OptionCategory benchCategory("Benchmark Options"); - cl::opt opt( - cl::desc("optimization mode"), - cl::values( - clEnumValN(Optimization::OPTIMIZE_O0, "O0", "No optimization"), - clEnumValN(Optimization::OPTIMIZE_O1, "O1", "Optimization level 1"), - clEnumValN(Optimization::OPTIMIZE_O2, "O2", "Optimization level 2"), - clEnumValN(Optimization::OPTIMIZE_O3, "O3", "Optimization level 3"), - clEnumValN(Optimization::OPTIMIZE_Os, "Os", "Optimization for size"), - clEnumValN(Optimization::OPTIMIZE_Oz, "Oz", "Optimization for size (aggressive)"), - clEnumValN(Optimization::OPTIMIZE_O0, "Debug", "Debug mode (no optimization)"), - clEnumValN(Optimization::OPTIMIZE_O3, "Release", "Release mode (optimization level 3)") - ), - cl::init(Optimization::OPTIMIZE_O3), - cl::cat(benchCategory), cl::AlwaysPrefix); - cl::opt silent("silent", cl::desc("Silent mode"), cl::cat(benchCategory)); - cl::opt no_progress("no-progress", cl::desc("Disable progress bar"), cl::cat(benchCategory)); - cl::alias _silent("s", cl::aliasopt(silent), cl::desc("Alias for -silent"), cl::cat(benchCategory)); - cl::alias _no_progress("np", cl::aliasopt(no_progress), cl::desc("Alias for -no-progress"), cl::cat(benchCategory)); - parse_args(args); - opts.bench_opts.opt = opt; - opts.bench_opts.silent = silent; - opts.bench_opts.no_progress = no_progress; -} - -void clean(Options& opts, argsVector& args) { - hide_args(); - cl::OptionCategory cleanCategory("Clean Options"); - parse_args(args); -} - -} // namespace modes -} // namespace cli - -#define SNOWBALL_PRINT_MESSAGE << "Snowball Compiler " << _SNOWBALL_VERSION << " (" << _SNOWBALL_BUILD_TYPE << " build)" << "\n"; - -Options CLI::parse() { - Options opts; - cl::SetVersionPrinter([](raw_ostream & OS) { - OS SNOWBALL_PRINT_MESSAGE; - }); - std::vector args{argv[0]}; - std::string mode; - if (argc < 2) { - args.push_back("--help"); - mode = "--help"; - } else { - for (int i = 2; i < argc; i++) - args.push_back(argv[i]); - mode = argv[1]; - } - std::string argv0 = std::string(args[0]) + " " + mode; - args[0] = argv0.data(); - static std::unordered_map>> modes - = { - {"run", {Options::RUN, cli::modes::run}}, - {"build", {Options::BUILD, cli::modes::build}}, - {"test", {Options::TEST, cli::modes::test}}, - {"init", {Options::INIT, cli::modes::init}}, - {"new", {Options::INIT, cli::modes::init}}, - {"docs", {Options::DOCS, cli::modes::docs}}, - {"bench", {Options::BENCH, cli::modes::bench}}, - {"clean", {Options::CLEAN, cli::modes::clean}}, - }; - if (mode == "--version" || mode == "-v") { - std::cout SNOWBALL_PRINT_MESSAGE; - exit(EXIT_SUCCESS); - } else if (mode == "--help" || mode == "-h") { - cli::modes::hide_args(); - cl::OptionCategory helpCategory("Help Options"); - cl::SubCommand run("run", "Run a Snowball program"); - cl::SubCommand build("build", "Build a Snowball program"); - cl::SubCommand test("test", "Test a Snowball program"); - cl::SubCommand init("init", "Initialize a Snowball project"); - cl::SubCommand docs("docs", "Generate documentation for a Snowball project"); - cl::SubCommand bench("bench", "Benchmark a Snowball program"); - cl::SubCommand clean("clean", "Clean a Snowball project"); - cli::modes::parse_args(args); - cl::PrintHelpMessage(); - exit(EXIT_SUCCESS); - } else { - if (modes.find(mode) == modes.end()) { - std::cout << "Unknown command '" << mode << "'\n"; - exit(EXIT_FAILURE); - } - auto& modePair = modes[mode]; - opts.command = modePair.first; - modePair.second(opts, args); - opts.init_opts.create_dir = mode == "new"; - } - return opts; -} -} // namespace app -} // namespace snowball - -#undef IF_ANY_ARG -#undef IF_ARG -#undef CHECK_ARG -#undef NEXT_ARGUMENT \ No newline at end of file diff --git a/app/cli.h b/app/cli.h deleted file mode 100644 index 2ccd803b..00000000 --- a/app/cli.h +++ /dev/null @@ -1,116 +0,0 @@ - -#include "../src/os/Driver.h" - -#include -#include - -#ifndef __SNOWBALL_EXEC_CLI_H_ -#define __SNOWBALL_EXEC_CLI_H_ - -namespace snowball { -namespace app { -struct Options { - enum EmitType { - EXECUTABLE, - OBJECT, - LLVM_IR, - ASSEMBLY, - SNOWBALL_IR, - }; - - enum Optimization { - OPTIMIZE_O0 = 0x00, - OPTIMIZE_O1 = 0x01, - OPTIMIZE_O2 = 0x02, - OPTIMIZE_O3 = 0x03, - OPTIMIZE_Os = 0x04, - OPTIMIZE_Oz = 0x05 - }; - - struct BuildOptions { - bool is_test = false; - bool is_bench = false; - Optimization opt = OPTIMIZE_O1; - EmitType emit_type = EXECUTABLE; - - bool silent = false; - std::string file = ""; - std::string output = ""; - bool no_progress = false; - } build_opts; - - struct RunOptions : BuildOptions { - bool jit = false; - std::vector progArgs; - } run_opts; - - struct TestOptions { - bool silent = false; - bool no_progress = false; - Optimization opt = OPTIMIZE_O1; - } test_opts; - - struct BenchmarkOptions { - bool silent = false; - bool no_progress = false; - Optimization opt = OPTIMIZE_O1; - } bench_opts; - - struct InitOptions { - bool cfg = false; - bool lib = false; - bool yes = false; - bool skip_cfg = false; - - std::string name = ""; - bool create_dir = false; - } init_opts; - - struct DocsOptions { - bool silent = false; - bool no_progress = false; - - std::string base = ""; - } docs_opts; - - enum Command { - UNKNOWN = -1, - - BUILD, - RUN, - TEST, - INIT, - DOCS, - BENCH, - CLEAN, - } command = UNKNOWN; -}; - -using argsVector = std::vector; - -namespace cli { -namespace modes { - -void run(Options& opts, argsVector& args); -void build(Options& opts, argsVector& args); -void test(Options& opts, argsVector& args); -void init(Options& opts, argsVector& args); -void docs(Options& opts, argsVector& args); -void bench(Options& opts, argsVector& args); - -} // namespace modes -} // namespace cli - -class CLI { - public: - CLI(int argc, char** argv); - Options parse(); - - private: - int argc; - char** argv; -}; -} // namespace app -} // namespace snowball - -#endif // __SNOWBALL_EXEC_CLI_H_ \ No newline at end of file diff --git a/app/commands/bench.h b/app/commands/bench.h deleted file mode 100644 index 568bfea8..00000000 --- a/app/commands/bench.h +++ /dev/null @@ -1,85 +0,0 @@ - -#include "cli.h" -#include "compiler.h" -#include "constants.h" -#include "errors.h" -#include "utils/logger.h" -#include "utils/utils.h" -#include "vendor/toml.hpp" - -#include -#include - -using namespace std::chrono; - -#ifndef __SNOWBALL_EXEC_BENCH_CMD_H_ -#define __SNOWBALL_EXEC_BENCH_CMD_H_ - -namespace snowball { -namespace app { -namespace commands { -int bench(app::Options::BenchmarkOptions p_opts) { - toml::parse_result parsed_config = Compiler::getConfiguration(); - std::string filename = - (std::string)(parsed_config["benchmark"]["entry"].value_or(fs::current_path() / "bench" / "main.sn")); - std::ifstream ifs(filename); - if (ifs.fail()) { - SNError(Error::IO_ERROR, - FMT("Package main file not found in snowball " - "project! \n\t(searching for: '%s')", - filename.c_str())) - .print_error(); - return EXIT_FAILURE; - } - std::string content((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); - // TODO: check for output - std::string output = _SNOWBALL_OUT_DEFAULT("snowball-bench", Options::EmitType::EXECUTABLE, false); - std::string build_type = ""; - filename = parsed_config["package"]["main"].value_or((fs::current_path() / "src" / "main.sn")); - std::string package_name = (std::string)(parsed_config["package"]["name"].value_or("")); - std::string package_version = parsed_config["package"]["version"].value_or(""); - if (p_opts.opt == Options::Optimization::OPTIMIZE_O0) { - build_type += "debug"; - } else { - build_type += "optimized"; - } - if (!p_opts.silent) - Logger::message( - "Project", - FMT("%s v%s [%s%s%s]", package_name.c_str(), package_version.c_str(), BOLD, build_type.c_str(), RESET) - ); - Compiler* compiler = new Compiler(content, filename); - compiler->initialize(); - compiler->enable_benchmark(); - compiler->setOptimization(p_opts.opt); - auto start = high_resolution_clock::now(); - // TODO: false if --no-output is passed - compiler->enamblePackageManager(true); - compiler->compile(p_opts.no_progress || p_opts.silent); - auto stop = high_resolution_clock::now(); - auto date = std::chrono::system_clock::now(); - compiler->emitBinary(output, false); - compiler->cleanup(); - // Get duration. Substart timepoints to - // get duration. To cast it to proper unit - // use duration cast method - auto duration = duration_cast(stop - start).count(); - if (!p_opts.silent) { - auto time = std::chrono::system_clock::to_time_t(date); - char buffer[12]; // __DATE__ format requires 12 characters (including null terminator) - std::strftime(buffer, sizeof(buffer), "%b %d %Y", std::localtime(&time)); - Logger::message("Finished", FMT("benchmark target(s) in %s%i%sms", BOLD, duration, RESET)); - Logger::compiling(FMT("version: %s%s%s\n", BOLD, _SNOWBALL_VERSION, RESET), "Snowball"); - Logger::compiling(FMT("Build date: %s%s%s\n", BOLD, buffer, RESET), "Date"); - Logger::message("Running", FMT("benchmarks (%s)", filename.c_str())); - } - char* args[] = {strdup(output.c_str()), NULL}; - int result = execvp(args[0], args); - // This shoudnt be executed - return result; -} -} // namespace commands -} // namespace app -} // namespace snowball - -#endif // __SNOWBALL_EXEC_BENCH_CMD_H_ diff --git a/app/commands/build.h b/app/commands/build.h deleted file mode 100644 index 32473be1..00000000 --- a/app/commands/build.h +++ /dev/null @@ -1,107 +0,0 @@ - -#include "cli.h" -#include "compiler.h" -#include "constants.h" -#include "errors.h" -#include "utils/utils.h" -#include "vendor/toml.hpp" - -#include -#include -#include - -using namespace std::chrono; -namespace fs = std::filesystem; - -#ifndef __SNOWBALL_EXEC_BUILD_CMD_H_ -#define __SNOWBALL_EXEC_BUILD_CMD_H_ - -namespace snowball { -namespace app { -namespace commands { -int build(app::Options::BuildOptions p_opts) { - std::string filename = p_opts.file; - std::string package_name = "file"; - std::string package_version = ""; - //bool isStaticLib = false; // TODO: implement static library support - if (p_opts.file.empty()) { - toml::parse_result parsed_config = Compiler::getConfiguration(); - filename = parsed_config["package"]["main"].value_or((fs::current_path() / "src" / "main.sn")); - package_name = (std::string)(parsed_config["package"]["name"].value_or("")); - package_version = parsed_config["package"]["version"].value_or(""); - } - std::ifstream ifs(filename); - if (ifs.fail()) { - SNError(Error::IO_ERROR, - FMT("Package main file not found in snowball " - "project! \n\t(searching for: '%s')", - filename.c_str())) - .print_error(); - return EXIT_FAILURE; - } - std::string build_type; - if (p_opts.is_test) { build_type = "test + "; } - if (p_opts.emit_type == Options::EmitType::EXECUTABLE) { - build_type += "executable"; - } else if (p_opts.emit_type == Options::EmitType::SNOWBALL_IR) { - build_type += "snowball-ir"; - } else if (p_opts.emit_type == Options::EmitType::LLVM_IR) { - build_type += "llvm-ir"; - } else if (p_opts.emit_type == Options::EmitType::OBJECT) { - build_type += "library"; - } else if (p_opts.emit_type == Options::EmitType::ASSEMBLY) { - build_type += "assembly"; - } else { - throw SNError(BUG, FMT("Unhandled emit type for build process ('%i')", p_opts.emit_type)); - } - if (p_opts.opt == Options::Optimization::OPTIMIZE_O0) { - build_type += " + debug"; - } else { - build_type += " + optimized"; - } - if (!p_opts.silent) - Logger::message( - "Project", - FMT("%s v%s [%s%s%s]", package_name.c_str(), package_version.c_str(), BOLD, build_type.c_str(), RESET) - ); - std::string content((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); - // TODO: check for output - Compiler* compiler = new Compiler(content, filename); - compiler->initialize(); - std::string output = _SNOWBALL_OUT_DEFAULT(package_name, p_opts.emit_type, !compiler->getGlobalContext().isDynamic); - if (!p_opts.output.empty()) { output = p_opts.output; } - compiler->setOptimization(p_opts.opt); - if (p_opts.is_test) { compiler->enable_tests(); } - auto start = high_resolution_clock::now(); - compiler->enamblePackageManager(p_opts.file.empty()); - compiler->compile(p_opts.no_progress || p_opts.silent); - auto stop = high_resolution_clock::now(); - // Get duration. Substart timepoints to - // get duration. To cast it to proper unit - // use duration cast method - auto duration = duration_cast(stop - start).count(); - if (!p_opts.silent) { - Logger::message("Finished", FMT("build target(s) in %s%ims%s", BOLD, duration, RESET)); - Logger::message("Generating", FMT("Generating output at `%s%s%s`", BOLD, output.c_str(), RESET)); - Logger::log(""); - } - int status; - if (p_opts.emit_type == app::Options::EmitType::OBJECT) { - status = compiler->emitObject(output, !p_opts.silent); - } else if (p_opts.emit_type == app::Options::EmitType::SNOWBALL_IR) { - status = compiler->emitSnowballIr(output, !p_opts.silent); - } else if (p_opts.emit_type == app::Options::EmitType::LLVM_IR) { - status = compiler->emitLLVMIr(output, !p_opts.silent); - } else if (p_opts.emit_type == app::Options::EmitType::ASSEMBLY) { - status = compiler->emitASM(output, !p_opts.silent); - } else { - status = compiler->emitBinary(output, !p_opts.silent); - } - compiler->cleanup(); - return status; -} -} // namespace commands -} // namespace app -} // namespace snowball - -#endif // __SNOWBALL_EXEC_BUILD_CMD_H_ diff --git a/app/commands/docgen.h b/app/commands/docgen.h deleted file mode 100644 index 678b4ac7..00000000 --- a/app/commands/docgen.h +++ /dev/null @@ -1,60 +0,0 @@ - -#include "cli.h" -#include "compiler.h" -#include "constants.h" -#include "ast/errors/error.h" -#include "utils/utils.h" -#include "vendor/toml.hpp" - -#include -#include -#include - -using namespace std::chrono; -namespace fs = std::filesystem; - -#ifndef __SNOWBALL_DOC_BUILD_CMD_H_ -#define __SNOWBALL_DOC_BUILD_CMD_H_ - -namespace snowball { -namespace app { -namespace commands { -int docgen(app::Options::DocsOptions p_opts) { - std::string package_name = "file"; - std::string package_version = ""; - toml::parse_result parsed_config = Compiler::getConfiguration(); - package_name = (std::string)(parsed_config["package"]["name"].value_or("")); - package_version = parsed_config["package"]["version"].value_or(""); - auto folder = parsed_config["documentation"]["entry"].value_or("./src"); - auto baseURL = p_opts.base; - if (baseURL.empty()) baseURL = parsed_config["documentation"]["base"].value_or("/"); - if (package_name == "") { - Syntax::E("No package name found in configuration file!\nPlease add a package name to your configuration file.\nPackage names are required for documentation generation."); - } - if (!p_opts.silent) - Logger::message( - "Project", - FMT("%s v%s [%sdocumentation%s]", package_name.c_str(), package_version.c_str(), BOLD, RESET) - ); - // TODO: check for output - auto compiler = new Compiler("", ""); - compiler->initialize(); - auto start = high_resolution_clock::now(); - int status = compiler->emitDocs(folder, baseURL, {.name = package_name, .version = package_version}, p_opts.silent); - auto stop = high_resolution_clock::now(); - // Get duration. Substart timepoints to - // get duration. To cast it to proper unit - // use duration cast method - auto duration = duration_cast(stop - start).count(); - if (!p_opts.silent) { - Logger::message("Finished", FMT("build documentation page(s) in %s%ims%s", BOLD, duration, RESET)); - Logger::log(""); - } - compiler->cleanup(); - return status; -} -} // namespace commands -} // namespace app -} // namespace snowball - -#endif // __SNOWBALL_DOC_BUILD_CMD_H_ diff --git a/app/commands/files/EXECUTABLE_MAIN b/app/commands/files/EXECUTABLE_MAIN deleted file mode 100644 index db10cd0f..00000000 --- a/app/commands/files/EXECUTABLE_MAIN +++ /dev/null @@ -1,7 +0,0 @@ - -import std::io; - -public func main() i32 { - io::println("Hello, world!"); - return 0; -} diff --git a/app/commands/files/LIBRARY_MAIN b/app/commands/files/LIBRARY_MAIN deleted file mode 100644 index d2b05f0c..00000000 --- a/app/commands/files/LIBRARY_MAIN +++ /dev/null @@ -1,6 +0,0 @@ - -import std::io; - -public func my_export() bool { - return true; -} diff --git a/app/commands/files/LIBRARY_TEST b/app/commands/files/LIBRARY_TEST deleted file mode 100644 index 96fde54a..00000000 --- a/app/commands/files/LIBRARY_TEST +++ /dev/null @@ -1,12 +0,0 @@ - -import pkg::lib; - -@cfg(tests) -namespace tests { - -@test -func should_pass() i32 { - return lib::my_export(); -} - -} diff --git a/app/commands/files/_GITIGNORE b/app/commands/files/_GITIGNORE deleted file mode 100644 index f51966f3..00000000 --- a/app/commands/files/_GITIGNORE +++ /dev/null @@ -1,2 +0,0 @@ - -.sn/ diff --git a/app/commands/files/assets.h b/app/commands/files/assets.h deleted file mode 100644 index 4f570fae..00000000 --- a/app/commands/files/assets.h +++ /dev/null @@ -1,38 +0,0 @@ - -unsigned char EXECUTABLE_MAIN[] = { - 0x0a, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x73, 0x74, 0x64, 0x3a, - 0x3a, 0x69, 0x6f, 0x3b, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, - 0x20, 0x66, 0x75, 0x6e, 0x63, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x29, - 0x20, 0x69, 0x33, 0x32, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, - 0x6f, 0x3a, 0x3a, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x6c, 0x6e, 0x28, 0x22, - 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, - 0x21, 0x22, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x30, 0x3b, 0x0a, 0x7d, 0x0a -}; -unsigned int EXECUTABLE_MAIN_len = 93; -unsigned char LIBRARY_MAIN[] = { - 0x0a, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x73, 0x74, 0x64, 0x3a, - 0x3a, 0x69, 0x6f, 0x3b, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, - 0x20, 0x66, 0x75, 0x6e, 0x63, 0x20, 0x6d, 0x79, 0x5f, 0x65, 0x78, 0x70, - 0x6f, 0x72, 0x74, 0x28, 0x29, 0x20, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x7b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x74, 0x72, 0x75, 0x65, 0x3b, 0x0a, 0x7d, 0x0a -}; -unsigned int LIBRARY_MAIN_len = 68; -unsigned char LIBRARY_TEST[] = { - 0x0a, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x70, 0x6b, 0x67, 0x3a, - 0x3a, 0x6c, 0x69, 0x62, 0x3b, 0x0a, 0x0a, 0x40, 0x63, 0x66, 0x67, 0x28, - 0x74, 0x65, 0x73, 0x74, 0x73, 0x29, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x20, 0x74, 0x65, 0x73, 0x74, 0x73, 0x20, 0x7b, - 0x0a, 0x0a, 0x40, 0x74, 0x65, 0x73, 0x74, 0x0a, 0x66, 0x75, 0x6e, 0x63, - 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x5f, 0x70, 0x61, 0x73, 0x73, - 0x28, 0x29, 0x20, 0x69, 0x33, 0x32, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x69, 0x62, 0x3a, - 0x3a, 0x6d, 0x79, 0x5f, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x28, 0x29, - 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x7d, 0x0a -}; -unsigned int LIBRARY_TEST_len = 115; -unsigned char _GITIGNORE[] = { - 0x0a, 0x2e, 0x73, 0x6e, 0x2f, 0x0a -}; -unsigned int _GITIGNORE_len = 6; diff --git a/app/commands/files/compile_init_files.sh b/app/commands/files/compile_init_files.sh deleted file mode 100644 index 33354a33..00000000 --- a/app/commands/files/compile_init_files.sh +++ /dev/null @@ -1,10 +0,0 @@ -set -ex - -# Clear file -echo "" > assets.h - -# append to header file -xxd -i EXECUTABLE_MAIN >> assets.h -xxd -i LIBRARY_MAIN >> assets.h -xxd -i LIBRARY_TEST >> assets.h -xxd -i _GITIGNORE >> assets.h diff --git a/app/commands/init.h b/app/commands/init.h deleted file mode 100644 index 0fba57e1..00000000 --- a/app/commands/init.h +++ /dev/null @@ -1,122 +0,0 @@ - -#include "cli.h" -#include "utils/logger.h" - -#include -#include -#include -#include - -using namespace std::chrono; - -#ifndef __SNOWBALL_EXEC_INIT_CMD_H_ -#define __SNOWBALL_EXEC_INIT_CMD_H_ - -#define STRINGIFY(...) #__VA_ARGS__ - -#define LIBRARY_ENTRY "src/lib.sn" -#define EXECUTABLE_ENTRY "src/main.sn" - -#define CONFIGURATION_FILE "sn.toml" - -#include "files/assets.h" - -namespace snowball { -namespace app { -namespace commands { - -void init_create_cfg(bool yes, std::string entry, app::Options::InitOptions p_opts) { - std::ofstream outfile(CONFIGURATION_FILE); - std::string version = "0.0.1"; - // TODO: ask questions if p_opts.yes is false - std::string toml_result; - std::stringstream toml(toml_result); - toml << "\n[package]"; - toml << FMT("\nname = \"%s\"", p_opts.name.c_str()); - toml << FMT("\nmain = \"%s\"", entry.c_str()); - toml << FMT("\nversion = \"%s\"", version.c_str()); - outfile << toml.str() << std::endl; - outfile.close(); - Logger::message("Configuration", FMT("Configured project file (%s)", CONFIGURATION_FILE)); -} - -// TODO: Output messages -int init(app::Options::InitOptions p_opts) { - auto start = high_resolution_clock::now(); - if (p_opts.create_dir) { - Logger::message("Creating", FMT("Snowball project at directory %s", p_opts.name.c_str())); - if (!fs::exists(p_opts.name)) fs::create_directory(p_opts.name); - fs::current_path(p_opts.name); - } - // If the folder is not empty, ask the user if he wants to continue - // if the user accepts, delete all files and continue - if (!fs::is_empty(fs::current_path())) { - Logger::rlog(FMT("%s[warning]%s: The current directory is not empty, do you want to continue? [y/N] ", BYEL, RESET)); - std::string answer; - std::getline(std::cin, answer); - if (answer != "y" && answer != "Y") { - Logger::message("Aborted", "Snowball project creation"); - return 0; - } - Logger::message("Deleting", "All files in the current directory"); - for (auto& p : fs::directory_iterator(fs::current_path())) { - fs::remove_all(p); - } - } - if (p_opts.cfg) { - init_create_cfg(p_opts.yes, EXECUTABLE_ENTRY, p_opts); - return 0; - } else if (p_opts.lib) { - Logger::message("Initalizing", FMT("Current project [library]", CONFIGURATION_FILE)); - if (!fs::exists("src")) fs::create_directory("src"); - if (!p_opts.skip_cfg) init_create_cfg(p_opts.yes, LIBRARY_ENTRY, p_opts); - std::ofstream outfile(LIBRARY_ENTRY); - auto libFile = std::string((const char*)LIBRARY_MAIN, LIBRARY_MAIN_len); - outfile << libFile << std::endl; - outfile.close(); - if (!fs::exists("tests")) fs::create_directory("tests"); - if (!fs::exists("tests/main.sn")) { - std::ofstream outfile("tests/main.sn"); - auto testFile = std::string((const char*)LIBRARY_TEST, LIBRARY_TEST_len); - outfile << testFile << std::endl; - outfile.close(); - } - } else { - Logger::message("Initalizing", FMT("Current project [executable]", CONFIGURATION_FILE)); - if (!fs::exists("src")) fs::create_directory("src"); - if (!p_opts.skip_cfg) init_create_cfg(p_opts.yes, EXECUTABLE_ENTRY, p_opts); - std::ofstream outfile(EXECUTABLE_ENTRY); - auto mainFile = std::string((const char*)EXECUTABLE_MAIN, EXECUTABLE_MAIN_len); - outfile << mainFile << std::endl; - outfile.close(); - } - auto gitignore = std::string((const char*)_GITIGNORE, _GITIGNORE_len); - std::ofstream outfile(".gitignore"); - outfile << gitignore << std::endl; - outfile.close(); - auto stop = high_resolution_clock::now(); - // Get duration. Substart timepoints to - // get duration. To cast it to proper unit - // use duration cast method - auto duration = duration_cast(stop - start).count(); - Logger::message("Finished", FMT("snowball project in %ims 🐱", duration)); - Logger::rlog("\n"); - Logger::info("Execute `snowball --help` to get a manual about " - "the project."); - return 0; -} -} // namespace commands -} // namespace app -} // namespace snowball - -#undef LIBRARY_MAIN -#undef LIBRARY_ENTRY - -#undef EXECUTABLE_MAIN -#undef EXECUTABLE_ENTRY - -#undef CONFIGURATION_FILE - -#undef STRINGIFY - -#endif // __SNOWBALL_EXEC_INIT_CMD_H_ diff --git a/app/commands/pm.h b/app/commands/pm.h deleted file mode 100644 index 0a90795d..00000000 --- a/app/commands/pm.h +++ /dev/null @@ -1,29 +0,0 @@ - - -#include "cli.h" -#include "utils/logger.h" - -#include -#include -#include -#include - -#ifndef __SNOWBALL_EXEC_UTILS_CMD_H_ -#define __SNOWBALL_EXEC_UTILS_CMD_H_ - -namespace snowball { -namespace app { -namespace commands { - -int clean() { - Logger::message("Cleaning", "Removing up build files"); - if (fs::exists(".sn")) fs::remove_all(".sn"); - return 0; -} - -} // namespace commands -} // namespace app -} // namespace snowball - -#endif // __SNOWBALL_EXEC_INIT_CMD_H_ - diff --git a/app/commands/run.h b/app/commands/run.h deleted file mode 100644 index cf3bae17..00000000 --- a/app/commands/run.h +++ /dev/null @@ -1,61 +0,0 @@ - -#include "cli.h" -#include "compiler.h" -#include "errors.h" -#include "utils/logger.h" -#include "utils/utils.h" -#include "vendor/toml.hpp" - -#include -#include - -#ifndef __SNOWBALL_EXEC_RUN_CMD_H_ -#define __SNOWBALL_EXEC_RUN_CMD_H_ - -namespace snowball { -namespace app { -namespace commands { -int run(app::Options::RunOptions p_opts) { - std::string filename = p_opts.file; - if (p_opts.file.empty()) { - toml::parse_result parsed_config = Compiler::getConfiguration(); - filename = p_opts.file.empty() ? - (std::string - )(parsed_config["package"]["main"].value_or((fs::current_path() / "src" / "main.sn"))) : - p_opts.file; - } - std::ifstream ifs(filename); - if (ifs.fail()) { - SNError(Error::IO_ERROR, - FMT("Package main file not found in snowball " - "project! \n\t(searching for: '%s')", - filename.c_str())) - .print_error(); - return EXIT_FAILURE; - } - std::string content((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); - // TODO: check for output - std::string output = - fs::current_path() / _SNOWBALL_OUT_DEFAULT("snowball-output", Options::EmitType::EXECUTABLE, false); - auto compiler = new Compiler(content, filename); - compiler->initialize(); - compiler->setOptimization(p_opts.opt); - // TODO: false if --no-output is passed - compiler->enamblePackageManager(p_opts.file.empty()); - compiler->compile(p_opts.no_progress || p_opts.silent); - compiler->emitBinary(output, false); - compiler->cleanup(); - char* args[1024] = {strdup(output.c_str())}; - for (size_t i = 0; i < p_opts.progArgs.size(); i++) { - args[i + 1] = strdup(p_opts.progArgs[i].c_str()); - } - args[p_opts.progArgs.size() + 1] = NULL; - int result = execvp(args[0], args); - // This shoudnt be executed - return result; -} -} // namespace commands -} // namespace app -} // namespace snowball - -#endif // __SNOWBALL_EXEC_RUN_CMD_H_ diff --git a/app/commands/test.h b/app/commands/test.h deleted file mode 100644 index f05a35d9..00000000 --- a/app/commands/test.h +++ /dev/null @@ -1,84 +0,0 @@ - -#include "cli.h" -#include "compiler.h" -#include "constants.h" -#include "errors.h" -#include "utils/logger.h" -#include "utils/utils.h" -#include "vendor/toml.hpp" - -#include - -using namespace std::chrono; - -#ifndef __SNOWBALL_EXEC_TEST_CMD_H_ -#define __SNOWBALL_EXEC_TEST_CMD_H_ - -namespace snowball { -namespace app { -namespace commands { -int test(app::Options::TestOptions p_opts) { - toml::parse_result parsed_config = Compiler::getConfiguration(); - std::string filename = - (std::string)(parsed_config["test"]["entry"].value_or(fs::current_path() / "tests" / "main.sn")); - std::ifstream ifs(filename); - if (ifs.fail()) { - SNError(Error::IO_ERROR, - FMT("Package main file not found in snowball " - "project! \n\t(searching for: '%s')", - filename.c_str())) - .print_error(); - return EXIT_FAILURE; - } - std::string content((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); - // TODO: check for output - std::string output = _SNOWBALL_OUT_DEFAULT("snowball-test-case", Options::EmitType::EXECUTABLE, false); - std::string build_type = ""; - filename = parsed_config["package"]["main"].value_or((fs::current_path() / "src" / "main.sn")); - std::string package_name = (std::string)(parsed_config["package"]["name"].value_or("")); - std::string package_version = parsed_config["package"]["version"].value_or(""); - if (p_opts.opt == Options::Optimization::OPTIMIZE_O0) { - build_type += "debug"; - } else { - build_type += "optimized"; - } - if (!p_opts.silent) - Logger::message( - "Project", - FMT("%s v%s [%stest + %s%s]", package_name.c_str(), package_version.c_str(), BOLD, build_type.c_str(), RESET) - ); - Compiler* compiler = new Compiler(content, filename); - compiler->initialize(); - compiler->enable_tests(); - compiler->setOptimization(p_opts.opt); - auto start = high_resolution_clock::now(); - compiler->enamblePackageManager(true); - compiler->compile(p_opts.no_progress || p_opts.silent); - auto stop = high_resolution_clock::now(); - auto date = std::chrono::system_clock::now(); - compiler->emitBinary(output, false); - compiler->cleanup(); - // Get duration. Substart timepoints to - // get duration. To cast it to proper unit - // use duration cast method - auto duration = duration_cast(stop - start).count(); - if (!p_opts.silent) { - auto time = std::chrono::system_clock::to_time_t(date); - char buffer[12]; // __DATE__ format requires 12 characters (including null terminator) - std::strftime(buffer, sizeof(buffer), "%b %d %Y", std::localtime(&time)); - Logger::message("Finished", FMT("test target(s) in %s%i%sms", BOLD, duration, RESET)); - Logger::compiling(FMT("version: %s%s%s\n", BOLD, _SNOWBALL_VERSION, RESET), "Snowball"); - Logger::compiling(FMT("Build date: %s%s%s\n", BOLD, buffer, RESET), "Date"); - Logger::compiling("Good luck with the tests! 🙏😽\n", "Motivation"); - Logger::message("Running", FMT("unittests (%s)", filename.c_str())); - } - char* args[] = {strdup(output.c_str()), NULL}; - int result = execvp(args[0], args); - // This shoudnt be executed - return result; -} -} // namespace commands -} // namespace app -} // namespace snowball - -#endif // __SNOWBALL_EXEC_TEST_CMD_H_ diff --git a/app/crash_handler.h b/app/crash_handler.h deleted file mode 100644 index 34a8acff..00000000 --- a/app/crash_handler.h +++ /dev/null @@ -1,513 +0,0 @@ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -/*************************************************************************/ -/* This file is part of: */ -/* CARBON LANGUAGE */ -/*https://github.com/ThakeeNathees/carbon/blob/master/src/main/crash_handler.h*/ -/*************************************************************************/ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -// This file is heavily modified version of the Godot's crahs_handler -// It's also heavily modified modified from: -// Usage: -// #define SNOWBALL_INCLUDE_CRASH_HANDLER_MAIN -// #define SNOWBALL_CRASH_HANDLER_IMPLEMENTATION -// #include "crash_handler.h" - -#if defined(_WIN32) - -#include -// #pragma comment(lib, "psapi.lib") -// #pragma comment(lib, "dbghelp.lib") - -// Crash handler exception only enabled with MSVC -#if (defined(_DEBUG) || _SN_DEBUG) && defined(_MSC_VER) -#define CRASH_HANDLER_EXCEPTION 1 -extern DWORD CrashHandlerException(EXCEPTION_POINTERS* ep); -#endif - -#elif defined(linux) - -#ifndef CRASH_HANDLER_X11_H -#define CRASH_HANDLER_X11_H - -// LINK: 'dl' - -class CrashHandler { - bool disabled; - - public: - void initialize(); - - void disable(); - bool is_disabled() const { return disabled; }; - - CrashHandler(); - ~CrashHandler(); -}; - -#endif // CRASH_HANDLER_X11_H - -#endif - -#ifdef SNOWBALL_INCLUDE_CRASH_HANDLER_MAIN - -/***************************************************************************************************************************/ -/* CRASH HANDLER MAIN */ -/***************************************************************************************************************************/ - -int _main(int, char**); - -#if defined(_WIN32) - -int main(int argc, char** argv) { -#ifdef CRASH_HANDLER_EXCEPTION - __try { - return _main(argc, argv); - } __except (CrashHandlerException(GetExceptionInformation())) { return 1; } -#else - return _main(argc, argv); -#endif -} - -#elif defined(linux) - -int main(int argc, char** argv) { - CrashHandler crash_handler; - crash_handler.initialize(); - return _main(argc, argv); -} - -#else -#define _main main - -#endif - -#endif // SNOWBALL_INCLUDE_CRASH_HANDLER_MAIN - -#if defined(SNOWBALL_CRASH_HANDLER_IMPLEMENTATION) || \ - (defined(SNOWBALL_INCLUDE_CRASH_HANDLER_MAIN) && defined(SNOWBALL_IMPLEMENTATION)) -/***************************************************************************************************************************/ -/* CRASH HANDLER WINDOWS */ -/***************************************************************************************************************************/ - -#if defined(_WIN32) - -#ifdef CRASH_HANDLER_EXCEPTION - -#include - -// Backtrace code code based on: -// https://stackoverflow.com/questions/6205981/windows-c-stack-trace-from-a-running-app - -#include - -#include -#include -#include - -// Some versions of imagehlp.dll lack the proper packing directives themselves -// so we need to do it. -#pragma pack(push, before_imagehlp, 8) -#include -#pragma pack(pop, before_imagehlp) - -struct module_data { - std::string image_name; - std::string module_name; - void* base_address; - DWORD load_size; -}; - -class symbol { - typedef IMAGEHLP_SYMBOL64 sym_type; - sym_type* sym; - static const int max_name_len = 1024; - - public: - symbol(HANDLE process, DWORD64 address) : sym((sym_type*) ::operator new (sizeof(*sym) + max_name_len)) { - memset(sym, '\0', sizeof(*sym) + max_name_len); - sym->SizeOfStruct = sizeof(*sym); - sym->MaxNameLength = max_name_len; - DWORD64 displacement; - SymGetSymFromAddr64(process, address, &displacement, sym); - } - - std::string name() { return std::string(sym->Name); } - std::string undecorated_name() { - if (*sym->Name == '\0') return ""; - std::vector und_name(max_name_len); - UnDecorateSymbolName(sym->Name, &und_name[0], max_name_len, UNDNAME_COMPLETE); - return std::string(&und_name[0], strlen(&und_name[0])); - } -}; - -class get_mod_info { - HANDLE process; - - public: - get_mod_info(HANDLE h) : process(h) { } - - module_data operator()(HMODULE module) { - module_data ret; - char temp[4096]; - MODULEINFO mi; - GetModuleInformation(process, module, &mi, sizeof(mi)); - ret.base_address = mi.lpBaseOfDll; - ret.load_size = mi.SizeOfImage; - GetModuleFileNameEx(process, module, temp, sizeof(temp)); - ret.image_name = temp; - GetModuleBaseName(process, module, temp, sizeof(temp)); - ret.module_name = temp; - std::vector img(ret.image_name.begin(), ret.image_name.end()); - std::vector mod(ret.module_name.begin(), ret.module_name.end()); - SymLoadModule64(process, 0, &img[0], &mod[0], (DWORD64) ret.base_address, ret.load_size); - return ret; - } -}; - -DWORD -CrashHandlerException(EXCEPTION_POINTERS* ep) { - HANDLE process = GetCurrentProcess(); - HANDLE hThread = GetCurrentThread(); - DWORD offset_from_symbol = 0; - IMAGEHLP_LINE64 line = {0}; - std::vector modules; - DWORD cbNeeded; - std::vector module_handles(1); - if (IsDebuggerPresent()) { return EXCEPTION_CONTINUE_SEARCH; } - fprintf(stderr, "%s: Program crashed\n", __FUNCTION__); - // Load the symbols: - if (!SymInitialize(process, nullptr, false)) return EXCEPTION_CONTINUE_SEARCH; - SymSetOptions(SymGetOptions() | SYMOPT_LOAD_LINES | SYMOPT_UNDNAME); - EnumProcessModules(process, &module_handles[0], (DWORD) module_handles.size() * sizeof(HMODULE), &cbNeeded); - module_handles.resize(cbNeeded / sizeof(HMODULE)); - EnumProcessModules(process, &module_handles[0], (DWORD) module_handles.size() * sizeof(HMODULE), &cbNeeded); - std::transform(module_handles.begin(), module_handles.end(), std::back_inserter(modules), get_mod_info(process)); - void* base = modules[0].base_address; - // Setup stuff: - CONTEXT* context = ep->ContextRecord; - STACKFRAME64 frame; - bool skip_first = false; - frame.AddrPC.Mode = AddrModeFlat; - frame.AddrStack.Mode = AddrModeFlat; - frame.AddrFrame.Mode = AddrModeFlat; -#ifdef _M_X64 - frame.AddrPC.Offset = context->Rip; - frame.AddrStack.Offset = context->Rsp; - frame.AddrFrame.Offset = context->Rbp; -#else - frame.AddrPC.Offset = context->Eip; - frame.AddrStack.Offset = context->Esp; - frame.AddrFrame.Offset = context->Ebp; - // Skip the first one to avoid a duplicate on 32-bit mode - skip_first = true; -#endif - line.SizeOfStruct = sizeof(line); - IMAGE_NT_HEADERS* h = ImageNtHeader(base); - DWORD image_type = h->FileHeader.Machine; - fprintf(stderr, "Dumping the backtrace.\n"); - int n = 0; - do { - if (skip_first) { - skip_first = false; - } else { - if (frame.AddrPC.Offset != 0) { - std::string fnName = symbol(process, frame.AddrPC.Offset).undecorated_name(); - if (SymGetLineFromAddr64(process, frame.AddrPC.Offset, &offset_from_symbol, &line)) - fprintf(stderr, "[%d] %s (%s:%d)\n", n, fnName.c_str(), line.FileName, line.LineNumber); - else - fprintf(stderr, "[%d] %s\n", n, fnName.c_str()); - } else - fprintf(stderr, "[%d] ???\n", n); - n++; - } - if (!StackWalk64( - image_type, - process, - hThread, - &frame, - context, - nullptr, - SymFunctionTableAccess64, - SymGetModuleBase64, - nullptr - )) - break; - } while (frame.AddrReturn.Offset != 0 && n < 256); - fprintf(stderr, "-- END OF BACKTRACE --\n"); - SymCleanup(process); - // Pass the exception to the OS - return EXCEPTION_CONTINUE_SEARCH; -} -#endif - -/***************************************************************************************************************************/ -/* CRASH HANDLER LINUX */ -/***************************************************************************************************************************/ - -#elif defined(linux) - -#if _SN_DEBUG -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -// TODO: move this to os related place -std::string _get_exec_path() { - int len = 1024; - char pBuf[len]; -#ifdef _WIN32 - int bytes = GetModuleFileName(NULL, pBuf, sizeof pBuf); - // TODO: assert bytes > 0 -#elif __linux__ - char szTmp[32]; - sprintf(szTmp, "/proc/%d/exe", getpid()); - // int bytes = min(readlink(szTmp, pBuf, len), len - 1); - int bytes = readlink(szTmp, pBuf, len); - if (bytes > len - 1) bytes = len - 1; - if (bytes >= 0) pBuf[bytes] = '\0'; -#endif - return pBuf; -} - -int _execute( - const std::string& p_path, - const std::vector& p_arguments, - bool p_blocking, - int* r_child_id, - std::string* r_pipe, - int* r_exitcode, - bool read_stderr = true /*,Mutex *p_pipe_mutex*/ -) { -#ifdef __EMSCRIPTEN__ - // Don't compile this code at all to avoid undefined references. - // Actual virtual call goes to OS_JavaScript. - ERR_FAIL_V(ERR_BUG); -#else - if (p_blocking && r_pipe) { - std::string argss; - argss = "\"" + p_path + "\""; - for (size_t i = 0; i < p_arguments.size(); i++) { argss += std::string(" \"") + p_arguments[i] + "\""; } - if (read_stderr) { - argss += " 2>&1"; // Read stderr too - } else { - argss += " 2>/dev/null"; // silence stderr - } - FILE* f = popen(argss.c_str(), "r"); - if (!f) { - printf("ERR_CANT_OPEN, Cannot pipe stream from process running " - "with following arguments\n\t%s.\n", - argss.c_str()); - return -1; - } - char buf[65535]; - while (fgets(buf, 65535, f)) { (*r_pipe) += std::string(buf); } - int rv = pclose(f); - if (r_exitcode) *r_exitcode = rv; - return 0; - } - pid_t pid = fork(); - if (pid < 0) { - printf("ERR_CANT_FORK\n"); - return -1; - } - if (pid == 0) { - // is child - if (!p_blocking) { - // For non blocking calls, create a new session-ID so parent won't - // wait for it. This ensures the process won't go zombie at end. - setsid(); - } - std::vector cs; - cs.push_back(p_path); - for (size_t i = 0; i < p_arguments.size(); i++) cs.push_back(p_arguments[i]); - std::vector args; - for (size_t i = 0; i < cs.size(); i++) args.push_back((char*) cs[i].c_str()); - args.push_back(0); - execvp(p_path.c_str(), &args[0]); - // still alive? something failed.. - fprintf(stderr, - "**ERROR** OS_Unix::execute - Could not create child process " - "while executing: %s\n", - p_path.c_str()); - abort(); - } - if (p_blocking) { - int status; - waitpid(pid, &status, 0); - if (r_exitcode) *r_exitcode = status; - } else { - if (r_child_id) *r_child_id = pid; - } - return 0; -#endif -} - -// FIXME: chage it to string split -std::string _func_offset(const char* string_symbol) { - // the backtrace_symbol output: - // /home/thakeenathees/dev/SNOWBALL/bin/SNOWBALL.x11.debug.64(+0x2801) - // [0x55c5aa0a2801] from that it'll extract the offset (0x2801) and feed to - // addr2line - size_t i = 0; - bool copy = false; - std::string offset; - while (char c = string_symbol[i++]) { - if (c == ')') break; - if (copy) offset += c; - if (c == '+') copy = true; - } - return offset; -} - -////////////////////////////////////////////////////////////////////////////////////////////////////////// - -static void handle_crash(int sig) { - void* bt_buffer[256]; - size_t size = backtrace(bt_buffer, 256); - std::string _execpath = _get_exec_path(); - // Dump the backtrace to stderr with a message to the user - fprintf(stderr, - "\n\n---------------- [ CRASH REPORT ] ----------------\n\n%s: " - "Snowball " - "crashed!\n", - __FUNCTION__); - fprintf(stderr, - "%s: Oh no! Fluffy got into the code and caused an error! /ᐠ.ᆽ.ᐟ " - "\\∫\n", - __FUNCTION__); - fprintf(stderr, "%s: Program crashed with signal %d\n", __FUNCTION__, sig); - fprintf(stderr, "%s: Dumping the backtrace.\n", __FUNCTION__); - char** strings = backtrace_symbols(bt_buffer, size); - if (strings) { - for (size_t i = 1; i < size; i++) { - /* fname not working like it works in godot!! using backtrace_symbol - string instead to get method char fname[1024]; Dl_info info; - snprintf(fname, 1024, "%s", strings[i]); - // Try to demangle the function name to provide a more - readable one if (dladdr(bt_buffer[i], &info) && info.dli_sname) { - if (info.dli_sname[0] == '_') { - int status; - char *demangled = - abi::__cxa_demangle(info.dli_sname, nullptr, nullptr, &status); - if (status == 0 && demangled) { - snprintf(fname, 1024, "%s", demangled); - } - if (demangled) - free(demangled); - } - } - */ - std::vector args; - // char str[1024]; - // snprintf(str, 1024, "%p", bt_buffer[i]); - // godot using this but It's not working for some reason - // but the offset from the backtrace_symbols working, why? - // using args.push_back(_func_offset(strings[i])); instead - args.push_back(_func_offset(strings[i])); - args.push_back("-e"); - args.push_back(_execpath); - args.push_back("-f"); - args.push_back("--demangle"); - args.push_back("-p"); - std::string output = ""; - // Try to get the file/line number using addr2line - int ret; - int err = _execute("addr2line", args, true, nullptr, &output, &ret); - if (err == 0) { output.erase(output.length() - 1, 1); } - if (output.find(" ??:") != std::string::npos) { // _start at ??:0 no symbol found - fprintf(stderr, - "[%ld] <> at %s\n", - (long int) i, - /*fname,*/ strings[i]); - } else { - fprintf(stderr, - "[%ld] %s\n", - (long int) i, - /*fname,*/ output.c_str()); - } - } - free(strings); - } - fprintf(stderr, "\n-------------- [ END OF BACKTRACE ] ---------------\n\n"); - // Abort to pass the error to the OS - abort(); -} -#endif - -CrashHandler::CrashHandler() { disabled = false; } - -CrashHandler::~CrashHandler() { disable(); } - -void CrashHandler::disable() { - if (disabled) return; -#if _SN_DEBUG - signal(SIGSEGV, nullptr); - signal(SIGFPE, nullptr); - signal(SIGILL, nullptr); -#endif - disabled = true; -} - -void CrashHandler::initialize() { -#if _SN_DEBUG - signal(SIGSEGV, handle_crash); - signal(SIGFPE, handle_crash); - signal(SIGILL, handle_crash); -#endif -} - -#endif -#endif // SNOWBALL_CRASH_HANDLER_IMPLEMENTATION diff --git a/app/main.cc b/app/main.cc deleted file mode 100644 index 77d64f17..00000000 --- a/app/main.cc +++ /dev/null @@ -1,69 +0,0 @@ - -#include "cli.h" -#include "commands/bench.h" -#include "commands/build.h" -#include "commands/init.h" -#include "commands/run.h" -#include "commands/test.h" -#include "commands/pm.h" -#include "commands/docgen.h" -#include "constants.h" -#include "utils/utils.h" -#include "vendor/toml.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define SNOWBALL_INCLUDE_CRASH_HANDLER_MAIN -#define SNOWBALL_CRASH_HANDLER_IMPLEMENTATION -#include "crash_handler.h" - -using namespace snowball; -using namespace std::chrono; -using namespace snowball::utils; - -int _main(int argc, char** argv) { - srand((unsigned) time(NULL) * getpid()); - try { - app::CLI* cli = new app::CLI(argc, argv); - app::Options opts = cli->parse(); - switch (opts.command) { - case app::Options::BUILD: - return app::commands::build(opts.build_opts); - case app::Options::RUN: - return app::commands::run(opts.run_opts); - case app::Options::TEST: - return app::commands::test(opts.test_opts); - case app::Options::INIT: - return app::commands::init(opts.init_opts); - case app::Options::BENCH: - return app::commands::bench(opts.bench_opts); - case app::Options::DOCS: - return app::commands::docgen(opts.docs_opts); - case app::Options::CLEAN: - return app::commands::clean(); - default: - throw SNError(Error::TODO, FMT("Command with type %i not yet supported", opts.command)); - } - } catch (const SNError& error) { - error.print_error(); - return EXIT_FAILURE; - } catch (const std::vector& errors) { - for (auto& error : errors) { - error->print_error(); - } - return EXIT_FAILURE; - } catch (const std::exception& e) { - Logger::error(FMT("\r\nAn unexpected error occurred: %s", e.what())); - return EXIT_FAILURE; - } - return EXIT_SUCCESS; -} diff --git a/build_scripts/build-snowball.sh b/build_scripts/build-snowball.sh deleted file mode 100644 index b3b9f3b3..00000000 --- a/build_scripts/build-snowball.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash - -if [[ "$ARCH" == "" ]] || [[ "$DIST" == "" ]] || [[ "$NAME" == "" ]]; then - echo "Usage: env ARCH=... DIST=... NAME=... bash $0" - exit 2 -fi - -set -x -set -e - -# check out latest tag - -label=snowball-"$NAME"-"$ARCH" - -if [[ "$NAME" == "ce-specific" ]]; then - export BUILD_FOR_CE=1 -fi - -bash build_scripts/release.sh -mkdir -p ./bin/Release/lib - -if [[ "$OSTYPE" == "darwin"* ]]; then - mv libsnowballrt.dylib ./bin/Release/lib - mv libSnowball.dylib ./bin/Release/lib -else - mv libsnowballrt.so ./bin/Release/lib - mv libSnowball.so ./bin/Release/lib -fi - -mkdir release -mkdir -p release/bin -mkdir -p release/lib -cp -a ./bin/Release/. release/ -mv release/snowball release/bin/snowball - -if [[ "$NAME" == "darwin" ]]; then - echo "TODO: rpath for darwin" - #brew install patchelf -# - #patchelf --set-rpath '@loader_path/../lib' release/bin/snowball - #patchelf --set-rpath '@loader_path/../lib' release/lib/libSnowball.dylib -else - patchelf --set-rpath '$ORIGIN/../lib' release/bin/snowball - patchelf --set-rpath '$ORIGIN/../lib' release/lib/libSnowball.so - - cp /usr/lib/x86_64-linux-gnu/libpthread.so release/lib - cp /usr/lib/x86_64-linux-gnu/libssl.so.1.1 release/lib - cp /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 release/lib - cp /usr/lib/x86_64-linux-gnu/libstdc++.so.6 release/lib - cp /usr/lib/x86_64-linux-gnu/libgcc_s.so.1 release/lib -fi - -cp -R ./stdlib release/stdlib -tar -czvf "$label".tar.gz -C release/ . diff --git a/build_scripts/clean.sh b/build_scripts/clean.sh deleted file mode 100644 index a2abdf41..00000000 --- a/build_scripts/clean.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/bash -set -x - -cmake --build . --target clean -rm -rf ./_deps -rm -rf ./.cache -rm -rf ./build -rm -rf ./CMakeFiles -rm -rf ./libsnowball.so -rm -rf ./libSnowball.so -rm -rf ./Makefile -rm -rf ./cmake_install.cmake -rm -rf ./CMakeCache.txt -rm -rf ./bin diff --git a/build_scripts/cross-compile-windows.sh b/build_scripts/cross-compile-windows.sh deleted file mode 100644 index 2f1cf957..00000000 --- a/build_scripts/cross-compile-windows.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env sh - -# CURRENTLY BROKEN! - -set -e -export CXXFLAGS="-D_SN_DEBUG=0" -export CMAKE_TOOLCHAIN_FILE="build_scripts/toolchains-windows.cmake" -export LIBRARY_PATH=/usr/lib/x86_64-linux-gnu - -mkdir -p bin/Release -cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_BACKTRACES=OFF \ --DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF \ --DLLVM_ENABLE_TERMINFO=OFF \ --DLLVM_ENABLE_ZLIB=OFF \ --DLLVM_INCLUDE_EXAMPLES=OFF \ --DLLVM_INCLUDE_DOCS=OFF \ --DLLVM_TOOL_LLVM_AR_BUILD=OFF -DEXECUTABLE_OUTPUT_PATH="bin/Release" $@ . -cmake --build . --config Release -- -j 3 diff --git a/build_scripts/dbg.sh b/build_scripts/dbg.sh deleted file mode 100755 index a1aee3d3..00000000 --- a/build_scripts/dbg.sh +++ /dev/null @@ -1,12 +0,0 @@ -set -ex -mkdir -p bin/Debug -# TODO: remove "-DCLANG_ENABLE_OPAQUE_POINTERS=OFF" line when support for llvm 16 -cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr/local -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug \ --DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ --DLLVM_ENABLE_BACKTRACES=OFF \ --DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF \ --DLLVM_ENABLE_TERMINFO=OFF \ --DLLVM_ENABLE_ZLIB=OFF \ --DLLVM_INCLUDE_EXAMPLES=OFF \ --DLLVM_INCLUDE_DOCS=OFF -DEXECUTABLE_OUTPUT_PATH="bin/Debug" . -cmake --build . --config Debug $@ diff --git a/build_scripts/install_deps.sh b/build_scripts/install_deps.sh deleted file mode 100644 index f6660c15..00000000 --- a/build_scripts/install_deps.sh +++ /dev/null @@ -1,14 +0,0 @@ -#/usr/bin/env bash -set -x - -mkdir install_deps_temp -cd install_deps_temp - -wget https://apt.llvm.org/llvm.sh -chmod +x llvm.sh -sudo ./llvm.sh 16 - -sudo apt install -y libzstd-dev libsigsegv-dev pkg-config curl libgssapi3-heimdal - -cd .. -rm -rf install_deps_temp \ No newline at end of file diff --git a/build_scripts/install_stdlib.sh b/build_scripts/install_stdlib.sh deleted file mode 100644 index b1c117bb..00000000 --- a/build_scripts/install_stdlib.sh +++ /dev/null @@ -1,5 +0,0 @@ -set -x -SNOWBALL_INSTALL_DIR=~/.snowball - -mkdir -p "$SNOWBALL_INSTALL_DIR"/stdlib -cp -r stdlib/. "$SNOWBALL_INSTALL_DIR"/stdlib \ No newline at end of file diff --git a/build_scripts/release.sh b/build_scripts/release.sh deleted file mode 100644 index 4dc4aecf..00000000 --- a/build_scripts/release.sh +++ /dev/null @@ -1,22 +0,0 @@ -if [[ "$OSTYPE" != "darwin"* ]]; then - sudo -n apt install software-properties-common - sudo -n add-apt-repository ppa:ubuntu-toolchain-r/test - sudo -n apt update - sudo -n apt install gcc-9 g++-9 -y - sudo -n apt install cmake curl -y - - export CC="/usr/bin/gcc-9" - export CXX="/usr/bin/g++-9" -fi - -mkdir -p bin/Release -cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr/local -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release \ --DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ --DLLVM_ENABLE_BACKTRACES=OFF \ --DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF \ --DLLVM_ENABLE_TERMINFO=OFF \ --DLLVM_ENABLE_ZLIB=OFF \ --DLLVM_INCLUDE_EXAMPLES=OFF \ --DCMAKE_OSX_ARCHITECTURES="$ARCH" \ --DLLVM_INCLUDE_DOCS=OFF -DEXECUTABLE_OUTPUT_PATH="bin/Release" . -cmake --build . --config Release -- $@ -j10 \ No newline at end of file diff --git a/build_scripts/release_build.sh b/build_scripts/release_build.sh deleted file mode 100644 index ef993f8b..00000000 --- a/build_scripts/release_build.sh +++ /dev/null @@ -1,61 +0,0 @@ -#! /bin/bash - -echo Building for: "$NAME" - -if [[ "$ARCH" == "" ]] || [[ "$DIST" == "" ]] || [[ "$NAME" == "" ]]; then - echo "Usage: env ARCH=... DIST=... NAME=... bash $0" - exit 1 -fi - -set -e - -error() { - export TERM=xterm-256color - tput setaf 1 - tput bold - echo "Error:" "$@" - tput sgr0 -} - -if [[ "$OSTYPE" == "darwin"* ]]; then - brew install llvm@16 - brew install gcc - brew install zstd - brew install curl - - export LLVM_DIR="/usr/local/opt/llvm@16/lib/cmake" - bash build_scripts/build-snowball.sh -else - - # needed to keep user ID in and outside Docker in sync to be able to write to workspace directory - uid="$(id -u)" - image="$DIST":"$ARCH"-uid"$uid" - dockerfile=containers/"$DIST"/Dockerfile."$ARCH" - - echo $dockerfile - echo $uid - if [ ! -d "containers/$DIST" ]; then - error "Unknown dist: $DIST" - exit 2 - fi - - if [ "$DIST" == "common" ]; then - error "\"common\" is not a distro" - exit 2 - fi - - if [ ! -f "$dockerfile" ]; then - error "Dockerfile $dockerfile could not be found" - exit 3 - fi - - # build image to cache dependencies - docker build -t "$image" -f "$dockerfile" --build-arg UID="$uid" containers/"$DIST" - - # run build inside this image - EXTRA_ARGS=() - [ -t 1 ] && EXTRA_ARGS+=("-t") - docker run --rm -i "${EXTRA_ARGS[@]}" -e DOCKER=1 -v "$(readlink -f .)":/ws "$image" bash -xc "cd /ws && bash build_scripts/build-snowball.sh" - - ls -fi diff --git a/build_scripts/toolchains-windows.cmake b/build_scripts/toolchains-windows.cmake deleted file mode 100644 index 1237f1b1..00000000 --- a/build_scripts/toolchains-windows.cmake +++ /dev/null @@ -1,15 +0,0 @@ -# set(CMAKE_SYSTEM_NAME Windows) -set(CMAKE_SYSTEM_NAME Generic) -set(CMAKE_SYSTEM_PROCESSOR x86_64) - -set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) -set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) -set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres) - -# set(CMAKE_FIND_ROOT_PATH /usr/lib/x86_64-linux-gnu/) -set(CMAKE_EXE_LINKER_FLAGS "" CACHE INTERNAL "") - -set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) -set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) \ No newline at end of file diff --git a/installer/main.nsh b/installer/main.nsh deleted file mode 100644 index 57d45fe9..00000000 --- a/installer/main.nsh +++ /dev/null @@ -1,100 +0,0 @@ -; The name of the installer -Name "snowball" - -; To change from default installer icon: -;Icon "snowball.ico" - -; The setup filename -OutFile "snowball_Setup.exe" - -; The default installation directory -InstallDir $bin\Release\ - -; Registry key to check for directory (so if you install again, it will -; overwrite the old one automatically) -InstallDirRegKey HKLM "Software\snowball" "Install_Dir" - -RequestExecutionLevel admin - -;-------------------------------- - -; Pages - -Page components -Page directory -Page instfiles - -UninstPage uninstConfirm -UninstPage instfiles - -;-------------------------------- - -; The stuff to install -Section "snowball (required)" - - SectionIn RO - - ; Set output path to the installation directory. - SetOutPath $INSTDIR - - ; Put file there (you can add more File lines too) - File "snowball.exe" - ; Wildcards are allowed: - ; File *.dll - ; To add a folder named MYFOLDER and all files in it recursively, use this EXACT syntax: - ; File /r MYFOLDER\*.* - ; See: https://nsis.sourceforge.io/Reference/File - ; MAKE SURE YOU PUT ALL THE FILES HERE IN THE UNINSTALLER TOO - - File "..\..\libsnowballrt.so" - - CopyFiles /SILENT /FILESONLY "$INSTDIR\lib" "..\..\libsnowballrt.so" - - - ; Write the installation path into the registry - WriteRegStr HKLM SOFTWARE\snowball "Install_Dir" "$INSTDIR" - - ; Write the uninstall keys for Windows - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\snowball" "DisplayName" "snowball" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\snowball" "UninstallString" '"$INSTDIR\uninstall.exe"' - WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\snowball" "NoModify" 1 - WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\snowball" "NoRepair" 1 - WriteUninstaller "$INSTDIR\uninstall.exe" - -SectionEnd - -; Optional section (can be disabled by the user) -Section "Start Menu Shortcuts (required)" - SectionIn RO - - CreateDirectory "$SMPROGRAMS\snowball" - CreateShortcut "$SMPROGRAMS\snowball\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 - CreateShortcut "$SMPROGRAMS\snowball\snowball.lnk" "$INSTDIR\snowball.exe" "" "$INSTDIR\snowball.exe" 0 - -SectionEnd - -;-------------------------------- - -; Uninstaller - -Section "Uninstall" - - ; Remove registry keys - DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\snowball" - DeleteRegKey HKLM SOFTWARE\snowball - - ; Remove files and uninstaller - ; MAKE SURE NOT TO USE A WILDCARD. IF A - ; USER CHOOSES A STUPID INSTALL DIRECTORY, - ; YOU'LL WIPE OUT OTHER FILES TOO - Delete $INSTDIR\snowball.exe - Delete $INSTDIR\uninstall.exe - - ; Remove shortcuts, if any - Delete "$SMPROGRAMS\snowball\*.*" - - ; Remove directories used (only deletes empty dirs) - RMDir "$SMPROGRAMS\snowball" - RMDir "$INSTDIR" - -SectionEnd \ No newline at end of file diff --git a/src/SourceInfo.h b/src/SourceInfo.h deleted file mode 100644 index 6d5803c1..00000000 --- a/src/SourceInfo.h +++ /dev/null @@ -1,33 +0,0 @@ - -#include -#include - -#ifndef __SNOWBALL_SOURCE_INFO_H_ -#define __SNOWBALL_SOURCE_INFO_H_ - -namespace snowball { - -/** - * @brief The source info is used so that the compiler knows - * where and what it's currently compiling - */ -class SourceInfo { - public: - SourceInfo(std::string p_code = "", std::string p_path = "") - : source(p_code), path(((std::filesystem::path) p_path).lexically_normal()), source_length(p_code.size()) {}; - - /// @brief Get the source content for the file - std::string getSource() const { return source; }; - /// @return The current file being working on - std::string getPath() const { return path; }; - - const int source_length = 0; - ~SourceInfo() noexcept = default; - - private: - std::string source; - std::string path; -}; -} // namespace snowball - -#endif // __SNOWBALL_SOURCE_INFO_H_ diff --git a/src/ValueVisitor/Visitor.h b/src/ValueVisitor/Visitor.h deleted file mode 100644 index a6e19569..00000000 --- a/src/ValueVisitor/Visitor.h +++ /dev/null @@ -1,44 +0,0 @@ - -#include "../common.h" - -#ifndef __SNOWBALL_VALUE_VISITOR_H_ -#define __SNOWBALL_VALUE_VISITOR_H_ - -namespace snowball { -namespace ir { -class Value; - -#define VISIT(n) class n; -#include "../defs/visits.def" -#undef VISIT - -} // namespace ir - -namespace codegen { - -/** - * @brief Value visitor - * - * This class is just a tree visitor that we - * can use for different scenarios. e.g. for - * type checking and for generating llvm ir. - */ -class ValueVisitor { - public: - /** - * @brief Start the codegen process - * - * Transform the value tree into an output the - * can use for another process. - */ - virtual void codegen() = 0; - -#define VISIT(n) virtual void visit(ir::n*) = 0; -#include "../defs/visits.def" -#undef VISIT -}; - -} // namespace codegen -} // namespace snowball - -#endif // __SNOWBALL_VALUE_VISITOR_H_ diff --git a/src/ast/cache/Cache.h b/src/ast/cache/Cache.h deleted file mode 100644 index d0bcf9fb..00000000 --- a/src/ast/cache/Cache.h +++ /dev/null @@ -1,32 +0,0 @@ - - -#include "../../sourceInfo/SourcedObject.h" -#include "../syntax/nodes.h" - -#include -#include -#include - -#ifndef __SNOWBALL_AST_CACHE_H_ -#define __SNOWBALL_AST_CACHE_H_ - -#include "FunctionCache.h" -#include "ModuleCache.h" -#include "TypeCache.h" - -namespace snowball { -namespace Syntax { - -/** - * @brief The cache class - * - * This class is used for temporal storage where - * it can't affect for the real one. It also adds - * some extra context to the ast visitor. - */ -class Cache : public cacheComponents::Functions, public cacheComponents::Types, public cacheComponents::Modules { }; - -} // namespace Syntax -} // namespace snowball - -#endif // __SNOWBALL_AST_CACHE_H_ diff --git a/src/ast/cache/FunctionCache.cc b/src/ast/cache/FunctionCache.cc deleted file mode 100644 index 44dad05e..00000000 --- a/src/ast/cache/FunctionCache.cc +++ /dev/null @@ -1,92 +0,0 @@ - - -#include "FunctionCache.h" - -#include "../types/DefinedType.h" -#include "../types/TypeAlias.h" - -namespace snowball { -using namespace services; - -namespace Syntax { -namespace cacheComponents { - -std::shared_ptr& Functions::getFunctionState(id_t id) { return functionStates.at(id); } -void Functions::setFunctionState(id_t id, std::shared_ptr& s) { functionStates[id] = s; } -void Functions::setFunction( - const std::string& name, Statement::FunctionDef* p_fn, std::shared_ptr state -) { - functions[name].push_front({p_fn, state}); -} - -std::optional> Functions::getFunction(const std::string name) { - auto f = functions.find(name); - if (f != functions.end()) return f->second; - return std::nullopt; -} - -void Functions::setTransformedFunction(const std::string& uuid, std::shared_ptr p_fn) { - if (createdFunctions.count(uuid)) { - auto x = createdFunctions.at(uuid); - for (auto f : p_fn->getFunctions()) { x->addFunction(f); } - return; - } - createdFunctions[uuid] = p_fn; -} - -std::optional> Functions::getTransformedFunction(const std::string uuid) { - auto f = createdFunctions.find(uuid); - if (f != createdFunctions.end()) return f->second; - return std::nullopt; -} - -namespace { -template -std::map getAllFunctionsByUUID(std::string uuid, std::map& functions) { - std::map result; - for (auto f : functions) { - if (utils::startsWith(f.first + ".", uuid)) { result[f.first] = f.second; } - } - return result; -} -} // namespace - -void Functions::performInheritance(types::DefinedType* ty, types::DefinedType* parent, bool allowConstructor) { - // Inherit all the way down - if (parent->getParent() != nullptr) performInheritance(ty, parent->getParent(), allowConstructor); - auto parentUUID = parent->getUUID(); - auto childUUID = ty->getUUID(); - auto createdFuncs = getAllFunctionsByUUID(parentUUID, createdFunctions); - auto nonGeneratedFunctions = getAllFunctionsByUUID(parentUUID, functions); - for (auto f : createdFuncs) { - auto name = f.first; - auto item = f.second; - auto functions = item->getFunctions(); - utils::replaceAll(name, parentUUID + ".", ""); - if (OperatorService::opEquals(name) && !allowConstructor) continue; - name = childUUID + "." + name; - setTransformedFunction(name, std::make_shared(*item)); - for (auto x : functions) { - if (x->inVirtualTable()) { ty->addVtableItem(x); } - } - } - for (auto f : nonGeneratedFunctions) { - auto name = f.first; - auto item = f.second; - auto functions = item; - // TODO: avoid constructors? - utils::replaceAll(name, parentUUID + ".", ""); - if (OperatorService::opEquals(name) && !allowConstructor) continue; - name = childUUID + "." + name; - for (auto fn : functions) { setFunction(name, fn.function, fn.state); } - } - for (auto f : parent->getFields()) { - ty->addField(f); - } - ty->hasVtable = parent->hasVtable; - return; -} - -} // namespace cacheComponents -} // namespace Syntax -} // namespace snowball diff --git a/src/ast/cache/FunctionCache.h b/src/ast/cache/FunctionCache.h deleted file mode 100644 index a19a0e14..00000000 --- a/src/ast/cache/FunctionCache.h +++ /dev/null @@ -1,81 +0,0 @@ - -#include "../../ir/module/Module.h" -#include "../../ir/values/Func.h" - -#include -#include -#include -#include -#include - -#ifndef __SNOWBALL_AST_FUNCTION_CACHE_H_ -#define __SNOWBALL_AST_FUNCTION_CACHE_H_ - -#include "../../visitors/TransformState.h" - -namespace snowball { -namespace Syntax { - -namespace transform { -class Item; -} - -namespace cacheComponents { - -/** - * @brief Cache component for functions - * - * Everything about function's polymorfism is stored - * inside this cache component. - * - * Things like overloads, generic functions, etc will - * be stored here. - */ -class Functions { - public: - /** - * @brief Representation of how functions are stored - * inside the cache. "State" refers to the transformer - * state that manages the current context and scope - * it was located at before being added to the cache. - */ - struct FunctionStore { - Statement::FunctionDef* function = nullptr; - std::shared_ptr state; - }; - - protected: - /// @brief A global map containing each function. - std::map> functions; - /// @brief a list of already transformed functions - std::map> createdFunctions; - /// @brief A map of states used for generated functions. - /// @note this can be used for things such as; default arguments - std::unordered_map> functionStates; - - public: - /// @brief Set a new function overload - void - setFunction(const std::string& name, Statement::FunctionDef* p_fn, std::shared_ptr state); - /// @return All function overloads for a function - std::optional> getFunction(const std::string name); - /// @return Get the current state of an already defined - /// function. - std::shared_ptr& getFunctionState(id_t id); - /// @brief defined a new state where the function has been - /// generated from - void setFunctionState(id_t id, std::shared_ptr& s); - /// @brief Set a new transformed function - /// @c Transformer::addFunction - void setTransformedFunction(const std::string& uuid, std::shared_ptr p_fn); - /// @return get an item of an already transformed function - std::optional> getTransformedFunction(const std::string uuid); - /// Copy a list of functions to a new list for a new type - void performInheritance(types::DefinedType* ty, types::DefinedType* parent, bool allowConstructor = false); -}; - -} // namespace cacheComponents -} // namespace Syntax -} // namespace snowball - -#endif // __SNOWBALL_AST_FUNCTION_CACHE_H_ diff --git a/src/ast/cache/ModuleCache.cc b/src/ast/cache/ModuleCache.cc deleted file mode 100644 index 2644b88d..00000000 --- a/src/ast/cache/ModuleCache.cc +++ /dev/null @@ -1,21 +0,0 @@ - -#include "ModuleCache.h" - -namespace snowball { -namespace Syntax { -namespace cacheComponents { - -void Modules::addModule(const std::string& uuid, std::shared_ptr module) { - assert(!getModule(uuid).has_value()); - modules[uuid] = module; -} - -std::optional> Modules::getModule(const std::string& uuid) { - auto f = modules.find(uuid); - if (f != modules.end()) return f->second; - return std::nullopt; -} - -} // namespace cacheComponents -} // namespace Syntax -} // namespace snowball diff --git a/src/ast/cache/ModuleCache.h b/src/ast/cache/ModuleCache.h deleted file mode 100644 index 9c5766bc..00000000 --- a/src/ast/cache/ModuleCache.h +++ /dev/null @@ -1,37 +0,0 @@ - -#include -#include -#include -#include - -#include "../../ir/module/Module.h" - -#ifndef __SNOWBALL_AST_MODULE_CACHE_H_ -#define __SNOWBALL_AST_MODULE_CACHE_H_ - -namespace snowball { -namespace Syntax { - -namespace cacheComponents { - -/** - * @brief Cache component for modules. This is used - * for caching modules that are imported. - */ -class Modules { - protected: - /// @brief A global map containing each module. - std::map> modules; - - public: - /// @brief add a new module to the cache - void addModule(const std::string& uuid, std::shared_ptr module); - /// @brief get a module from the cache - std::optional> getModule(const std::string& uuid); -}; - -} // namespace cacheComponents -} // namespace Syntax -} // namespace snowball - -#endif // __SNOWBALL_AST_MODULE_CACHE_H_ diff --git a/src/ast/cache/TypeCache.cc b/src/ast/cache/TypeCache.cc deleted file mode 100644 index f411c842..00000000 --- a/src/ast/cache/TypeCache.cc +++ /dev/null @@ -1,45 +0,0 @@ - -#include "TypeCache.h" - -#include "../types/DefinedType.h" - -namespace snowball { -namespace Syntax { -namespace cacheComponents { - -void Types::setType(const std::string uuid, Statement::Base* p_ty, std::shared_ptr state) { - assert(utils::cast(p_ty) || utils::cast(p_ty) - || utils::cast(p_ty)); - types.insert({uuid, TypeStore{p_ty, state}}); -} - -void Types::setTransformedType( - const std::string uuid, std::shared_ptr p_ty, const std::string overloadedUUID -) { - auto storeUUID = overloadedUUID.empty() ? uuid : overloadedUUID; - identifierLookup[uuid].emplace_back(storeUUID); - createdTypes[storeUUID] = p_ty; -} - -std::optional>> Types::getTransformedType(const std::string& uuid) { - auto identifiers = identifierLookup.find(uuid); - if (identifiers == identifierLookup.end()) return std::nullopt; - std::vector> typesFound; - for (auto id : identifiers->second) { - auto type = createdTypes.find(id); - assert(type != createdTypes.end()); - typesFound.emplace_back(type->second); - } - if (typesFound.size() > 0) return typesFound; - return std::nullopt; -} - -std::optional Types::getType(const std::string uuid) { - auto f = types.find(uuid); - if (f != types.end()) return f->second; - return std::nullopt; -} - -} // namespace cacheComponents -} // namespace Syntax -} // namespace snowball diff --git a/src/ast/cache/TypeCache.h b/src/ast/cache/TypeCache.h deleted file mode 100644 index 48f9a307..00000000 --- a/src/ast/cache/TypeCache.h +++ /dev/null @@ -1,75 +0,0 @@ - -#include "../../ir/values/Func.h" - -#include -#include -#include -#include - -#ifndef __SNOWBALL_AST_TYPE_CACHE_H_ -#define __SNOWBALL_AST_TYPE_CACHE_H_ - -#include "../../visitors/TransformItem.h" -#include "../../visitors/TransformState.h" -#include "../types/DefinedType.h" -#include "../types/Interface.h" -#include "../types/EnumType.h" -#include "../types/TypeAlias.h" - -namespace snowball { -namespace Syntax { - -namespace transform { -class Item; -} - -namespace cacheComponents { - -/** - * @brief Cache component for types. - * - * Types can have generics, making them unique - * based on their generics also making my life misserable. - */ -class Types { - public: - /** - * @brief Representation of how functions are stored - * inside the cache. "State" refers to the transformer - * state that manages the current context and scope - * it was located at before being added to the cache. - */ - struct TypeStore { - Statement::Base* type = nullptr; - std::shared_ptr state; - }; - - protected: - /// @brief A global map containing each class. - std::unordered_map types; - /// @brief a list of already transformed types - std::unordered_map> createdTypes; - - public: - /// @brief A map containing what UUIDs are associated with it's original identifiers - /// @example Foo -> [Foo:1, Foo:2, ...] - std::unordered_map> identifierLookup; - - public: - /// @brief Set a new type to the cache - void setType(const std::string uuid, Statement::Base* p_ty, std::shared_ptr state); - /// @brief add a new generated class to the cache - void setTransformedType( - const std::string uuid, std::shared_ptr p_ty, const std::string overloadedUUID = "" - ); - /// @brief add a new generated class to the cache - std::optional>> getTransformedType(const std::string& uuid); - /// @return All function overloads for a function - std::optional getType(const std::string uuid); -}; - -} // namespace cacheComponents -} // namespace Syntax -} // namespace snowball - -#endif // __SNOWBALL_AST_TYPE_CACHE_H_ diff --git a/src/ast/errors/error.h b/src/ast/errors/error.h deleted file mode 100644 index ce581315..00000000 --- a/src/ast/errors/error.h +++ /dev/null @@ -1,36 +0,0 @@ - -#include "../../errors.h" -#include "../../sourceInfo/SourcedObject.h" -#include "../syntax/nodes.h" - -#include -#include -#include - -#ifndef __SNOWBALL_AST_ERROR_H_ -#define __SNOWBALL_AST_ERROR_H_ - -namespace snowball { -namespace Syntax { - -template -auto EI(Val item, std::string msg = "", ErrorInfo info = {}) { - auto i = item->getDBGInfo(); - auto error = new CompilerError(e, msg, i, info); - return error; -} - -template -void E(Val item, std::string msg, ErrorInfo info = {}) noexcept(false) { - throw* EI(item, msg, info); -} - -template -void E(std::string msg) noexcept(false) { - throw SNError(e, msg); -} - -} // namespace Syntax -} // namespace snowball - -#endif // __SNOWBALL_AST_ERROR_H_ diff --git a/src/ast/syntax/accepts.cc b/src/ast/syntax/accepts.cc deleted file mode 100644 index ea5469fd..00000000 --- a/src/ast/syntax/accepts.cc +++ /dev/null @@ -1,14 +0,0 @@ - -#include "../visitor/Visitor.h" -#include "common.h" -#include "nodes.h" - -namespace snowball { -namespace Syntax { - -#define ACCEPT(Node) \ - void Node::accept(Syntax::Visitor* v) { v->visit(this); } -#include "../../defs/accepts.def" - -} // namespace Syntax -} // namespace snowball diff --git a/src/ast/syntax/common.h b/src/ast/syntax/common.h deleted file mode 100644 index c437b0cd..00000000 --- a/src/ast/syntax/common.h +++ /dev/null @@ -1,480 +0,0 @@ - - -#include "../../common.h" -#include "../../sourceInfo/DBGSourceInfo.h" - -#include -#include -#include -#include -#include -#include - -#ifndef __SNOWBALL_AST_COMMON_NODES_H_ -#define __SNOWBALL_AST_COMMON_NODES_H_ - -#include "../types/Type.h" - -#define ACCEPT() void accept(Syntax::Visitor* v) override; - -namespace snowball { - -/// @brief An enum representing the attributes that can be stored -/// for a node. -enum Attributes { - // Default attributes - INVALID, - CFG, - ATTR, - - // FUNCTION ATTRIBUTES - TEST, - BENCH, - LLVM_FUNC, - INTERNAL_LINKAGE, - EXTERNAL_LINKAGE, - INLINE, - NO_INLINE, - NO_MANGLE, - NOT_IMPLEMENTED, - EXPORT, - OVERRIDE, - FIRST_ARG_IS_SELF, - UNSAFE_FUNC_NOT_BODY, - UNSAFE, // also used for blocks - - // Builting related attributes - BUILTIN, - NO_POINTER_SELF, - INTRINSIC, - - // Function internal attributes - TYPECHECKED, - ALLOW_FOR_TEST, - ALLOW_FOR_BENCH, - - // Class attributes - CLASS_EXTENDS, - NO_CONSTRUCTOR, - - // Import attributes - MACROS, -}; - -namespace Syntax { -namespace transform { -struct MacroInstance; -} -// Forward declarations -class Visitor; -class WhereClause; - -/** - * A generic class that accepts an enum as a template parameter and - * stores and checks attributes for a node. - */ -class AttributeHolder { - using StoreType = std::unordered_map; - std::unordered_map arguments; - - public: - /** - * Checks if a specific attribute is set for the node. - * - * @param attribute The attribute to check. - * @return True if the attribute is set, false otherwise. - */ - bool hasAttribute(Attributes attribute) const { return (m_attributes & (1 << static_cast(attribute))) != 0; } - /** - * Sets the bit for a specific attribute in the `m_attributes` - * variable. - * - * @param attribute The attribute to add. - */ - auto addAttribute(Attributes attribute, StoreType args = {}) { - arguments[attribute] = args; - return m_attributes |= (1 << static_cast(attribute)); - } - /** - * Sets a new list of attributes to the current holder - */ - void setAttributes(unsigned int attribute, std::unordered_map& args) { - m_attributes = attribute; - arguments = args; - } - /** - * Returns the respective unsigned integer for the attributes - */ - auto getAttributes() const { return m_attributes; } - /** - * Returns all the arguments for the attributes - */ - auto& getAllAttributeArgs() { return arguments; } - /** - * Sets the attributes from a holder - */ - void setAttributes(AttributeHolder* holder) { - arguments = std::move(holder->getAllAttributeArgs()); - m_attributes = holder->m_attributes; - } - /** - * Clears the bit for a specific attribute in the `m_attributes` - * variable. - * - * @param attribute The attribute to remove. - */ - void removeAttribute(Attributes attribute) { m_attributes &= ~(1 << static_cast(attribute)); } - /** - * Clears all attributes for the node by setting `m_attributes` - * to zero. - */ - void clearAttributes() { m_attributes = 0; } - - /** - * Gets the arguments for a specific attribute. - * @param attribute The attribute to get the arguments for. - * @return A vector containing the arguments for the attribute. - */ - StoreType getAttributeArgs(Attributes attribute) const { - auto it = arguments.find(attribute); - if (it == arguments.end()) return {}; - return it->second; - } - /** - * Get attr value - */ - std::optional getAttrValue(std::string attrName) { - if (hasAttribute(Attributes::ATTR)) { - auto args = getAttributeArgs(Attributes::ATTR); - auto it = args.find(attrName); - if (it != args.end()) return it->second; - } - return std::nullopt; - } - - private: - /** The bit field storing the attributes for the node. */ - unsigned int m_attributes = 0; -}; - -struct Macro; - -struct Node : public DBGObject, public AttributeHolder { - public: - Node() = default; - ~Node() noexcept = default; - - virtual void accept(Syntax::Visitor* v) = 0; - - transform::MacroInstance* parentMacro = nullptr; - /// @brief A flag that tells if the current node is - /// an operator - bool isOperator = false; -}; - -/** - * @brief This namespaces are used just for the more "generic" - * classes that can be inherited to make my life easier. - */ - -namespace Expression { -struct Base : public AcceptorExtend { }; - -// Making a reference to the type. This should only appear on the -// parser stage -struct TypeRef : public types::Type, public Base { - std::vector generics; - - /// @brief Internal type when using @fn types::Type::toRef(). - /// @note this shoudn't be used for normal usage! - types::Type* internalType = nullptr; - - /// @brief AST used to declare this TypeRef. - /// @note this shoudn't be used for normal usage! - Expression::Base* internalAST = nullptr; - - /// @brief The id of the type - std::string id; - - public: - TypeRef(std::string p_name, DBGSourceInfo* p_dbg, std::vector p_generics = {}, std::string id = ""); - TypeRef(std::string p_name, DBGSourceInfo* p_dbg, types::Type* internalType, std::string id); - TypeRef(Expression::Base* p_ast, std::string p_name, DBGSourceInfo* p_dbg, std::string id); - - /// @brief Get type's generics - std::vector getGenerics(); - /// @return A good looking, human readable representation of - /// this type. - std::string getPrettyName() const override; - /// @brief Set a generic list for this type - void setGenerics(std::vector g); - - /// @return Internal type when using @fn types::Type::toRef(). - /// @note this shoudn't be used for normal usage! - auto _getInternalType() { return internalType; } - - /// @return AST used to declare this TypeRef. - /// @note this shoudn't be used for normal usage! - auto _getInternalAST() { return internalAST; } - - /// @return true if it's a delctype(...) - virtual bool isTypeDecl() { return false; } - /// @return true if the type is a pointer - virtual bool isReferenceType() { return false; } - /// @return true if the type is a pointer - virtual bool isPointerType() { return false; } - /// @return true if the type is a function - virtual bool isFunctionType() { return false; } - - /// @return The id of the type - auto getId() { return id; } - - ACCEPT() - ~TypeRef() noexcept = default; -}; - -/** - * @class DeclType - * @brief A struct representing a declaration type that derives from - * TypeRef. - * - * This struct holds a pointer to a Base object and provides methods - * to access the expression value and determine if it is a type - * declaration. - */ -struct DeclType : public TypeRef { - Base* value; - - public: - DeclType(Base* value, DBGSourceInfo* srcInfo); - - /// @return the expr value to get the type from - auto getExpr() { return value; } - bool isTypeDecl() override { return true; } - - ~DeclType() noexcept = default; -}; - -/** - * @class FuncType - * @brief A struct representing a function type that derives from - * TypeRef. - * - * This struct holds a pointer to a TypeRef object and provides methods - * to access the type value and determine if it is a function type. - */ -struct FuncType : public TypeRef { - /// @brief The return value of the function - TypeRef* returnValue; - /// @brief The arguments of the function - std::vector args; - - public: - FuncType(std::vector args, TypeRef* returnValue, DBGSourceInfo* srcInfo); - - /// @return the arguments of the function - auto getArgs() { return args; } - /// @return the return value of the function - auto getReturnValue() { return returnValue; } - - bool isFunctionType() override { return true; } - - ~FuncType() noexcept = default; -}; - -/** - * @class TupleType - * @brief A struct representing a tuple type that derives from - * TypeRef. - * - * This struct holds a pointer to a TypeRef object and provides methods - * to access the type value and determine if it is a tuple type. - */ -struct TupleType : public TypeRef { - std::vector types; - - public: - TupleType(std::vector types, DBGSourceInfo* srcInfo); - - /// @return the arguments of the function - auto getTypes() { return types; } - - ~TupleType() noexcept = default; -}; - -/** - * @class ReferenceType - * @brief A struct representing a pointer type that derives from - * TypeRef. - * - * This struct holds a pointer to a TypeRef object and provides methods - * to access the type value and determine if it is a pointer type. - */ -struct ReferenceType : public TypeRef { - TypeRef* baseType; - - public: - ReferenceType(TypeRef* baseType, DBGSourceInfo* srcInfo); - - /// @return the expr value to get the type from - auto getBaseType() { return baseType; } - bool isReferenceType() override { return true; } - - ~ReferenceType() noexcept = default; -}; - -/** - * @class PointerType - * @brief A struct representing a pointer type that derives from - * TypeRef. - * - * This struct holds a pointer to a TypeRef object and provides methods - * to access the type value and determine if it is a pointer type. - */ -struct PointerType : public TypeRef { - TypeRef* baseType; - - public: - PointerType(TypeRef* baseType, bool isMutable, DBGSourceInfo* srcInfo); - - /// @return the expr value to get the type from - auto getBaseType() { return baseType; } - bool isPointerType() override { return true; } - - ~PointerType() noexcept = default; -}; - -/** - * @brief Represents a "where" clause in a program. - * - * The `WhereClause` struct is used to define constraints or conditions - * in a program. It is typically used in conjunction with templates or - * generic programming to restrict the types that can be used as arguments. - * - * @code rs - * fn example() { ... } - * ^^^^^^^^^^^^^^^^^ 2 checks - * @endcode - */ -struct WhereClause { - public: - using ChecksVectorType = std::vector; - - private: - /** - * @brief A vector containing the checks that should be executed - * for each generic argument. - */ - ChecksVectorType checks; - - public: - WhereClause(ChecksVectorType checks) : checks(checks) { } - explicit WhereClause(TypeRef* check) : checks(ChecksVectorType{check}) { } - - /// @return The checks to perform - auto getChecks() { return checks; } - - ~WhereClause() = default; -}; - -/// Function signature parameter helper node (name: type). -struct Param { - // Parameter's name. - std::string name; - - // Parameter's type. Note, if the prarameter - // type is "Generic", `type` actually refers - // to the default generic parameter. - TypeRef* type = nullptr; - /// @brief default value used for the function - Syntax::Expression::Base* defaultValue = nullptr; - /// @brief The where clause for the parameter- - /// @note This only should be for generic parameters! - WhereClause* whereClause = nullptr; - /// @brief Parameter status (aka: parameter type) - enum Status { - Normal, - Generic - } status; - /// @brief If the argument is mutable or not - bool mutableArg = false; - - public: - /// @brief Create a new param instance - explicit Param(std::string name = "", TypeRef* type = nullptr, Status generic = Normal); - - /// Get the param status, whether - /// it is a generic parameter or a normal one - auto getStatus() { return status; } - /// @return The parameter's type - TypeRef* getType() const { return type; }; - /// @brief Set parameter's type - void setType(TypeRef* ty) { type = ty; }; - /// @brief Set the default value to the parameter - void setDefaultValue(Base* b) { defaultValue = b; } - /// @brief Parameter's name - std::string getName() const { return name; }; - /// @brief check if the function contains a default value - bool hasDefaultValue() { return defaultValue != nullptr; } - /// @return default value if it exists - auto getDefaultValue() { - assert(status == Normal); - assert(hasDefaultValue()); - return defaultValue; - } - /// @return The where clause for this generic parameter - auto getWhereClause() const { - assert(status == Generic); - return whereClause; - }; - /// @brief Set The where clause for this generic parameter - void setWhereClause(WhereClause* clause) { - assert(status == Generic); - whereClause = clause; - }; - /// @brief Set the parameter's mutability - void setMutable(bool m = true) { mutableArg = m; } - /// @brief If the variable is mutable or not - bool isMutable() { return mutableArg; } -}; -} // namespace Expression - -namespace Statement { - -/** - * This struct is used a sort of container - * for any node that require generic - * expressions. - * - * e.g. Functions, classes, etc... - */ -template -struct GenericContainer { - using GenericList = std::vector; - GenericList generics; - - bool _generic = false; - - public: - GenericContainer() = default; - GenericContainer(GenericList generics) : _generic(true), generics(generics) {}; - - GenericList getGenerics() const { return generics; } - void setGenerics(GenericList list) { - _generic = true; - generics = std::move(list); - } - - /// @return iterator to the first generic - auto genericsBegin() { return generics.begin(); } - /// @return iterator beyond the last generic - auto genericsEnd() { return generics.end(); } - /// @return true if the node has generics - bool isGeneric() { return _generic; } -}; -} // namespace Statement - -} // namespace Syntax -} // namespace snowball - -#endif // __SNOWBALL_AST_COMMON_NODES_H_ diff --git a/src/ast/syntax/exprs.cc b/src/ast/syntax/exprs.cc deleted file mode 100644 index 76fc1ef7..00000000 --- a/src/ast/syntax/exprs.cc +++ /dev/null @@ -1,184 +0,0 @@ - -#include "../errors/error.h" -#include "../types/Type.h" -#include "common.h" -#include "nodes.h" - -#include -#include -#include - -namespace snowball { -namespace Syntax { -namespace Expression { - -DeclType::DeclType(Base* value, DBGSourceInfo* srcInfo) : value(value), TypeRef("decltype(...)", srcInfo) {}; -FuncType::FuncType(std::vector args, TypeRef* returnValue, DBGSourceInfo* srcInfo) - : args(args), returnValue(returnValue), TypeRef("fn(...)", srcInfo) {}; -ReferenceType::ReferenceType(TypeRef* baseType, DBGSourceInfo* srcInfo) - : baseType(baseType), TypeRef(baseType->getName() + "&", srcInfo) {}; -PointerType::PointerType(TypeRef* baseType, bool isMutable, DBGSourceInfo* srcInfo) - : baseType(baseType), TypeRef(baseType->getName() + "*", srcInfo) { setMutable(isMutable);}; -TupleType::TupleType(std::vector types, DBGSourceInfo* srcInfo) - : TypeRef("", srcInfo), types(types) { } -PseudoVariable::PseudoVariable(std::string identifier) : identifier(identifier) {}; -void PseudoVariable::setArgs(std::vector args) { - this->args = args; - hasArguments = true; -} -bool PseudoVariable::hasArgs() const { return hasArguments; } -std::vector PseudoVariable::getArgs() const { return args; } -TypeRef::TypeRef(Expression::Base* p_ast, std::string p_name, DBGSourceInfo* p_dbg, std::string id) - : internalAST(p_ast), types::Type(REF, p_name), id(id) { - setDBGInfo(p_dbg); -} -TypeRef::TypeRef(std::string p_name, snowball::DBGSourceInfo* p_dbg, std::vector p_generics, std::string id) - : generics(p_generics), types::Type(REF, p_name), id(id) { - setDBGInfo(p_dbg); -} -TypeRef::TypeRef(std::string p_name, DBGSourceInfo* p_dbg, types::Type* internalType, std::string id) - : internalType(internalType), types::Type(REF, p_name), id(id) { - setDBGInfo(p_dbg); -} -NewInstance::NewInstance(DBGSourceInfo* dbg, std::vector args, TypeRef* ty) : type(ty) { - auto call = Syntax::N(ty->toRef(), args); - call->setDBGInfo(dbg); - this->call = call; -} -void TypeRef::setGenerics(std::vector g) { generics = g; } -std::vector GenericIdentifier::getGenerics() const { return generics; } -std::vector TypeRef::getGenerics() { return this->generics; } -Param::Param(std::string name, TypeRef* type, Status generic) : name(name), type(type), status(generic) { - assert(generic <= 1 && generic >= 0 && "Invalid param status"); -} // clang-format off -bool BinaryOp::is_assignment(OpType opType) { - return opType == OpType::EQ || opType == OpType::PLUSEQ || - opType == OpType::MINUSEQ || - opType == OpType::MULEQ || opType == OpType::DIVEQ || - opType == OpType::MOD_EQ || - opType == OpType::BIT_LSHIFT_EQ || - opType == OpType::BIT_RSHIFT_EQ || - opType == OpType::BIT_OR_EQ || - opType == OpType::BIT_AND_EQ || - opType == OpType::BIT_XOR_EQ; -} -bool BinaryOp::is_assignment(BinaryOp* p_node) { - OpType p_op_type = p_node->op_type; - return is_assignment(p_op_type); -} -bool BinaryOp::is_comp(OpType opType) { - return opType == OpType::GT || opType == OpType::LT || - opType == OpType::GTEQ || opType == OpType::LTEQ || - opType == OpType::EQEQ || opType == OpType::NOTEQ; -} -std::string BinaryOp::to_string() const { -#define OP_CASE(op, symbol) case OpType::op: return symbol; -#define OP_DEFAULT default: assert(false); - switch (op_type) { - OP_CASE(GT, ">") OP_CASE(LT, "<") - OP_CASE(GTEQ, ">=") OP_CASE(EQEQ, "==") - OP_CASE(LTEQ, "<=") OP_CASE(NOTEQ, "!=") - // Mathematical symbols - OP_CASE(MOD, "%") OP_CASE(DIV, "/") - OP_CASE(MUL, "*") OP_CASE(UPLUS, "+") - OP_CASE(PLUS, "+") OP_CASE(MINUS, "-") - OP_CASE(UMINUS, "-") OP_CASE(MULEQ, "*=") - OP_CASE(DIVEQ, "/=") OP_CASE(PLUSEQ, "+=") - OP_CASE(MOD_EQ, "%=") OP_CASE(MINUSEQ, "-=") - OP_CASE(REFERENCE, "&") - // Assignment - OP_CASE(EQ, "=") OP_CASE(OR, "||") - OP_CASE(AND, "&&") OP_CASE(NOT, "!") - // Bitwise operations - OP_CASE(BIT_OR, "|") OP_CASE(BIT_NOT, "~") - OP_CASE(BIT_AND, "&") OP_CASE(BIT_XOR, "^") - OP_CASE(BIT_OR_EQ, "|=") OP_CASE(BIT_LSHIFT, "<<") - OP_CASE(BIT_RSHIFT, ">>") OP_CASE(BIT_AND_EQ, "&=") - OP_CASE(BIT_XOR_EQ, "^=") OP_CASE(BIT_LSHIFT_EQ, "<<=") - OP_CASE(BIT_RSHIFT_EQ, ">>=") - OP_DEFAULT - } -#undef OP_CASE -#undef OP_DEFAULT -} // clang-format on - -std::string FunctionCall::getArgumentsAsString(const std::vector args) { - std::string result; - int i = 0; - for (auto arg = args.begin(); arg != args.end(); ++arg) { - result += (*arg)->getPrettyName(); - if (i != (int)args.size() - 1) { result += ", "; } - i++; - } - return result; -} - -std::string GenericIdentifier::getNiceName() const { - std::string gens = "<"; - int gIndex = 0; - for (auto t : generics) { - gens += t->getPrettyName(); - if (gIndex != (int)(generics.size() - 1)) { gens += ", "; } - gIndex++; - } - return identifier + (gIndex > 0 ? gens + ">" : ""); -} - -#define CASE(t, r) \ - case TokenType::t: return r; -ConstantValue::ConstantType ConstantValue::deduceType(TokenType ty) { - switch (ty) { - CASE(VALUE_STRING, String) - CASE(VALUE_CHAR, Char) - CASE(VALUE_FLOAT, Float) - CASE(VALUE_NUMBER, Number) - CASE(VALUE_BOOL, Bool) - default: E(FMT("Unknown token type, coudn't deduce! (ty: %i)", ty)); - } - UNREACHABLE -} -#undef CASE - -std::string TypeRef::getPrettyName() const { - std::string gens = "<"; - int gIndex = 0; - for (auto t : generics) { - gens += t->getPrettyName(); - if (gIndex != (int)(generics.size() - 1)) { gens += ", "; } - gIndex++; - } - return getName() + (gIndex > 0 ? gens + ">" : ""); -} - -} // namespace Expression - -std::string Macro::arguementTypeToString(Macro::ArguementType t) { - switch (t) { - case Macro::ArguementType::CONSTANT: return "constant"; - case Macro::ArguementType::EXPRESSION: return "expression"; - case Macro::ArguementType::STATEMENT: return "statement"; - case Macro::ArguementType::CONSTANT_STRING: return "constant string"; - case Macro::ArguementType::CONSTANT_NUMBER: return "constant number"; - case Macro::ArguementType::CONSTANT_CHAR: return "constant char"; - case Macro::ArguementType::TYPE: return "type"; - default: E(FMT("Unknown arguement type '%i'!", t)); - } - UNREACHABLE -} - -std::string Macro::arguementTypeToSyntax(ArguementType type) { - switch (type) { - case ArguementType::CONSTANT: return "const"; - case ArguementType::EXPRESSION: return "expr"; - case ArguementType::STATEMENT: return "stmt"; - case ArguementType::CONSTANT_STRING: return "const[str]"; - case ArguementType::CONSTANT_NUMBER: return "const[num]"; - case ArguementType::CONSTANT_CHAR: return "const[chr]"; - case ArguementType::TYPE: return "type"; - default: E(FMT("Unknown arguement type '%i'!", type)); - } - UNREACHABLE -} - -} // namespace Syntax -} // namespace snowball diff --git a/src/ast/syntax/nodes.h b/src/ast/syntax/nodes.h deleted file mode 100644 index fe0789a6..00000000 --- a/src/ast/syntax/nodes.h +++ /dev/null @@ -1,1455 +0,0 @@ - -#include "../../common.h" -#include "../../services/OperatorService.h" -#include "../../sourceInfo/DBGSourceInfo.h" -#include "../../utils/utils.h" -#include "../types/Type.h" -#include "common.h" - -#include -#include - -#ifndef __SNOWBALL_AST_NODES_H_ -#define __SNOWBALL_AST_NODES_H_ - -/** - * Syntax nodes are a way for snowball to understand - * what the source code means in it's own "compiled" - * format. - * - * This is sort of an AST (abstract syntax tree) in - * where the parser creates a syntax tree that will - * make it much easier to interpret the source code. - * - * The nodes are divided into 2 sections. There are - * the expressions and the statements. - */ -namespace snowball { -namespace Syntax { - -namespace transform { -struct ContextState; -} - -class Visitor; - -// In snowball, a block is composed of -// a list of nodes. -struct Block : AcceptorExtend { - std::vector stmts; - - public: - Block() : AcceptorExtend() {}; - Block(std::vector s) : AcceptorExtend(), stmts(s) { } - ~Block() noexcept = default; - - // Aceptance for the AST visitor - ACCEPT() - // Geter function to fetch the parsed statements - auto getStmts() { return stmts; } - // Append a new statement to the block - void append(Node* stmt); -}; - -/** - * AST representation of a comment. Comments are ignored - * by the compiler but we can still use them to document - */ -struct Comment { - std::map values; - std::string body; - bool valid = false; - - public: - Comment(std::map values, std::string body, bool valid = false) - : values(values), body(body), valid(valid) {}; - - /// @return Get the comment's body - std::string getBody() const { return body; } - /// @return Get the comment's values - std::map getValues() const { return values; } - - bool isValid() const { return valid; } -}; - -/** - * An expression in snowball is a value, - * or anything that executes and ends up being a value. - * - * var x = 1 + 2 - * ^^^^^ - * In this case, we consider "1 + 2" as an binary operator - * expression. - * - */ -namespace Expression { - -/** - * This struct represents a constant value from the AST. - * A constant is a value that cannot be altered by the program. - * - * These are things like: numbers, strings, null, etc... e.g.: - * 123, "hello", 89.12, null are constant values. - */ -struct ConstantValue : public AcceptorExtend { - public: - /** - * This enum allows a constant value to be - * differentiate from the other ones. - */ - enum ConstantType { -#include "../../defs/ct.def" - }; - - private: - /** - * The value holding the constant as a string. - * This constant value can be any of the types. - * - * note: Constant strings will have the quotes - * included. - */ - std::string value; - - // Constant value type to know what is what. - ConstantType type; - - // @brief Constant's value prefix - // @example b"hello" -> prefix = "b" - std::string prefix = ""; - - public: - using AcceptorExtend::AcceptorExtend; - - ConstantValue(ConstantType type, std::string value, std::string prefix = "") - : type(type), value(value), prefix(prefix) {}; - - /// @return Get constant value - std::string getValue() const { return value; } - /// @return Get the type that defines this constant. - ConstantType getType() const { return type; } - /// @return Get the prefix of the constant - std::string getPrefix() const { return prefix; } - - ACCEPT() - - public: - /** - * @brief Deduce the constant type based on the token type. - * @return Respective constant type - */ - static ConstantType deduceType(TokenType ty); -}; - -/** - * @brief A representation of a cast for a value to a - * certain type. - * @example of converting an integer to a float 32 - * 1 | 123 as f32 - * | ^^^ ^^ ^^^ - cast to f32 - * | | |___ cast operator - * | |_____ value to cast from - */ -struct Cast : public AcceptorExtend { - private: - /// @brief Value that's needed to be casted - Base* value; - /// @brief Result type thats casted to - TypeRef* type; - - public: - using AcceptorExtend::AcceptorExtend; - - Cast(Base* value, TypeRef* ty) : type(ty), value(value) {}; - - /// @return The value to cast - auto getValue() { return value; } - /// @brief get the type trying to be casted to - auto getType() { return type; } - - ACCEPT() -}; - -/** - * Representation of a function call. Functions aren't generated - * until it's being called. - * - * @example - * f(x) -> we know the number/types of arguments, and the function - * name. We can use this information in order to deduce - * what function we should use. - */ -struct FunctionCall : public AcceptorExtend { - /** - * The callee value that's going to be called. - * Unlike most programming languages, function calls dont - * require an identifier because it can just call any expression - * that ends up being a function and has a respective function - * type. - * @example for correct usage - * myFunction() - * (cond ? myFunc : mySecondFunc)() - * myFunction()() - * @example for incorrect usage - * 4() - * () - * ^---------- '4' or 'type void' are not functions - */ - Base* callee; - /// @brief A list of arguments passed to the function - std::vector arguments; - /** - * @brief A variable used to fix a special occation for - * variable mutability. Uninitialized variables should - * allow an initial assigment (but just once). - * @example - * let a: i32; - * a = 10 // ok - * a = 20 // error - * @note It's a special variable for the OpType::EQ operator. - */ - bool isInitialization = false; - - public: - using AcceptorExtend::AcceptorExtend; - - FunctionCall(Base* callee, std::vector arguments = {}) - : callee(callee), arguments(arguments), AcceptorExtend() {}; - - /// @return Get function's callee - auto getCallee() { return callee; } - /// @return Call instruction arguments - auto& getArguments() { return arguments; } - /// @brief Set a new call expression to this call - void setCallee(Base* c) { callee = c; } - - public: - /// @return string representation of a function call arguments - static std::string getArgumentsAsString(const std::vector args); - - ACCEPT() -}; - -/** - * @brief It represents the "new" operator to create a new - * instance of a class. - * @note What it actually does it just calls the new operator - * as a static function and creates a new allocation of that - * type. - * @example - * _c = alloca [type] - * c = [type]::[new operator](_c) - */ -struct NewInstance : public AcceptorExtend { - private: - /// @brief Call representation containing the arguments - FunctionCall* call; - /// @brief Type that's being initialized - TypeRef* type; - - public: - using AcceptorExtend::AcceptorExtend; - - NewInstance(FunctionCall* call, TypeRef* ty) : type(ty), call(call) {}; - NewInstance(DBGSourceInfo* dbg, std::vector args, TypeRef* ty); - - /// @return Get the call value from the operator - auto getCall() { return call; } - /// @brief Get the type trying to be initialized - auto getType() { return type; } - - ACCEPT() -}; - -/** - * Representation of an identifier. An identifier can be used to get - * the value of a variable, reference a class/function, etc... - */ -struct Identifier : public AcceptorExtend { - // The value used as identifier - std::string identifier; - - public: - // using AcceptorExtend::AcceptorExtend; - - Identifier(const std::string& identifier) : identifier(identifier), AcceptorExtend() {}; - - /// @return Get respective identifier - /// Syntax::Expression::Identifierlue - auto getIdentifier() { return identifier; } - virtual std::string getNiceName() const { - if (services::OperatorService::isOperator(identifier)) { - auto i = services::OperatorService::operatorID(identifier); - return services::OperatorService::operatorName(i); - } - return identifier; - } - - virtual ~Identifier() noexcept = default; - ACCEPT() -}; - -/** - * @brief pseudo string variables are substituted at compile time. - * These can be used as "information" variables that can be very - * beneficial for the user. - */ -struct PseudoVariable : public AcceptorExtend { - std::string identifier; - /// @brief Arguments passed to the variable - std::vector args; - /// @brief Wether or not the variable has arguments - bool hasArguments = false; - - public: - PseudoVariable(std::string identifier); - /// @return Get the pseudo variable identifier without the - /// prefix - auto getIdentifier() { return identifier; } - - /// @brief If the variable contains arguments - bool hasArgs() const; - /// @return Get the arguments passed to the variable - std::vector getArgs() const; - /// @brief Set the arguments passed to the variable - void setArgs(std::vector args); - /// @brief If the variable is used inside a statement - bool asStatement = false; - - ACCEPT() -}; - -/** - * Representation of an index node. Index nodes can either be - * static or not. It's decided by it's syntax. Using '.' means it's - * not static but using '::' does imply that it's static. - */ -struct Index : public AcceptorExtend { - /// Base value from where we are geting the value - Base* base; - /// Identifier node that we are trying to extract. - /// @note Identifier can also have generics! - Identifier* identifier; - - public: - /// @brief Wether the extract is marked as static or not - bool const isStatic = false; - - using AcceptorExtend::AcceptorExtend; - - Index(Base* base, Identifier* identifier, bool isStatic = false) - : base(base), isStatic(isStatic), identifier(identifier), AcceptorExtend() {}; - - /// @return Get respective base value - auto getBase() { return base; } - /// @return Get respective base value - auto getIdentifier() { return identifier; } - /// @brief Set a new identifier to the index - /// @note This shoudn't be used unless you know what you're doing - void unsafeSetidentifier(Identifier* id) { identifier = id; } - - ACCEPT() -}; - -/** - * This is the same as an identifier except that it will contain - * generic - */ -struct GenericIdentifier : public AcceptorExtend { - /// @brief Generics stored into the identifier - std::vector generics; - - public: - using AcceptorExtend::AcceptorExtend; - GenericIdentifier(const std::string& idnt, std::vector generics = {}) - : AcceptorExtend(idnt), generics(generics) {}; - - /// @return generic list set to this identifier - std::vector getGenerics() const; - std::string getNiceName() const override; - - ACCEPT() -}; - -/** - * @struct BinaryOp - * @brief Represents a binary operator expression node. - * @extends AcceptorExtend - */ -struct BinaryOp : public AcceptorExtend { - public: - using OpType = services::OperatorService::OperatorType; - - Base* left; ///< Left node - Base* right; ///< Right node - OpType op_type; ///< The type of operator - bool unary = false; ///< Whether it's a unary operator - - bool isMutableReference = false; ///< If the operator is a mutable reference - - /** - * @brief Determines if the operator is an assignment operator. - * @param p_node The operator expression node. - * @return Whether it's an assignment operator. - */ - static bool is_assignment(OpType opType); - static bool is_assignment(BinaryOp* p_node); - /** - * @brief Determines if the operator is a comparison operator. - * @param p_node The operator expression node. - * @return Whether it's a comparison operator. - */ - static bool is_comp(OpType p_node); - /** - * @brief Converts the operator type to a string. - * @return The string representation of the operator. - */ - std::string to_string() const; - ACCEPT() - - BinaryOp(OpType t) : op_type(t) { - unary = - (op_type == OpType::NOT || op_type == OpType::BIT_NOT || op_type == OpType::UPLUS || - op_type == OpType::UMINUS || op_type == OpType::REFERENCE || op_type == OpType::DEREFERENCE); - }; - ~BinaryOp() noexcept = default; - - public: - /** - * @brief A variable used to fix a special occation for - * variable mutability. Uninitialized variables should - * allow an initial assigment (but just once). - * @example - * let a: i32; - * a = 10 // ok - * a = 20 // error - * @note It's a special variable for the OpType::EQ operator. - */ - bool isInitialization = false; -}; - -}; // namespace Expression - -/** - * A statement (aka a meaningful declarative sentence) - * is used to declare something. This something may be - * a function, class, import, etc. - * - * - https://en.wikipedia.org/wiki/Statement_(logic) - */ -namespace Statement { -struct Base : public AcceptorExtend { }; - -/** - * This is just a wrapper class for all nodes - * that require some sort of visibility. - * - * E.g. some of this nodes can be: - * - modules, functions, classes, ... - */ -struct Privacy { - // The visibility specifies where can the node - // be accessed from. For example, a private function - // inside a class can't be accessed outside from it. - // @warning keep the order the same, always! - enum Status { - PUBLIC = 0, - PRIVATE = 1 - } status = PRIVATE; - - public: - Privacy() { status = PRIVATE; } - - Privacy(Status status); - ~Privacy() noexcept = default; - - /// @return node's status - Status getPrivacy() const; - - /// @brief Set node's privacy - void setPrivacy(Status s); - - /// @return if the item is private or public. - /// @note isPublic and isPrivate are just utility functions to know - /// the item's privacy but they both do essentially the same. - auto isPublic() { return status == PUBLIC; } - auto isPrivate() { return !isPublic(); } - - public: - /// @brief Convert an integer to a Status - /// @param p_status Integer to transform (note: it will be - /// inverted) - /// @return equivalent for Status - static Status fromInt(bool p_status); -}; - -/// @brief A holder for documentation comments. -struct CommentHolder { - /// @brief Documentation comment - Comment* comment = nullptr; - public: - /// @return Get the documentation comment - Comment* getComment() const; - /// @brief Set a new documentation comment - void setComment(Comment* comment); -}; - -/** - * Function definition, check out parseFunction for - * it's respective rules - */ -struct FunctionDef : public AcceptorExtend, - public AcceptorExtend, - public AcceptorExtend>, - public AcceptorExtend { - // Function's identifier - std::string name; - // Arguments available for the functions - std::vector args; - // Function's return type - Expression::TypeRef* retType; - // Whether or not function can take an infinite - // number of arguments - bool variadic = false; - /// If the function is declared as static or not. - bool _static = false; - // Declaration of wether or not the function is declared - // as virtual. - bool _virtual = false; - // Declaration of wether or not the function is declared - // as mutable. - bool _mutable = false; - - /// @brief Context state for the function (it shoudn't be used often) - std::shared_ptr _contextState = nullptr; - - public: - FunctionDef(const std::string name, Privacy::Status prvc = PRIVATE); - - /// @brief Get function's identifier - std::string getName(); - /// @brief Set a function name - void setName(const std::string name); - - /// @return iterator to the first arg - auto argBegin() { return args.begin(); } - /// @return iterator beyond the last arg - auto argEnd() { return args.end(); } - - /// @return Argument list - std::vector getArgs() const; - /// @brief Set a new argument list to the function - void setArgs(std::vector p_args); - - /// @return Return type - Expression::TypeRef* getRetType() const; - /// @brief Set a return type to the function - void setRetType(Expression::TypeRef* p_type); - - /// @return Whether or not the function is marked as variadic - bool isVariadic(); - /// @brief Mark if the function is variadic or not - void setVariadic(bool v = true); - - /// @return of wether or not the function is declared as - /// virtual. - bool isVirtual(); - /// @brief Mark if the function if it's virtual or not - void setVirtual(bool v = true); - - /// @return `true` if the function is declared as static - bool isStatic(); - /// @brief Declare a function static or not. - void setStatic(bool s = true); - - /// @return `true` if the function is declared as mutable - bool isMutable(); - /// @brief Declare a function mutable or not. - void isMutable(bool m); - - /// Check if the function is declared as an extern function - virtual bool isExtern() { return false; } - /// Check if the function is declared as a constructor - virtual bool isConstructor() { return false; } - - /// @brief Copy the function - virtual FunctionDef* copy() { return new FunctionDef(*this); } - - /// @brief Get the context state for the function - std::shared_ptr getContextState() const; - /// @brief Set the context state for the function - void setContextState(std::shared_ptr state); - - // Set an acceptance call - ACCEPT() -}; - -/** - * AST representation for a variable declaration. Variables - * can either be mutable or unmutable. - */ -struct VariableDecl : public AcceptorExtend, - public AcceptorExtend, public AcceptorExtend { - /// @brief Variables's identifier - std::string name; - /// @brief Variable's default value - Expression::Base* value = nullptr; - /// @brief Whether the variable can change or not - bool _mutable = false; - // @brief User defined type - // @example - // let a: f32 = 2 - // ----- converted ir = - // variable - // value: cast "2"(i32) -> f32 - // ----- it can also be written as: - // let a = 2 as f32 - Expression::TypeRef* definedType = nullptr; - /// @brief If the variable is actually a constant expression. - bool isConstant = false; - /// @brief If the variable is external - bool isExtern = false; - - public: - VariableDecl( - const std::string& name, Expression::Base* value = nullptr, bool isMutable = false, bool isConstant = false - ); - - /// @brief Get the identifier assign to the variable - std::string getName() const; - /// @return the value holt by the variable - Expression::Base* getValue(); - /// @return Wether or not the variable is mutable - bool isMutable(); - /// @return The desired type the programmer wants - /// @note It might possibly be nullptr! - Expression::TypeRef* getDefinedType(); - /// @brief declare a defined type for the variable - void setDefinedType(Expression::TypeRef* t); - /// @return true if the variable has been initialied - bool isInitialized(); - /// @brief If the variable is actually declared as a constant - bool isContantDecl(); - /// @brief If the variable is declared as an extern variable - bool isExternDecl(); - /// @brief Set the variable as an extern variable - void setExternDecl(bool e = true); - - // Set an acceptance call - ACCEPT() -}; - -/** - * @struct TypeAlias - * @brief Representation of a type alias declaration inside the AST. - * - * Type aliases can be used to solve a variaety of different - * problems such as to avoid writing long types. - * - * @example - * type HelloWorld = My::Super::Long:Class:Name::With* - */ -struct TypeAlias : public AcceptorExtend, - public AcceptorExtend, - public AcceptorExtend>, - public AcceptorExtend { - /// @brief Name of the alias to be exported as - std::string identifier; - /// @brief The type being refered by the alias - Expression::TypeRef* type; - - public: - explicit TypeAlias(const std::string& identifier, Expression::TypeRef* type) : identifier(identifier), type(type) {}; - - /// @return The name of the alias to be exported as - auto getIdentifier() { return identifier; } - /// @return The type being refered by the alias - auto getType() { return type; } - - // Set a visit handler for the generators - ACCEPT() -}; - -/** - * Class definition. Created at "Parser::parseClass" function - */ -struct DefinedTypeDef : public AcceptorExtend, - public AcceptorExtend, - public AcceptorExtend>, - public AcceptorExtend { - /// @brief Class identifier - std::string name; - /// @brief Defined functions to the class - /// @note Although operators act like functions, - /// they are treated differently. - std::vector functions; - /// @brief Class defined variables - std::vector variables; - /// @brief A list containing all the child types - /// @note It can contain type aliases, classes, structs, etc... but - /// not any other type of statement. - std::vector typeAliases; - /// @brief Class inheritance parent - Expression::TypeRef* extends = nullptr; - /// @brief The defined type's type - enum Type { - CLASS, - STRUCT, - INTERFACE - } type = CLASS; - /// @brief Type implementations for interfaces - std::vector impls; - - public: - DefinedTypeDef( - std::string name, Expression::TypeRef* extends = nullptr, Privacy::Status prvc = PRIVATE, Type type = CLASS - ); - - /// @brief Get class name - std::string getName() const; - /// @brief Set a new class name - /// @note This shoudn't be used unless you know what you're doing - void unsafeSetName(const std::string& name); - - /// Add a function to the function list - void addFunction(FunctionDef* fnDef); - /// Declare a variable and store it to this class - void addVariable(VariableDecl* var); - - /// Iterator utilities - using FunctionIterator = std::vector::iterator; - using VariableIterator = std::vector::iterator; - - /// @return A full list of declared functions - std::vector& getFunctions(); - /// @return All variables defined on the current class - std::vector& getVariables(); - - FunctionIterator funcStart(); - FunctionIterator funcEnd(); - - VariableIterator varStart(); - VariableIterator varEnd(); - - /// @return A full list of declared type aliases - std::vector& getChildTypes(); - /// @brief Add a type alias to the class - void addChildType(Base* alias); - - /// @return If the class is a struct or not - virtual bool isStruct(); - /// @return If the class is an interface or not - virtual bool isInterface(); - - /// @brief Set class' implementations - void setImpls(std::vector impls); - /// @return Get class' implementations - std::vector getImpls() const; - - /// @return the parent class being inherited on - Expression::TypeRef* getParent() const; - - // Set an acceptance call - ACCEPT() - public: - /// @brief If the class has a constructor - bool hasConstructor = false; -}; - -/** - * @brief Representation of an enum type in the AST. - */ -struct EnumTypeDef : public AcceptorExtend, - public AcceptorExtend, - public AcceptorExtend>, - public AcceptorExtend { - /// @brief Enum identifier - std::string name; - /// @brief Defined enum fields - std::vector>> fields; - /// @brief Enum's extended type method's - std::vector methods; - /// @brief Enum's extended implementations - std::vector impls; - public: - EnumTypeDef(std::string name, Privacy::Status prvc = PRIVATE); - - /// @brief Get enum name - std::string getName() const; - - /// Add a field to the field list - void addField(std::pair> field); - - /// Iterator utilities - using FieldIterator = std::vector>>::iterator; - - /// @return A full list of declared fields - std::vector>>& getFields(); - - FieldIterator fieldStart(); - FieldIterator fieldEnd(); - - /// @return A full list of declared methods - std::vector& getMethods(); - /// @brief Add a method to the enum - /// Yes, enums can have methods! - /// Methods can be defined by using `class extends` to - /// extend the enum. - void addMethod(FunctionDef* method); - /// @brief Add an implementation to the enum - void addImpl(Expression::TypeRef* impl); - /// @return Get enum's implementations - std::vector getImpls() const; - - // Set an acceptance call - ACCEPT() -}; - -/** - * @brief Representation of a switch statement in the AST. - */ -struct Switch : public AcceptorExtend { - public: - struct CaseBlock { - /// @brief The expression to compare - std::pair expression = {nullptr, ""}; - /// @brief Arguments passed to the expression - std::vector args; - /// @brief If the case is a default case - bool isDefault = false; - /// @brief If the argument is variadic - bool isVariadic = false; - /// @brief The block to execute if the case is met - Block* block; - - std::string expressionAsString() const { - if (expression.first == nullptr) { - return expression.second; - } - assert(expression.first != nullptr); - throw std::runtime_error("Not implemented"); - } - Expression::Base* getExpression() const { - assert(expression.first != nullptr); - return expression.first; - } - }; - private: - /// @brief The expression to compare - Expression::Base* expr; - /// @brief The cases to compare - std::vector cases; - /// @brief If it's a c-like switch - bool isCStyle = false; - public: - Switch(Expression::Base* expr, std::vector cases, bool isCStyle = false) - : expr(expr), cases(cases), isCStyle(isCStyle) {}; - - /// @return The expression to compare - auto getExpr() { return expr; } - /// @return The cases to compare - auto getCases() { return cases; } - /// @return If it's a c-like switch - auto isCStyleSwitch() { return isCStyle; } - - // Set a visit handler for the generators - ACCEPT() -}; - -/** - * @brief Representation of a Raise statement in the AST. - * This is used to throw an exception. - * @example - * raise new Exception("Something went wrong") - */ -struct Raise : public AcceptorExtend { - /// @brief Expression to be raised - Expression::Base* expr; - - public: - Raise(Expression::Base* expr) : expr(expr) {}; - - /// @return Get the expression to be raised - auto getExpr() { return expr; } - - // Set an acceptance call - ACCEPT() -}; - -/** - * @brief Representation of a conditional block or "if statement" in - * the AST. This contains instructions that are executed inside of - * it if a condition is met, if not, the "else" statement is - * executed if it exists. - */ -struct Conditional : public AcceptorExtend { - // Instructions stored inside a block - Block* insts; - // the expression to be evaluated - Expression::Base* cond; - // The "else" statement block if the condition is false - Block* elseBlock; - - public: - explicit Conditional(Expression::Base* cond, Block* insts, Block* elseBlock = nullptr) - : cond(cond), insts(insts), elseBlock(elseBlock) {}; - - /// @return body block instructions to execute - // if the condition is met - auto getBlock() { return insts; } - /// @return the expression to be evaluated - auto getCondition() { return cond; } - /// @return Get "else" statement - auto getElse() { return elseBlock; } - - // Set a visit handler for the generators - ACCEPT() -}; - -/** - * Representation of a loop flow. This is used to - * break or continue a loop. - */ -struct LoopFlow : public AcceptorExtend { - public: - /// @brief Loop flow type (break or continue) - enum FlowType { - Break, - Continue - } type; - - using AcceptorExtend::AcceptorExtend; - - LoopFlow(FlowType type) : type(type) {}; - - /// @return Get the loop flow type - auto getFlowType() { return type; } - - ACCEPT() -}; - -/** - * @brief Representation of a try-catch block in the AST. - */ -struct TryCatch : public AcceptorExtend { - public: - struct CatchBlock { - /// @brief The exception type to catch - Expression::TypeRef* exceptionType; - /// @brief The variable to store the exception - std::string exceptionVar; - /// @brief The block to execute if the exception is caught - Block* block; - - public: - CatchBlock(Expression::TypeRef* exceptionType, std::string exceptionVar, Block* block) - : exceptionType(exceptionType), exceptionVar(exceptionVar), block(block) {}; - - /// @return The exception type to catch - auto getExceptionType() { return exceptionType; } - /// @return The variable to store the exception - auto getExceptionVar() { return exceptionVar; } - /// @return The block to execute if the exception is caught - auto getBlock() { return block; } - }; - - private: - /// @brief The block to execute - Block* tryBlock; - /// @brief The block to execute if an exception is caught - std::vector catchBlocks; - - public: - TryCatch(Block* tryBlock, std::vector catchBlocks) : tryBlock(tryBlock), catchBlocks(catchBlocks) {}; - - /// @return The block to execute - auto getTryBlock() { return tryBlock; } - /// @return The block to execute if an exception is caught - auto getCatchBlocks() { return catchBlocks; } - - // Set a visit handler for the generators - ACCEPT() -}; - -/** - * @brief Representation of a for loop in the AST. - */ -struct ForLoop : public AcceptorExtend { - /// @brief The variable to iterate - std::string var; - /// @brief The expression to iterate - Expression::Base* expr; - /// @brief The block to execute - Block* block; - - public: - ForLoop(std::string var, Expression::Base* expr, Block* block) : var(var), expr(expr), block(block) {}; - - /// @return The variable to iterate - auto getVar() { return var; } - /// @return The expression to iterate - auto getExpr() { return expr; } - /// @return The block to execute - auto getBlock() { return block; } - - // Set a visit handler for the generators - ACCEPT() -}; - -/** - * @brief AST representation of a conditional statement that contains a - * `constexpr` expression as it's condition. - */ -struct ConditionalConstExpr : public AcceptorExtend { - // Instructions stored inside a block - Block* insts; - // The "else" statement block if the condition is false - Block* elseBlock = nullptr; - - public: - explicit ConditionalConstExpr(Block* insts, Block* elseBlock = nullptr) - : insts(insts), elseBlock(elseBlock) {}; - - /// @return body block instructions to execute - // if the condition is met - auto getBlock() { return insts; } - /// @return Get "else" statement - auto getElse() { return elseBlock; } - // Set a visit handler for the generators - ACCEPT() -}; - -/** - * A struct representing a while loop in a program. - * It inherits from the AcceptorExtend class, which allows for - * pattern matching and traversal of the while loop. - * It also inherits from the Base class, which provides - * a common interface for all nodes in the program's AST. - */ -struct WhileLoop : public AcceptorExtend { - // Instructions stored inside a block - Block* insts = nullptr; - // the expression to be evaluated before each iteration - Expression::Base* cond = nullptr; - /** - * It has the same characteristics as a while loop except that - * it has some differentiations. As the name suggests, a - * do-while executes the instructions block before doing the - * check. For example, we can use it the following (PSEUDOCODE): - * this will execute "hello" 5 times. - * ``` - * 1 | A = 0 - * 2 | DO { - * 3 | print("hello") - * 4 | A += 1 - * 5 | } WHILE (A < 4) - * ``` - */ - bool doWhile = false; - // For loop condition (if it's a for loop) - Node* forCond = nullptr; - - public: - explicit WhileLoop(Expression::Base* cond, Block* insts, bool isDoWhile = false) - : cond(cond), insts(insts), doWhile(isDoWhile) {}; - explicit WhileLoop(Expression::Base* cond, Block* insts, Node* forCond) - : cond(cond), insts(insts), forCond(forCond) {}; - - /// @return body block instructions to execute - // each iterator if the condition is truth - auto getBlock() const { return insts; } - /// @return the expression to be evaluated each iteration - auto getCondition() const { return cond; } - /// @return If the condition should be checked before or after - /// each iteration - auto isDoWhile() const { return doWhile; } - /// @return The for loop condition - auto getForCond() const { return forCond; } - - // Set a visit handler for the generators - ACCEPT() -}; - -/** - * Import statement. Imports functions, classes and symbols from - * other files / modules. - */ -struct ImportStmt : public AcceptorExtend { - /// @brief Represents the path trying to be accessed. - /// It gets translated from the source code, snowball-like - /// syntax into a vector of strings. - /// @example of different import statements and how they are - /// represented. - /// | use std::io | {"io"} - /// | use hello::myPath::secondPath | {"myPath", - /// "secondPath"} | use hello::myPath:..:helloAgain | - /// {"myPath", "..", "helloAgain"} - /// @note (1): Last path will be checked with all kind of - /// different supported - /// extensions (sn, so, ...) and it's @c exportSymbol will be - /// the name of the last path. - /// @note (2): The user can manually specify the path extension - /// by doing the following: - /// | use myModule::path:path2:myFile(so)::{ myFunc } - std::vector path; - /// @brief place where searching the path from. This can be used - /// so we can decide from what package we need to import this. - /// @example - /// | use std::io | package = "std" - /// @note If the package name is `$` that means that it's being - /// extracted - /// from the current module. - std::string package; - /// @brief How the declaration is being exported into the - /// current file. - std::string exportSymbol; - /// @brief Variables to be imported from the file - /// first: variable name - /// second: variable alias - std::vector> variables; - - public: - ImportStmt(const std::vector path = {}, const std::string package = "pkg", - std::vector> variables = {}, std::string exportSymbol = ""); - - public: - /// @brief get the package name where it's imported from - std::string getPackage() const; - /// @return The defined path for the package - std::vector getPath() const; - /// @brief Get the identifier the user wants it imported as - /// @c exportSymbol - std::string getExportSymbol() const; - /// @brief Get the variables to be imported from the file - std::vector> getVariables() const; - - // Set an acceptance call - ACCEPT() -}; - -/** - * @class Namespace. AST representation of a namespace declaration. - * Namespaces are used to group different symbols together. - * This can be used to avoid name collisions. - * @example - * namespace MyNamespace { - * // ... - * } - * @note Namespaces can be nested. - * @note Namespaces can be used to access symbols from other - * namespaces. - * @example - * namespace MyNamespace { - * namespace MySecondNamespace { - * // ... - * } - * } - * MyNamespace::MySecondNamespace::myFunction() - */ -struct Namespace : public AcceptorExtend, public AcceptorExtend { - /// @brief Name of the namespace - std::string name; - /// @brief Body of the namespace - std::vector body; - - public: - Namespace(std::string name, std::vector body); - - public: - /// @return Name of the namespace - std::string getName() const; - /// @return Body of the namespace - std::vector getBody() const; - - // Set an acceptance call - ACCEPT() -}; - -/** - * In snowball, a return statement ends the execution of a - * function, and returns control to the calling function. - * - * @note return type must match function's return type - */ -struct Return : public AcceptorExtend { - // Function's return type - Expression::Base* value = nullptr; - - public: - Return(Expression::Base* value); - - /// @return the value holt by the variable - Expression::Base* getValue() const; - - // Set an acceptance call - ACCEPT() -}; - -/** - * This represents a function declaration - * that has been declared as external. - * - * In snowball, external functions are the ones - * who's names isn't mangled and body is not defined. - * - * There can be different type of extern types. E.g. - * you can have; "C" or "System". - */ -struct ExternFnDef : public AcceptorExtend { - // External function for the function. - std::string externalName; - - public: - using AcceptorExtend::AcceptorExtend; - - template - ExternFnDef(std::string externalName, Args& ... args) - : externalName(externalName), AcceptorExtend(std::forward(args)...) {}; - - // Whether the function is external, it is true in this case - virtual bool isExtern() override { return true; } - /// @return Get external function's name. - std::string getExternalName() { return externalName; } - - // Copy the function - virtual ExternFnDef* copy() override { return new ExternFnDef(*this); } -}; - -/** - * A bodied function is a function with a declared block. - * This block contains the instructions that will be - * executed once this function is called. - */ -struct BodiedFunction : public AcceptorExtend { - // Function's block. This block contains all the intructions - // a function executes when it's called. - Block* block; - - public: - using AcceptorExtend::AcceptorExtend; - - template - BodiedFunction(Block* block, Args& ... args) : block(block), AcceptorExtend(std::forward(args)...) {}; - - /// @return Get function's body declaration. - Block* getBody() { return block; } - - // Copy the function - virtual BodiedFunction* copy() override { return new BodiedFunction(*this); } -}; - -/** - * @brief Representation of a class constructor. It's a special function that - * gets called when a new instance of a class is created. - * @example - * class A { - * A() { ... } - * } - */ -struct ConstructorDef : public AcceptorExtend { - /** - * @brief Arguments used to initialize the parent class. - * @example - * class A { - * A() { ... } - * } - * class B : A { - * B() super(...) { ... } - * } - */ - std::vector superArgs; - /** - * @brief Arguments used to initialize the class. - * @example - * class A { - * let x: i32; - * A() : x(4) { ... } - * } - * @note This can be useful to store values to unmutable variables. - */ - std::map initArgs; - /// @brief Wether or not the constructor has super arguments - bool _hasSuperArgs = false; - - public: - using AcceptorExtend::AcceptorExtend; - - template - ConstructorDef(bool hasSuperArgs, Args& ... args) : AcceptorExtend(args...), _hasSuperArgs(hasSuperArgs) {}; - - /// @brief Wether or not the constructor has super arguments - bool hasSuperArgs() const { return _hasSuperArgs; }; - - /// @brief Set the arguments used to initialize the parent class. - void setSuperArgs(std::vector args); - /// @brief Set the arguments used to initialize the class. - void setInitArgs(std::map args); - /// @return Arguments used to initialize the parent class. - decltype(superArgs) getSuperArgs() const; - /// @return Arguments used to initialize the class. - decltype(initArgs) getInitArgs() const; - /// @return The start of the super arguments - decltype(superArgs)::iterator superArgsBegin(); - /// @return The end of the super arguments - decltype(superArgs)::iterator superArgsEnd(); - /// @return The start of the init arguments - decltype(initArgs)::iterator initArgsBegin(); - /// @return The end of the init arguments - decltype(initArgs)::iterator initArgsEnd(); - - /// @return `true` if the function is declared as a constructor - bool isConstructor() override { return true; } - - // Copy the function - virtual ConstructorDef* copy() override { return new ConstructorDef(*this); } -}; - -/** - * An LLVM defined function is a function with a declared LLVM - * block. This block contains the instructions that will be executed - * once this function is called. - */ -struct LLVMFunction : public AcceptorExtend { - // Function's block. This block contains all the LLVM IR - // intructions a function executes when it's called. - std::string block; - // Types being used inside the function - std::vector llvmTypesUsed; - - public: - using AcceptorExtend::AcceptorExtend; - - template - LLVMFunction(std::string block, std::vector llvmTypesUsed, Args& ... args) - : block(block), llvmTypesUsed(llvmTypesUsed), AcceptorExtend(std::forward(args)...) {}; - - /// @return Get function's body declaration. - auto getBody() { return block; } - /// @return Get function's types used. - auto getTypesUsed() { return llvmTypesUsed; } - - // Copy the function - virtual LLVMFunction* copy() override { return new LLVMFunction(*this); } -}; - -}; // namespace Statement - -namespace Expression { -/** - * A struct representing a Lambda Function, which is derived from - * the AcceptorExtend class and inherits the BodiedFunction class. - * It provides a way to define an anonymous function that can be - * passed as an argument to another function or assigned to a - * variable. - * - * The LambdaFunction struct inherits the functionality of the - * AcceptorExtend and BodiedFunction classes, allowing it to be used - * as an acceptor of visitors and to have a body that can be - * evaluated when called. - */ -struct LambdaFunction : public AcceptorExtend { - public: - using AcceptorExtend::AcceptorExtend; - - /* Function used inside the lambda since a lambda struct is - sor of used as an "Interface" for expressions */ - Statement::BodiedFunction* func = nullptr; - - /// @return the function assigned to this lambda interface - auto getFunc() { return func; } - - LambdaFunction(Statement::BodiedFunction* func) : AcceptorExtend(), func(func) {}; - - ACCEPT() -}; -} // namespace Expression - -/** - * @brief Representation of a macro declaration in the AST. - * Macros are used to generate code at compile time. - * @example - * macro myMacro(a: i32, b: i32) { - * return a + b - * } - * @note Macros can be used as statements or expressions. - */ -struct Macro : public AcceptorExtend, public AcceptorExtend { - public: - enum ArguementType { - STATEMENT, - EXPRESSION, - CONSTANT, - TYPE, - - CONSTANT_CHAR, - CONSTANT_NUMBER, - CONSTANT_STRING, - }; - - private: - std::string name; - std::vector> args; - Block* body; - - bool isStatement = false; - - public: - Macro(std::string name, - std::vector> args, - Block* body, - bool isStatement = false) - : name(name), args(args), body(body), isStatement(isStatement) {}; - - /// @return Get macro's name - std::string getName() const { return name; } - /// @return Get macro's arguments - auto getArgs() const { return args; } - /// @return Get macro's body - Block* getBody() const { return body; } - /// @return If the macro is a statement or not - bool isMacroStatement() const { return isStatement; } - /// @brief Convert an arguement type to a string - /// @param type Type to convert - /// @return String representation of the type - static std::string arguementTypeToString(ArguementType type); - /// @brief Convert an arguement type to a syntax equivalent - /// @param type Type to convert - /// @return String representation of the type - static std::string arguementTypeToSyntax(ArguementType type); - // Set an acceptance call - ACCEPT() -}; - -/** - * @brief Utility function to create a new node - * @tparam ...Args arguments for the node - * @tparam Inst Node type to be initialized - * @return Resultant node - */ -template -Inst* N(Args&&... args) { - // Our template parameter must - // be inherited from Node - static_assert(std::is_base_of::value, "Inst must inherit from Node"); - auto n = new Inst(std::forward(args)...); - return n; -} - -/** - * @brief Utility function to create a type reference - * @tparam ...Args arguments for the type - * @return New type reference - */ -template -Expression::TypeRef* TR(Args&&... args) { - auto n = new Expression::TypeRef(std::forward(args)...); - return n; -} - -using PrivacyStatus = Statement::Privacy::Status; ///< Privacy status enum - -}; // namespace Syntax -}; // namespace snowball - -#undef ACCEPT -#endif // __SNOWBALL_AST_NODES_H_ diff --git a/src/ast/syntax/stmts.cc b/src/ast/syntax/stmts.cc deleted file mode 100644 index 9badbd26..00000000 --- a/src/ast/syntax/stmts.cc +++ /dev/null @@ -1,111 +0,0 @@ - -#include "common.h" -#include "nodes.h" - -#include -#include -#include - -namespace snowball { -namespace Syntax { -void Block::append(Node* stmt) { stmts.push_back(stmt); } -namespace Statement { -// Separated namespace in order to use -// Privacy::Status without name conflicts -using Status = Privacy::Status; -Privacy::Privacy(Status status) : status(status) { } -void Privacy::setPrivacy(Status s) { status = s; } -Status Privacy::getPrivacy() const { return status; } -Status Privacy::fromInt(bool p_status) { return static_cast(!p_status); } -} // namespace Statement -namespace Statement { -FunctionDef::FunctionDef(std::string name, Privacy::Status prvc) - : AcceptorExtend(prvc), name(name) { } -std::vector FunctionDef::getArgs() const { return args; } -void FunctionDef::setArgs(std::vector p_args) { args = p_args; } -Expression::TypeRef* FunctionDef::getRetType() const { return retType; }; -void FunctionDef::setRetType(Expression::TypeRef* p_type) { retType = p_type; } -bool FunctionDef::isVirtual() { return _virtual; } -void FunctionDef::setVirtual(bool v) { _virtual = v; } -std::string FunctionDef::getName() { return name; } -void FunctionDef::setName(const std::string name) { this->name = name; } -bool FunctionDef::isVariadic() { return variadic; } -void FunctionDef::setVariadic(bool v) { variadic = v; } -bool FunctionDef::isStatic() { return _static; } -void FunctionDef::setStatic(bool s) { _static = s; } -bool FunctionDef::isMutable() { return _mutable; } -void FunctionDef::isMutable(bool m) { _mutable = m; } -void ConstructorDef::setSuperArgs(std::vector args) { superArgs = args; } -void ConstructorDef::setInitArgs(std::map list) { initArgs = list; } -std::map ConstructorDef::getInitArgs() const { return initArgs; } -std::vector ConstructorDef::getSuperArgs() const { return superArgs; } -std::vector::iterator ConstructorDef::superArgsBegin() { return superArgs.begin(); } -std::vector::iterator ConstructorDef::superArgsEnd() { return superArgs.end(); } -std::shared_ptr FunctionDef::getContextState() const { return _contextState; } -void FunctionDef::setContextState(std::shared_ptr state) { _contextState = state; } -std::map::iterator ConstructorDef::initArgsBegin() { - return initArgs.begin(); -} -EnumTypeDef::EnumTypeDef(std::string name, Privacy::Status prvc) : AcceptorExtend(prvc), - name(name) { } -std::string EnumTypeDef::getName() const { return name; } -void EnumTypeDef::addField(std::pair> field) { fields.push_back(field); } -std::vector>>& EnumTypeDef::getFields() { return fields; } -EnumTypeDef::FieldIterator EnumTypeDef::fieldStart() { return fields.begin(); } -EnumTypeDef::FieldIterator EnumTypeDef::fieldEnd() { return fields.end(); } -std::map::iterator ConstructorDef::initArgsEnd() { return initArgs.end(); } -Namespace::Namespace(std::string name, std::vector body) : body(body), name(name) { } -std::string Namespace::getName() const { return name; } -std::vector Namespace::getBody() const { return body; } -ImportStmt::ImportStmt(const std::vector path, const std::string package, - std::vector> variables, std::string exportSymbol) - : path(path), package(package), variables(variables), exportSymbol(exportSymbol) { } -std::vector> ImportStmt::getVariables() const { return variables; } -VariableDecl::VariableDecl(const std::string& name, Expression::Base* value, bool isMutable, bool isConstant) - : name(name), value(value), _mutable(isMutable), isConstant(isConstant) {}; -bool VariableDecl::isInitialized() { return value != nullptr; } -bool VariableDecl::isContantDecl() { return isConstant; } -std::string VariableDecl::getName() const { return name; } -Expression::Base* VariableDecl::getValue() { return value; } -bool VariableDecl::isMutable() { return _mutable; } -bool VariableDecl::isExternDecl() { return isExtern; } -void VariableDecl::setExternDecl(bool e) { isExtern = e; } -Expression::TypeRef* VariableDecl::getDefinedType() { return definedType; } -void VariableDecl::setDefinedType(Expression::TypeRef* t) { definedType = t; } -Return::Return(Expression::Base* value) : value(value) {}; -Expression::Base* Return::getValue() const { return value; } -DefinedTypeDef::DefinedTypeDef( - std::string name, Expression::TypeRef* extends, Privacy::Status prvc, DefinedTypeDef::Type type -) - : name(name), extends(extends), AcceptorExtend(prvc), type(type) { } -void DefinedTypeDef::addFunction(FunctionDef* fnDef) { functions.push_back(fnDef); } -void DefinedTypeDef::addVariable(VariableDecl* var) { variables.push_back(var); } -void DefinedTypeDef::unsafeSetName(const std::string& name) { this->name = name; } -bool DefinedTypeDef::isStruct() { return type == DefinedTypeDef::STRUCT; } -// bool DefinedTypeDef::isClass() { return type == DefinedTypeDef::CLASS; } -bool DefinedTypeDef::isInterface() { return type == DefinedTypeDef::INTERFACE; } -std::vector& DefinedTypeDef::getChildTypes() { return typeAliases; } -void DefinedTypeDef::addChildType(Base* alias) { typeAliases.push_back(alias); } -void DefinedTypeDef::setImpls(std::vector impls) { this->impls = impls; } -std::vector DefinedTypeDef::getImpls() const { return impls; } -Expression::TypeRef* DefinedTypeDef::getParent() const { return extends; } -std::string DefinedTypeDef::getName() const { return name; } -std::vector& DefinedTypeDef::getFunctions() { return functions; } -std::vector& DefinedTypeDef::getVariables() { return variables; } -DefinedTypeDef::FunctionIterator DefinedTypeDef::funcStart() { return functions.begin(); } -DefinedTypeDef::FunctionIterator DefinedTypeDef::funcEnd() { return functions.end(); } -DefinedTypeDef::VariableIterator DefinedTypeDef::varStart() { return variables.begin(); } -DefinedTypeDef::VariableIterator DefinedTypeDef::varEnd() { return variables.end(); } -std::string ImportStmt::getPackage() const { return package; } -std::vector ImportStmt::getPath() const { return path; } -std::string ImportStmt::getExportSymbol() const { return exportSymbol; } -Comment* CommentHolder::getComment() const { return comment; } -void CommentHolder::setComment(Comment* comment) { this->comment = comment; } -std::vector& EnumTypeDef::getMethods() { return methods; } -void EnumTypeDef::addMethod(FunctionDef* method) { methods.push_back(method); } -void EnumTypeDef::addImpl(Expression::TypeRef* impl) { impls.push_back(impl); } -std::vector EnumTypeDef::getImpls() const { return impls; } - -} // namespace Statement -} // namespace Syntax -} // namespace snowball diff --git a/src/ast/types/BaseType.cc b/src/ast/types/BaseType.cc deleted file mode 100644 index 05785544..00000000 --- a/src/ast/types/BaseType.cc +++ /dev/null @@ -1,36 +0,0 @@ -#include "BaseType.h" -#include "../../common.h" -#include "../../constants.h" -#include "../../ir/values/Func.h" -#include "../../utils/utils.h" -#include "../syntax/common.h" -#include "../syntax/nodes.h" -#include "Type.h" - -#include -#include -#include -#include - -namespace snowball { -namespace types { - -BaseType::BaseType(Kind t, std::string name) : Type(t, name) { } -std::shared_ptr BaseType::getModule() const { return module; } -std::string BaseType::getUUID() const { return uuid; } -void BaseType::unsafeSetUUID(std::string uuid) { this->uuid = uuid; } -void BaseType::unsafeSetModule(std::shared_ptr m) { module = m; } -void BaseType::setDefaultGenerics(std::vector generics) { defaultGenerics = generics; } -void BaseType::setDefaultGenericStart(std::size_t start) { defaultGenericStart = start; } -std::vector BaseType::getDefaultGenerics() const { return defaultGenerics; } -std::size_t BaseType::getDefaultGenericStart() const { return defaultGenericStart; } -int BaseType::getVtableSize() { return classVtable.size(); } -void BaseType::unsafeOverrideVtable(std::vector> vtable) { classVtable = vtable; } -int BaseType::addVtableItem(std::shared_ptr f) { - classVtable.push_back(f); - return getVtableSize() - 1; -} -std::vector>& BaseType::getVTable() { return classVtable; } - -} // namespace types -} // namespace snowball diff --git a/src/ast/types/BaseType.h b/src/ast/types/BaseType.h deleted file mode 100644 index 7a8a42ec..00000000 --- a/src/ast/types/BaseType.h +++ /dev/null @@ -1,88 +0,0 @@ - -#include "../../ast/syntax/common.h" -#include "../../ast/syntax/nodes.h" -#include "../../common.h" -#include "../../ir/id.h" -#include "../../ir/module/Module.h" -#include "../../sourceInfo/DBGSourceInfo.h" -#include "Type.h" - -#include -#include - -#ifndef __SNOWBALL_AST_BASE_TYPE_H_ -#define __SNOWBALL_AST_BASE_TYPE_H_ - -namespace snowball { - -namespace Syntax { -namespace Expression { -struct TypeRef; -} -}; // namespace Syntax - -namespace types { - -class BaseType : public Type, - public DBGObject, - public Syntax::Statement::Privacy, - public Syntax::Statement::GenericContainer, - public ir::IdMixin { - protected: - /// @brief Definition of where in the stack this class is stored - /// @example [module name].MyClass:2 - std::string uuid; - /// @brief A module where the type is defined. - std::shared_ptr module; - - /// @brief A list of default generic types. - std::vector defaultGenerics; - /// @brief The start of the default generic types. - std::size_t defaultGenericStart = 0; - /// @brief VTable holding all it's functions - std::vector> classVtable; - - public: - BaseType(Kind kind, const std::string name); - BaseType(const BaseType& other) = default; - - /// @brief Get the module where the type is defined. - std::shared_ptr getModule() const; - /// @brief Get the UUID of the type. - std::string getUUID() const; - - /// @brief Set the module where the type is defined. - void unsafeSetModule(std::shared_ptr m); - /// @brief Set the UUID of the type. - void unsafeSetUUID(const std::string uuid); - - /// @return The size of the class virtual table - int getVtableSize(); - /// @brief Increase the size of the virtual table - int addVtableItem(std::shared_ptr f); - /// @return a vector containing all the functions in a vtable - std::vector>& getVTable(); - /// @brief It overrides the virtual table - void unsafeOverrideVtable(std::vector> vtable); - - virtual std::int64_t sizeOf() const override { assert(false); } - virtual std::int64_t alignmentOf() const override { assert(false); } - - void setDefaultGenerics(std::vector generics); - void setDefaultGenericStart(std::size_t start); - - std::vector getDefaultGenerics() const; - std::size_t getDefaultGenericStart() const; - - /// @brief Whether or not the type has a vtable - bool hasVtable = false; - - SNOWBALL_TYPE_COPIABLE(BaseType) - - virtual ~BaseType() noexcept = default; -}; - -}; // namespace types -}; // namespace snowball - -#endif // __SNOWBALL_AST_BASE_TYPE_H_ diff --git a/src/ast/types/DefinedType.cc b/src/ast/types/DefinedType.cc deleted file mode 100644 index d2789a74..00000000 --- a/src/ast/types/DefinedType.cc +++ /dev/null @@ -1,157 +0,0 @@ - -#include "DefinedType.h" - -#include "../../common.h" -#include "../../constants.h" -#include "../../ir/values/Func.h" -#include "../../utils/utils.h" -#include "../syntax/common.h" -#include "Type.h" - -#include -#include -#include -#include - -namespace snowball { -namespace types { - -DefinedType::DefinedType( - const std::string& name, - const std::string uuid, - std::shared_ptr module, - Syntax::Statement::DefinedTypeDef* ast, - std::vector fields, - std::vector> staticFields, - DefinedType* parent, - std::vector generics, - bool isStruct -) - : AcceptorExtend(Kind::CLASS, name), parent(parent), ast(ast), fields(fields), _struct(isStruct), - staticFields(staticFields) { - setGenerics(generics); - setPrivacy(PRIVATE); - unsafeSetUUID(uuid); - unsafeSetModule(module); - this->_mutable = true; // Structs are always mutable -} -DefinedType::ClassField::ClassField( - const std::string& name, Type* type, Privacy privacy, Syntax::Expression::Base* initializedValue, bool isMutable -) - : name(name) - , type(type) - , Syntax::Statement::Privacy(privacy) - , initializedValue(initializedValue) - , isMutable(isMutable) { } -Syntax::Statement::DefinedTypeDef* DefinedType::getAST() const { return ast; } -void DefinedType::addField(ClassField* f) { fields.emplace_back(f); } -bool DefinedType::is(DefinedType* ty) const { - auto otherArgs = ty->getGenerics(); - bool genericSizeEqual = otherArgs.size() == generics.size(); - bool argumentsEqual = genericSizeEqual ? std::all_of( - otherArgs.begin(), - otherArgs.end(), - [&, idx = 0](Type * i) mutable { - idx++; - return generics.at(idx - 1)->is(i); - } - ) : - false; - return (ty->getUUID() == uuid) && argumentsEqual; -} - -void DefinedType::setMutable(bool m) { - /*noop*/ -} - - -std::string DefinedType::getPrettyName() const { - auto base = module->isMain() ? "" : module->getName() + "::"; - auto n = base + getName(); - std::string genericString; // Start args tag - if (generics.size() > 0) { - genericString = "<"; - for (auto g : generics) { - genericString += g->getPrettyName(); - if (g != generics.back()) genericString += ", "; - } - genericString += ">"; - } - auto res = n + genericString; - if (getName() == _SNOWBALL_CONST_PTR) { - res = "(*const " + generics.at(0)->getName() + ")"; - } else if (getName() == _SNOWBALL_MUT_PTR) { - res = "(*mut " + generics.at(0)->getName() + ")"; - } - return res; -} - -std::string DefinedType::getMangledName() const { - auto base = module->getUniqueName(); - auto _tyID = static_cast(getId()); - std::stringstream sstm; - sstm << (utils::startsWith(base, _SN_MANGLE_PREFIX) ? base : _SN_MANGLE_PREFIX) << "&" << name.size() << name << "Cv" - << _tyID; - auto prefix = sstm.str(); // disambiguator - std::string mangledArgs; // Start args tag - if (generics.size() > 0) { - mangledArgs = "ClsGSt"; - int argCounter = 1; - for (auto g : generics) { - mangledArgs += "A" + std::to_string(argCounter) + g->getMangledName(); - argCounter++; - } - } - std::string mangled = prefix + mangledArgs + "ClsE"; // ClsE = end of class - return mangled; -} - -Syntax::Expression::TypeRef* DefinedType::toRef() { - auto tRef = Syntax::TR(getUUID(), nullptr, this, getUUID()); - std::vector genericRef; - for (auto g : generics) { genericRef.push_back(g->toRef()); } - tRef->setGenerics(genericRef); - return tRef; -} - -bool DefinedType::canCast(Type* ty) const { - if (auto x = utils::cast(ty)) return canCast(x); - return false; -} - -bool DefinedType::canCast(DefinedType* ty) const { - SNOWBALL_MUTABLE_CAST_CHECK - // TODO: test this: - return hasParent() && (ty->is(getParent())); -} - -// - https://en.wikipedia.org/wiki/Data_structure_alignment#Computing_padding -std::int64_t DefinedType::sizeOf() const { - auto address = (std::int64_t) 0; - for (const auto& f : fields) { - auto typeSize = f->type->sizeOf(); - auto typeAlignment = f->type->alignmentOf(); - address += (address - (address % typeAlignment)) % typeAlignment; - address += (typeAlignment - (address % typeAlignment)) % typeAlignment; - address += typeSize; - } - auto alignment = alignmentOf(); - address += (address - (address % alignment)) % alignment; - address += (alignment - (address % alignment)) % alignment; - address += (hasVtable * 8); - if (address == 0) address = 1; // prevent 0-sized types - return address; -} - -std::int64_t DefinedType::alignmentOf() const { - auto maximumAlignment = (std::int64_t) 0; - for (const auto& f : fields) { - auto alignment = f->type->alignmentOf(); - if (alignment > maximumAlignment) maximumAlignment = alignment; - } - if (maximumAlignment == 0) maximumAlignment = 1; // prevent 0-sized types - return maximumAlignment; -} - -}; // namespace types -}; // namespace snowball diff --git a/src/ast/types/DefinedType.h b/src/ast/types/DefinedType.h deleted file mode 100644 index 0b4d376a..00000000 --- a/src/ast/types/DefinedType.h +++ /dev/null @@ -1,159 +0,0 @@ - -#include "../../common.h" -#include "../../constants.h" -#include "../../ir/id.h" -#include "../../ir/module/Module.h" -#include "../../utils/utils.h" -#include "../syntax/common.h" -#include "../syntax/nodes.h" -#include "BaseType.h" -#include "Type.h" - -#include -#include -#include - -#ifndef __SNOWBALL_AST_DEFINED_TYPES_H_ -#define __SNOWBALL_AST_DEFINED_TYPES_H_ - -namespace snowball { -namespace types { - -/** - * @brief Defined types. - * - * These can also be called as classes or objects. This - * type is defined by the programmer. It can contain some extra - * stuff such as generics and it's own defined members. Unlike - * primitive types, in order to use these type and it's member, - * a new initialization of the object is required. - */ -class DefinedType : public AcceptorExtend { - public: - /** - * @brief A class field represents all of the "elements" a - * type has stored into it. - * - * @note The number of items does not affect whether this type - * is eqaul to another type. - */ - struct ClassField : public Syntax::Statement::Privacy, public DBGObject { - explicit ClassField( - const std::string& name, - Type* type, - Privacy privacy = PRIVATE, - Syntax::Expression::Base* initializedValue = nullptr, - bool isMutable = false - ); - const std::string name; - Type* type; - - Syntax::Expression::Base* initializedValue = nullptr; - - bool isMutable = false; - bool initialized = false; - }; - - friend AcceptorExtend; - - private: - /// @brief a list of fields this class has - std::vector fields; - /// @brief a list of static fields this class has - std::vector> staticFields; - /// @brief Parent class where the class in inherited from - DefinedType* parent = nullptr; - /// @brief The ast representation for the type - Syntax::Statement::DefinedTypeDef* ast = nullptr; - /// @brief Whether or not the type is a struct - bool _struct = false; - - public: - DefinedType( - const std::string& name, - const std::string uuid, - std::shared_ptr module, - Syntax::Statement::DefinedTypeDef* ast = nullptr, - std::vector fields = {}, - std::vector> staticFields = {}, - DefinedType* parent = nullptr, - std::vector generics = {}, - bool isStruct = false - ); - DefinedType(const DefinedType&) = default; - DefinedType& operator=(DefinedType const&) = delete; - /** - * @param other another type to check. - * - * @note Class types will only be checked - * if the @param other is also a defined type. - * - * For other types such as: function types and - * primitive types, this function will automatically - * return false. - */ - virtual bool is(Type* other) const override { - if (auto c = utils::cast(other)) { return is(c); } - return false; - } - - /** - * @brief Check whether one defiend type equals - * another defined type. - * - * @param other Type to check - * @return true/false depending on the equality - */ - virtual bool is(DefinedType* other) const; - - /// @brief Get the type represented as a "human-readable" string - std::string getPrettyName() const override; - /// @return the mangled version of the type - std::string getMangledName() const override; - /// @return The ast representation for the type - Syntax::Statement::DefinedTypeDef* getAST() const; - /// @return the parent class it inherits from - /// @note It may be std::nullptr if it does not inherit from - /// anything! - auto getParent() const { return parent; } - /// @brief Set the parent class it inherits from - void setParent(DefinedType* p) { parent = p; } - /// @return true/false depending on whether the class has a parent - auto hasParent() const { return parent != nullptr; } - /// @return A list containing all the fields declared for the class - /// @note It does not include the parent fields! - auto& getFields() const { return fields; } - /// @brief Append a new field (ClassField) to the list - void addField(ClassField* f); - /// @c Type::toRef() for information about this function. - /// @note It essentially does the same thing except it adds - /// generics if needed - Syntax::Expression::TypeRef* toRef() override; - /// @return true/false depending on whether the type is a struct - bool isStruct() const { return _struct; } - - /// @brief Get the static fields for the class - auto& getStaticFields() const { return staticFields; } - /// @brief Add a new static field to the class - void addStaticField(std::shared_ptr field) { staticFields.emplace_back(field); } - - void setMutable(bool m) override; - - /// @brief override function. - virtual bool canCast(Type* ty) const override; - virtual bool canCast(DefinedType* ty) const; - - public: - /// @brief If the class has a constructor - bool hasConstructor = false; - - virtual std::int64_t sizeOf() const override; - virtual std::int64_t alignmentOf() const override; - - SNOWBALL_TYPE_COPIABLE(DefinedType) -}; - -}; // namespace types -}; // namespace snowball - -#endif // __SNOWBALL_AST_DEFINED_TYPES_H_ diff --git a/src/ast/types/EnumType.cc b/src/ast/types/EnumType.cc deleted file mode 100644 index fab8b512..00000000 --- a/src/ast/types/EnumType.cc +++ /dev/null @@ -1,132 +0,0 @@ - -#include "EnumType.h" - -#include "../../common.h" -#include "../../constants.h" -#include "../../ir/values/Func.h" -#include "../../utils/utils.h" -#include "../syntax/common.h" -#include "Type.h" - -#include -#include -#include -#include - -namespace snowball { -namespace types { - -EnumType::EnumType( - const std::string& name, - const std::string uuid, - std::shared_ptr module, - Privacy::Status privacy -) : AcceptorExtend(Kind::ENUM, name) { - setGenerics(generics); - setPrivacy(privacy); - unsafeSetUUID(uuid); - unsafeSetModule(module); -} -EnumType::EnumField::EnumField( - const std::string& name, - std::vector types) - : types(types), name(name) { } -bool EnumType::is(EnumType* ty) const { - auto otherArgs = ty->getGenerics(); - bool genericSizeEqual = otherArgs.size() == generics.size(); - bool argumentsEqual = genericSizeEqual ? std::all_of( - otherArgs.begin(), - otherArgs.end(), - [&, idx = 0](Type * i) mutable { - idx++; - return generics.at(idx - 1)->is(i); - } - ) : - false; - return (ty->getUUID() == uuid) && argumentsEqual; -} -void EnumType::addField(EnumField field) { fields.push_back(field); } -std::string EnumType::getPrettyName() const { - auto base = module->isMain() ? "" : module->getName() + "::"; - auto n = base + getName(); - std::string genericString; // Start args tag - if (generics.size() > 0) { - genericString = "<"; - for (auto g : generics) { - genericString += g->getPrettyName(); - if (g != generics.back()) genericString += ", "; - } - genericString += ">"; - } - return n + genericString; -} - -std::string EnumType::getMangledName() const { - auto base = module->getUniqueName(); - auto _tyID = static_cast(getId()); - std::stringstream sstm; - sstm << (utils::startsWith(base, _SN_MANGLE_PREFIX) ? base : _SN_MANGLE_PREFIX) << "&" << name.size() << name << "Ev" - << _tyID; - auto prefix = sstm.str(); // disambiguator - std::string mangledArgs; // Start args tag - if (generics.size() > 0) { - mangledArgs = "EnuGSt"; - int argCounter = 1; - for (auto g : generics) { - mangledArgs += "A" + std::to_string(argCounter) + g->getMangledName(); - argCounter++; - } - } - std::string mangled = prefix + mangledArgs + "EnuE"; // Enu = end enum - return mangled; -} - -Syntax::Expression::TypeRef* EnumType::toRef() { - auto tRef = Syntax::TR(getUUID(), nullptr, this, getUUID()); - std::vector genericRef; - for (auto g : generics) { genericRef.push_back(g->toRef()); } - tRef->setGenerics(genericRef); - return tRef; -} - -bool EnumType::canCast(Type* ty) const { - if (auto x = utils::cast(ty)) return canCast(x); - return false; -} - -bool EnumType::canCast(EnumType* ty) const { - SNOWBALL_MUTABLE_CAST_CHECK - // TODO: maybe do something here? - return false; -} - -// - https://en.wikipedia.org/wiki/Data_structure_alignment#Computing_padding -std::int64_t EnumType::sizeOf() const { - auto maxSizeOf = (std::int64_t) 0; - for (const auto& f : fields) { - auto sizeOf = (std::int64_t) 0; - for (const auto t : f.types) { - auto s = t->sizeOf(); - if (s > sizeOf) sizeOf = s; - } - if (sizeOf > maxSizeOf) maxSizeOf = sizeOf; - } - return maxSizeOf * 8 + 8; // add 8 bytes for the enum field -} - -std::int64_t EnumType::alignmentOf() const { - auto maximumAlignment = (std::int64_t) 0; - for (const auto& f : fields) { - auto alignment = 0; - for (const auto t : f.types) { - auto a = t->alignmentOf(); - if (a > alignment) alignment = a; - } - if (alignment > maximumAlignment) maximumAlignment = alignment; - } - if (maximumAlignment == 0) maximumAlignment = 1; // prevent 0-sized types - return maximumAlignment; -} - -}; // namespace types -}; // namespace snowball diff --git a/src/ast/types/EnumType.h b/src/ast/types/EnumType.h deleted file mode 100644 index 915bc65d..00000000 --- a/src/ast/types/EnumType.h +++ /dev/null @@ -1,115 +0,0 @@ - -#include "../../common.h" -#include "../../constants.h" -#include "../../ir/id.h" -#include "../../ir/module/Module.h" -#include "../../utils/utils.h" -#include "../syntax/common.h" -#include "../syntax/nodes.h" -#include "BaseType.h" -#include "Type.h" - -#include -#include -#include - -#ifndef __SNOWBALL_AST_ENUM_TYPES_H_ -#define __SNOWBALL_AST_ENUM_TYPES_H_ - -namespace snowball { -namespace types { - -/** - * @brief Enum types. - * - * These types are defined by the programmer. They can contain some extra - * stuff such as generics and it's own defined members. Unlike - * primitive types, in order to use these type and it's member, - * a new initialization of the object is required. - */ -class EnumType final : public AcceptorExtend { - public: - /** - * @brief An enum field represents all of the "elements" a - * type has stored into it. - * - * @note The number of items does not affect whether this type - * is eqaul to another type. - */ - struct EnumField final : public DBGObject { - explicit EnumField( - const std::string& name, - std::vector types); - - const std::string name; - std::vector types; - - virtual ~EnumField() = default; - }; - - friend AcceptorExtend; - - private: - /// @brief a list of fields this class has - std::vector fields; - - public: - EnumType( - const std::string& name, - const std::string uuid, - std::shared_ptr module, - Privacy::Status privacy = PRIVATE - ); - /** - * @param other another type to check. - * - * @note Class types will only be checked - * if the @param other is also an enum type. - * - * For other types such as: function types and - * primitive types, this function will automatically - * return false. - */ - virtual bool is(Type* other) const override { - if (auto c = utils::cast(other)) { return is(c); } - return false; - } - - /** - * @brief Check whether one enum type equals - * another enum type. - * - * @param other Type to check - * @return true/false depending on the equality - */ - virtual bool is(EnumType* other) const; - - /// @brief Get the type represented as a "human-readable" string - std::string getPrettyName() const override; - /// @return the mangled version of the type - std::string getMangledName() const override; - /// @return A list containing all the fields declared for the class - auto& getFields() const { return fields; } - /// @brief Append a new field (EnumField) to the list - void addField(EnumField f); - /// @c Type::toRef() for information about this function. - /// @note It essentially does the same thing except it adds - /// generics if needed - Syntax::Expression::TypeRef* toRef() override; - - /// @brief override function. - virtual bool canCast(Type* ty) const override; - virtual bool canCast(EnumType* ty) const; - - public: - - virtual std::int64_t sizeOf() const override; - virtual std::int64_t alignmentOf() const override; - - SNOWBALL_TYPE_COPIABLE(EnumType) -}; - -}; // namespace types -}; // namespace snowball - -#endif // __SNOWBALL_AST_ENUM_TYPES_H_ diff --git a/src/ast/types/FunctionType.cc b/src/ast/types/FunctionType.cc deleted file mode 100644 index 017efe03..00000000 --- a/src/ast/types/FunctionType.cc +++ /dev/null @@ -1,76 +0,0 @@ - - -#include "FunctionType.h" - -#include "../../ast/syntax/nodes.h" -#include "../../common.h" -#include "../../constants.h" -#include "../../ir/values/Argument.h" -#include "../../ir/values/Func.h" -#include "../../utils/utils.h" -#include "Type.h" - -#include -#include -#include - -namespace snowball { -namespace types { - -std::string FunctionType::getPrettyName() const { - auto stringArgs = Syntax::Expression::FunctionCall::getArgumentsAsString(args); - auto stringRet = retTy->getPrettyName(); - if (variadic) { - if (stringArgs.size() > 0) stringArgs += ", "; - stringArgs += "..."; - } - return FMT("function (%s) %s-> %s", stringArgs.c_str(), isMutable() ? "mut " : "", stringRet.c_str()); -} - -bool FunctionType::is(FunctionType* other) const { - auto otherArgs = other->getArgs(); - if (args.size() != otherArgs.size()) return false; - bool argumentsEqual = - args.size() == 0 ? true : std::all_of(otherArgs.begin(), otherArgs.end(), [&, idx = 0](Type * i) mutable { - idx++; - return args.at(idx - 1)->is(i); - }); - auto returnEquals = retTy->is(other->getRetType()); - return returnEquals && argumentsEqual && (variadic == other->isVariadic()); -} - -std::string FunctionType::getMangledName() const { - std::string result = "_FntY."; // Function type indicator - result += retTy->getMangledName(); - result += "fAr"; // start of arguments list indicator - for (auto a : args) result += a->getMangledName(); - if (variadic) result += "VaGv"; - result += "fAe"; // end of arguments indicator - return result; -} - -FunctionType* FunctionType::from(ir::Func* fn, Syntax::Statement::FunctionDef* node) { - auto args = utils::map, Type*>( - fn->getArgs(), [&](auto map) -> auto{ return map.second->getType(); } - ); - bool isMutable = node ? node->isMutable() : false; - auto ret = fn->getRetTy(); - return new FunctionType(args, ret, fn->isVariadic(), isMutable, ""); -} - -bool FunctionType::isIgnoringSelf(FunctionType* other) { - assert(other->getArgs().size() > 0); - assert(args.size() > 0); - auto otherArgs = other->getArgs(); - if (args.size() != otherArgs.size()) return false; - bool argumentsEqual = - std::all_of(otherArgs.begin() + 1, otherArgs.end(), [&, idx = 1](Type * i) mutable { - idx++; - return args.at(idx - 1)->is(i); - }); - auto returnEquals = retTy->is(other->getRetType()); - return returnEquals && argumentsEqual && (variadic == other->isVariadic()); -} - -}; // namespace types -}; // namespace snowball diff --git a/src/ast/types/FunctionType.h b/src/ast/types/FunctionType.h deleted file mode 100644 index c9832910..00000000 --- a/src/ast/types/FunctionType.h +++ /dev/null @@ -1,129 +0,0 @@ - -#include "../../common.h" -#include "../../constants.h" -#include "../../ir/values/Func.h" -#include "../../utils/utils.h" -#include "Type.h" - -#include -#include -#include - -#ifndef __SNOWBALL_AST_FUNCTION_TYPES_H_ -#define __SNOWBALL_AST_FUNCTION_TYPES_H_ - -/** - * Function types are really insane. When checking - * a function type, we must take into consideration - * all the factors that make 2 functions equal. - * This can be checked by checking: - * - function types, base type, return type, ... - * - * hold on, give me some (mathematical) examples, pls: - * - lets imagine the following function declaration. - * - * pub fn incrementN(n: i32) i32 { return n++; } - * - * This function will be mathematicaly considered as - * `λn.n+1`. In this example, we can see that function's - * return and first argument has type `i32`. These are all - * factors that we will take into consideration for checking - * whether 2 functions match or not. - * - * In simple type theory, two functions are considered equal - * if they have the same type and produce the same output for the - * same input. For example, if we have two functions f and g of - * type A -> B, where A and B are types, f and g are considered - * equal if for all values x of type A, f(x) = g(x). This notion - * of equality between functions is known as extensionality. - * - * Of course, this checking theory just checks for parameter types, - * but in snowball, we also some take more things into consideration - * whether `f(x) = g(x)` or `f(x) != g(x)`. - */ -namespace snowball { -namespace types { - -class FunctionType : public AcceptorExtend, public Syntax::AttributeHolder { - // Function's argument type. - std::vector args; - // Function's return type. - Type* retTy; - // Whether or not a function is declared - // as variadic. - bool variadic = false; - - public: - FunctionType( - std::vector args, - Type* retTy, - bool isVariadic = false, - bool isMutable = true, - const std::string& name = "" - ) - : AcceptorExtend(Kind::TYPE, name, isMutable), args(args), retTy(retTy), variadic(isVariadic) {} - FunctionType(const FunctionType& other) = default; - - /** - * @param other another (non-functional) type. - * - * This function will always return false if the type - * is not a functional type since you can't compare - * functional types with "normal" types. e.g.: - * function void (i32) == string - * - * This will just wont work. C++ will just look for the - * actual function corresponding to a FunctionType and this - * function will just have the purpose as a fallback. - */ - virtual bool is(Type* other) const override { - if (auto f = utils::cast(other)) { return is(f); } - return false; - } - - /** - * @brief Check whether one function type matches - * another function type. - * - * @param other Function type to check - * @return true/false depending on the equality - */ - virtual bool is(FunctionType* other) const; - - /// @return function argument types - std::vector getArgs() const { return args; } - /// @return function return types - Type* getRetType() const { return retTy; } - /// @return If the function is declared as variadic - bool isVariadic() const { return variadic; } - - // std::string getName() const override; // TODO: - - /** - * @brief Get the function represented as a "human-readable" - * string - */ - std::string getPrettyName() const override; - std::string getMangledName() const override; - - public: - /** - * Create a function type based on the given node. - * - * @param fn Function value to process - * @return FunctionType* resultant type - */ - static FunctionType* from(ir::Func* fn, Syntax::Statement::FunctionDef* node = nullptr); - - virtual std::int64_t sizeOf() const override { return 8; } - virtual std::int64_t alignmentOf() const override { return 8; } - - bool isIgnoringSelf(FunctionType* fn); - - SNOWBALL_TYPE_COPIABLE(FunctionType) -}; - -}; // namespace types -}; // namespace snowball - -#endif // __SNOWBALL_AST_FUNCTION_TYPES_H_ diff --git a/src/ast/types/Interface.cc b/src/ast/types/Interface.cc deleted file mode 100644 index 0bb25d04..00000000 --- a/src/ast/types/Interface.cc +++ /dev/null @@ -1,112 +0,0 @@ - -#include "Interface.h" - -#include "../../common.h" -#include "../../constants.h" -#include "../../ir/values/Func.h" -#include "../../utils/utils.h" -#include "../syntax/common.h" -#include "Type.h" - -#include -#include -#include -#include - -namespace snowball { -namespace types { - -bool InterfaceType::is(InterfaceType* ty) const { - auto otherArgs = ty->getGenerics(); - bool genericSizeEqual = otherArgs.size() == generics.size(); - bool argumentsEqual = genericSizeEqual ? std::all_of( - otherArgs.begin(), - otherArgs.end(), - [&, idx = 0](Type * i) mutable { - idx++; - return generics.at(idx - 1)->is(i); - } - ) : - false; - return (ty->getUUID() == uuid) && argumentsEqual; -} - -Syntax::Expression::TypeRef* InterfaceType::toRef() { - auto tRef = Syntax::TR(getUUID(), nullptr, this, getUUID()); - std::vector genericRef; - for (auto g : generics) { genericRef.push_back(g->toRef()); } - tRef->setGenerics(genericRef); - return tRef; -} - -std::string InterfaceType::getPrettyName() const { - auto base = module->isMain() ? "" : module->getName() + "::"; - auto n = base + getName(); - std::string genericString; // Start args tag - if (generics.size() > 0) { - genericString = "<"; - for (auto g : generics) { - genericString += g->getPrettyName(); - if (g != generics.back()) genericString += ", "; - } - genericString += ">"; - } - std::string mut = isMutable() ? "mut " : ""; - auto res = mut + n + genericString; - if (getName() == _SNOWBALL_CONST_PTR) { - res = "(*const " + generics.at(0)->getName() + ")"; - } else if (getName() == _SNOWBALL_MUT_PTR) { - res = "(*mut " + generics.at(0)->getName() + ")"; - } - return res; -} - -std::string InterfaceType::getMangledName() const { - auto base = module->getUniqueName(); - auto _tyID = static_cast(getId()); - std::stringstream sstm; - sstm << (utils::startsWith(base, _SN_MANGLE_PREFIX) ? base : _SN_MANGLE_PREFIX) << "&" << name.size() << name << "I" - << _tyID; - auto prefix = sstm.str(); // disambiguator - std::string mangledArgs; // Start args tag - if (generics.size() > 0) { - mangledArgs = "IGSt"; - int argCounter = 1; - for (auto g : generics) { - mangledArgs += "A" + std::to_string(argCounter) + g->getMangledName(); - argCounter++; - } - } - std::string mangled = prefix + mangledArgs + "IE"; // ClsE = end of class - return mangled; -} - -// - https://en.wikipedia.org/wiki/Data_structure_alignment#Computing_padding -std::int64_t InterfaceType::sizeOf() const { - auto address = (std::int64_t) 0; - for (const auto& f : fields) { - auto typeSize = f->type->sizeOf(); - auto typeAlignment = f->type->alignmentOf(); - address += (address - (address % typeAlignment)) % typeAlignment; - address += (typeAlignment - (address % typeAlignment)) % typeAlignment; - address += typeSize; - } - auto alignment = alignmentOf(); - address += (address - (address % alignment)) % alignment; - address += (alignment - (address % alignment)) % alignment; - if (address == 0) address = 1; - return address + (hasVtable * 8); -} - -std::int64_t InterfaceType::alignmentOf() const { - auto maximumAlignment = (std::int64_t) 0; - for (const auto& f : fields) { - auto alignment = f->type->alignmentOf(); - if (alignment > maximumAlignment) maximumAlignment = alignment; - } - if (maximumAlignment == 0) maximumAlignment = 1; - return maximumAlignment; -} - -}; // namespace types -}; // namespace snowball diff --git a/src/ast/types/Interface.h b/src/ast/types/Interface.h deleted file mode 100644 index 56bcb62b..00000000 --- a/src/ast/types/Interface.h +++ /dev/null @@ -1,131 +0,0 @@ - -#include "../../common.h" -#include "../../constants.h" -#include "../../ir/id.h" -#include "../../ir/module/Module.h" -#include "../../utils/utils.h" -#include "../syntax/common.h" -#include "../syntax/nodes.h" -#include "BaseType.h" -#include "DefinedType.h" -#include "Type.h" - -#include -#include -#include - -#include "../syntax/nodes.h" - -#ifndef __SNOWBALL_AST_INTERFACES_TYPES_H_ -#define __SNOWBALL_AST_INTERFACES_TYPES_H_ - -namespace snowball { -namespace types { - -/** - * @brief Interface types. - * - * These can also be called as classes or objects. This - * type is defined by the programmer. It can contain some extra - * stuff such as generics and it's own defined members. Unlike - * primitive types, in order to use these type and it's member, - * a new initialization of the object is required. - * - * @note This type is different from the DefinedType type. - * The difference is that this type is used for interfaces - * and the DefinedType is used for classes. - * - * @see DefinedType - */ -class InterfaceType : public BaseType { - public: - struct Member : public DefinedType::ClassField { - enum Kind { - FIELD, - METHOD - } kind; - - explicit Member( - const std::string& name, - Type* type, - Kind kind, - Syntax::Statement::Base* ast, - Privacy privacy = PRIVATE, - bool isMutable = false - ) - : ClassField(name, type, privacy, nullptr, isMutable), kind(kind), ast(ast) {}; - Syntax::Statement::Base* ast; - }; - - private: - /// @brief a list of fields this class has - std::vector fields; - - public: - InterfaceType( - const std::string& name, - const std::string uuid, - std::shared_ptr module, - std::vector fields = {}, - std::vector generics = {} - ) - : BaseType(INTERFACE, name), fields(fields) { - setGenerics(generics); - unsafeSetUUID(uuid); - unsafeSetModule(module); - }; - InterfaceType(const InterfaceType&) = default; - InterfaceType& operator=(InterfaceType const&) = delete; - /** - * @param other another type to check. - * - * @note Class types will only be checked - * if the @param other is also a defined type. - * - * For other types such as: function types and - * primitive types, this function will automatically - * return false. - */ - virtual bool is(Type* other) const override { - if (auto c = utils::cast(other)) { return is(c); } - return false; - } - - /** - * @brief Check whether one defiend type equals - * another defined type. - * - * @param other Type to check - * @return true/false depending on the equality - */ - virtual bool is(InterfaceType* other) const; - - /// @brief Get the type represented as a "human-readable" string - std::string getPrettyName() const override; - /// @return the mangled version of the type - std::string getMangledName() const override; - /// @return A list containing all the fields declared for the interface - /// @note It does not include the parent fields! - auto getFields() const { return fields; } - /// @brief Add a new field to the interface - void addField(Member* f) { fields.emplace_back(f); } - /// @c Type::toRef() for information about this function. - /// @note It essentially does the same thing except it adds - /// generics if needed - Syntax::Expression::TypeRef* toRef() override; - - /// @brief override function. - virtual bool canCast(Type* ty) const override { return false; } - virtual bool canCast(InterfaceType* ty) const { return false; } - - public: - virtual std::int64_t sizeOf() const override; - virtual std::int64_t alignmentOf() const override; - - SNOWBALL_TYPE_COPIABLE(InterfaceType) -}; - -}; // namespace types -}; // namespace snowball - -#endif // __SNOWBALL_AST_INTERFACES_TYPES_H_ diff --git a/src/ast/types/PointerType.cc b/src/ast/types/PointerType.cc deleted file mode 100644 index 2c0ae420..00000000 --- a/src/ast/types/PointerType.cc +++ /dev/null @@ -1,55 +0,0 @@ - -#include "PointerType.h" - -#include "../../common.h" -#include "../../constants.h" -#include "../../ir/values/Func.h" -#include "../../utils/utils.h" -#include "../syntax/common.h" -#include "Type.h" - -#include -#include -#include -#include - -namespace snowball { -namespace types { - -PointerType::PointerType(Type* base, bool isMutable) : AcceptorExtend(Kind::TYPE, base->getName()), base(base) { - setMutable(isMutable); -} -Type* PointerType::getPointedType() const { return base; } -std::string PointerType::getPrettyName() const { - auto baseName = base->getPrettyName(); - return "*" + (std::string)(isMutable() ? "mut " : "const ") + baseName; -} - -std::string PointerType::getMangledName() const { - auto mangledBase = base->getMangledName(); - return mangledBase + ".p"; -} - -Syntax::Expression::TypeRef* PointerType::toRef() { - auto tRef = new Syntax::Expression::PointerType(base->toRef(), isMutable(), getDBGInfo()); - return tRef; -} - -Type* PointerType::getBaseType() const { - if (auto c = utils::cast(base)) return c->getBaseType(); - return base; -} - -bool PointerType::canCast(Type* ty) const { - SNOWBALL_MUTABLE_CAST_CHECK - if (auto c = utils::cast(ty)) return base->canCast(c->getPointedType()); - return false; -} - -void PointerType::setMutable(bool m) { - _mutable = m; - name = m ? _SNOWBALL_MUT_PTR : _SNOWBALL_CONST_PTR; -} - -}; // namespace types -}; // namespace snowball diff --git a/src/ast/types/PointerType.h b/src/ast/types/PointerType.h deleted file mode 100644 index 528a6cbc..00000000 --- a/src/ast/types/PointerType.h +++ /dev/null @@ -1,74 +0,0 @@ - -#include "../../common.h" -#include "../../constants.h" -#include "../../ir/id.h" -#include "../../ir/module/Module.h" -#include "../../utils/utils.h" -#include "../syntax/common.h" -#include "../syntax/nodes.h" -#include "Type.h" - -#include -#include -#include - -#ifndef __SNOWBALL_AST_POINTER_TYPES_H_ -#define __SNOWBALL_AST_POINTER_TYPES_H_ - -namespace snowball { -namespace types { - -class PointerType : public AcceptorExtend, public DBGObject { - friend AcceptorExtend; - - private: - /// @brief Base class that this type is pointing to - Type* base = nullptr; - - public: - PointerType(Type* base, bool isMutable); - PointerType(const PointerType& other) = default; - - /** - * @param other another type to check. - */ - virtual bool is(Type* other) const override { - if (auto c = utils::cast(other)) { return base->is(c->getPointedType()); } - return false; - } - - /// @brief Get the type represented as a "human-readable" string - std::string getPrettyName() const override; - /// @return the mangled version of the type - std::string getMangledName() const override; - /// @return The pointed type this type is pointing to - /// @see PointerType::base - Type* getPointedType() const; - /// @return The base type being pointed. - /// @example ****i32 -> i32 - Type* getBaseType() const; - - /// @c Type::toRef() for information about this function. - /// @note It essentially does the same thing except it adds - /// generics if needed - Syntax::Expression::TypeRef* toRef() override; - - /// @brief override function. All numeric types - /// can cast to any other numeric types. - bool canCast(Type* ty) const override; - - /// @brief let's make it polymorphic - virtual bool isReference() const { return true; } - - virtual void setMutable(bool m) override; - - virtual std::int64_t sizeOf() const override { return 8; } - virtual std::int64_t alignmentOf() const override { return 8; } - - SNOWBALL_TYPE_COPIABLE(PointerType) -}; - -}; // namespace types -}; // namespace snowball - -#endif // __SNOWBALL_AST_POINTER_TYPES_H_ diff --git a/src/ast/types/PrimitiveTypes.cc b/src/ast/types/PrimitiveTypes.cc deleted file mode 100644 index 451a7f3c..00000000 --- a/src/ast/types/PrimitiveTypes.cc +++ /dev/null @@ -1,7 +0,0 @@ -#include "PrimitiveTypes.h" - -#include "../../utils/utils.h" - -namespace snowball::types { -bool NumericType::isNumericType(Type* ty) { return utils::is(ty); } -} // namespace snowball::types diff --git a/src/ast/types/PrimitiveTypes.h b/src/ast/types/PrimitiveTypes.h deleted file mode 100644 index 32b63b92..00000000 --- a/src/ast/types/PrimitiveTypes.h +++ /dev/null @@ -1,126 +0,0 @@ - -#include "../../common.h" -#include "../../constants.h" -#include "../../utils/utils.h" -#include "Type.h" - -#include - -#ifndef __SNOWBALL_AST_PRIMITIVE_TYPE_H_ -#define __SNOWBALL_AST_PRIMITIVE_TYPE_H_ - -#define SN_BOOL_TYPE "bool" -#define SN_STR_TYPE "String" -#define SN_CHR_TYPE "char" -#define SN_INT64_TYPE "i64" -#define SN_INT32_TYPE "i32" -#define SN_INT16_TYPE "i16" -#define SN_INT8_TYPE "i8" -#define SN_F64_TYPE "f64" -#define SN_F32_TYPE "f32" -#define SN_VOID_TYPE "void" - -/** - * Primitive types are those types who differ from - * user defined types. These types are not constructed. - * - * These types often refers to a limited set of data - * in use by a particular preprocessor. - * - * There are: null, int, string, float, etc... - */ -namespace snowball { -namespace types { -class PrimitiveType : public AcceptorExtend { - public: - PrimitiveType(std::string p_name) : AcceptorExtend(Kind::TYPE, p_name) { } - SNOWBALL_TYPE_COPIABLE(PrimitiveType) -}; - -/** - * @brief This is a primitive type that acts like - * a numeric type. (e.g. i32, f64, bool, etc...) - */ -class NumericType : public AcceptorExtend { - public: - NumericType(std::string p_name) : AcceptorExtend(p_name) {}; - - /// @brief override function. All numeric types - /// can cast to any other numeric types. - virtual bool canCast(Type* ty) const override { return NumericType::isNumericType(ty); } - - public: - /** - * @brief Check if a type is numeric. - * @note These are the numberic types: - * ints: i[N], i64, i32, i16, i8, - * floats: f64, f32, - * boolean: i1 - */ - static bool isNumericType(Type* ty); - SNOWBALL_TYPE_COPIABLE(NumericType) -}; - -/// @brief Representation of a void type. -class VoidType : public AcceptorExtend { - public: - VoidType() : AcceptorExtend(SN_VOID_TYPE) { } - SNOWBALL_TYPE_COPIABLE(VoidType) - - virtual std::int64_t sizeOf() const override { return 0; } - virtual std::int64_t alignmentOf() const override { return 0; } -}; - -/// @brief Float (N) (represents N-bit floating point) -class FloatType : public AcceptorExtend { - std::int32_t bits; - - public: - FloatType(std::int32_t bits) : bits(bits), AcceptorExtend("f" + std::to_string(bits)) { } - std::int32_t getBits() const { return bits; } - SNOWBALL_TYPE_COPIABLE(FloatType) - - virtual std::int64_t sizeOf() const override { return bits; } - virtual std::int64_t alignmentOf() const override { return bits; } -}; - -/** - * Int (N) (represents N-bit signed integer) - * @note This is a base class for all integer types. - */ -class IntType : public AcceptorExtend { - std::int32_t bits; - bool isItSigned = true; - - public: - IntType(std::int32_t bits, bool isSigned = true) : bits(bits), isItSigned(isSigned), - AcceptorExtend(bits == 1 ? "bool" : (isSigned ? "i" : "u") + std::to_string(bits)) { } - std::int32_t getBits() const { return bits; } - bool isSigned() const { return isItSigned; } - SNOWBALL_TYPE_COPIABLE(IntType) - - virtual std::int64_t sizeOf() const override { return bits == 1 ? 1 : (std::int64_t)(bits); } - virtual std::int64_t alignmentOf() const override { return bits == 1 ? 1 : (std::int64_t)(bits); } -}; - -/// @brief Utility method to check if a type is an integer type. -static bool isIntType(Type* ty, std::int32_t bits = 32) { - if (auto x = utils::cast(ty)) return x->getBits() == bits; - return false; -} - -static bool isInt32Type(Type* ty) { return isIntType(ty, 32); } - -/// @brief Utility method to check if a type is a float type. -static bool isFloatType(Type* ty, std::int32_t bits = 32) { - if (auto x = utils::cast(ty)) return x->getBits() == bits; - return false; -} - -static bool isFloat32Type(Type* ty) { return isFloatType(ty, 32); } -static bool isDoubleType(Type* ty) { return isFloatType(ty, 64); } - -}; // namespace types -}; // namespace snowball - -#endif // __SNOWBALL_AST_PRIMITIVE_TYPE_H_ diff --git a/src/ast/types/ReferenceType.cc b/src/ast/types/ReferenceType.cc deleted file mode 100644 index 4e80b217..00000000 --- a/src/ast/types/ReferenceType.cc +++ /dev/null @@ -1,53 +0,0 @@ - -#include "ReferenceType.h" - -#include "../../common.h" -#include "../../constants.h" -#include "../../ir/values/Func.h" -#include "../../utils/utils.h" -#include "../syntax/common.h" -#include "Type.h" - -#include -#include -#include -#include - -namespace snowball { -namespace types { - -ReferenceType::ReferenceType(Type* base) : AcceptorExtend(Kind::TYPE, "&" + base->getName()), base(base) { -} -Type* ReferenceType::getPointedType() const { return base; } -std::string ReferenceType::getPrettyName() const { - auto baseName = base->getPrettyName(); - return "&" + baseName; -} - -std::string ReferenceType::getMangledName() const { - auto mangledBase = base->getMangledName(); - return mangledBase + ".r"; -} - -Syntax::Expression::TypeRef* ReferenceType::toRef() { - auto tRef = new Syntax::Expression::ReferenceType(base->toRef(), getDBGInfo()); - return tRef; -} - -Type* ReferenceType::getBaseType() const { - if (auto c = utils::cast(base)) return c->getBaseType(); - return base; -} - -bool ReferenceType::canCast(Type* ty) const { - SNOWBALL_MUTABLE_CAST_CHECK - if (auto c = utils::cast(ty)) return base->canCast(c->getPointedType()); - return false; -} - -void ReferenceType::setMutable(bool m) { - _mutable = m; -} - -}; // namespace types -}; // namespace snowball diff --git a/src/ast/types/ReferenceType.h b/src/ast/types/ReferenceType.h deleted file mode 100644 index 8b3a3739..00000000 --- a/src/ast/types/ReferenceType.h +++ /dev/null @@ -1,74 +0,0 @@ - -#include "../../common.h" -#include "../../constants.h" -#include "../../ir/id.h" -#include "../../ir/module/Module.h" -#include "../../utils/utils.h" -#include "../syntax/common.h" -#include "../syntax/nodes.h" -#include "Type.h" - -#include -#include -#include - -#ifndef __SNOWBALL_AST_REFERENCE_TYPES_H_ -#define __SNOWBALL_AST_REFERENCE_TYPES_H_ - -namespace snowball { -namespace types { - -class ReferenceType : public AcceptorExtend, public DBGObject { - friend AcceptorExtend; - - private: - /// @brief Base class that this type is pointing to - Type* base = nullptr; - - public: - ReferenceType(Type* base); - ReferenceType(const ReferenceType& other) = default; - - /** - * @param other another type to check. - */ - virtual bool is(Type* other) const override { - if (auto c = utils::cast(other)) { return base->is(c->getPointedType()); } - return false; - } - - /// @brief Get the type represented as a "human-readable" string - std::string getPrettyName() const override; - /// @return the mangled version of the type - std::string getMangledName() const override; - /// @return The pointed type this type is pointing to - /// @see ReferenceType::base - Type* getPointedType() const; - /// @return The base type being pointed. - /// @example i32**** -> i32 - Type* getBaseType() const; - - /// @c Type::toRef() for information about this function. - /// @note It essentially does the same thing except it adds - /// generics if needed - Syntax::Expression::TypeRef* toRef() override; - - /// @brief override function. All numeric types - /// can cast to any other numeric types. - bool canCast(Type* ty) const override; - - /// @brief let's make it polymorphic - virtual bool isReference() const { return true; } - - virtual void setMutable(bool m) override; - - virtual std::int64_t sizeOf() const override { return 8; } - virtual std::int64_t alignmentOf() const override { return 8; } - - SNOWBALL_TYPE_COPIABLE(ReferenceType) -}; - -}; // namespace types -}; // namespace snowball - -#endif // __SNOWBALL_AST_REFERENCE_TYPES_H_ diff --git a/src/ast/types/Type.cc b/src/ast/types/Type.cc deleted file mode 100644 index b57b122c..00000000 --- a/src/ast/types/Type.cc +++ /dev/null @@ -1,24 +0,0 @@ - -#include "Type.h" - -#include "../syntax/nodes.h" -#include "PointerType.h" -#include "ReferenceType.h" - -namespace snowball { -namespace types { - -Type::Type(Kind p_kind, std::string p_name, bool isMutable) : kind(p_kind), name(p_name), _mutable(isMutable) { } -Type::Type(Kind p_kind, bool isMutable) : kind(p_kind), _mutable(isMutable) { } - -Syntax::Expression::TypeRef* Type::toRef() { - auto ty = Syntax::TR(getName(), NO_DBGINFO, this, getName()); - return ty; -} - -Type* Type::getReferenceTo() { return new ReferenceType(copy()); } -Type* Type::getPointerTo(bool isMutable) { return new PointerType(copy(), isMutable); } -Type* Type::copy() const { assert(!"called copy to not-specialised type!"); } -void Type::setMutable(bool m) { _mutable = m; } -} // namespace types -} // namespace snowball diff --git a/src/ast/types/Type.h b/src/ast/types/Type.h deleted file mode 100644 index e2cdaa96..00000000 --- a/src/ast/types/Type.h +++ /dev/null @@ -1,118 +0,0 @@ - -#include "../../common.h" -#include "../../ir/id.h" - -#include -#include -#include -#include - -#define SNOWBALL_TYPE_COPIABLE(X) \ - Type* copy() const override { return new X(*this); } - -#ifndef __SNOWBALL_AST_TYPE_H_ -#define __SNOWBALL_AST_TYPE_H_ - -#define SNOWBALL_MUTABLE_CAST_CHECK \ - if (!_mutable && ty->isMutable()) return false; - -/** - * Types in snowball can be represented in many different forms. - * There can be user defined types (aka, classes and structs) and - * there can be already built in primitive types. - * - * The purpose of this base type is to create a common group - * for all of this kind of types. - * - * Each type should have atleast a function that generates it's - * llvm ir equivalent of it. - */ -namespace snowball { - -namespace Syntax { -namespace Expression { -struct TypeRef; -} -}; // namespace Syntax - -namespace types { -class ReferenceType; -class InterfaceType; - -class Type { - protected: - // Type's name - std::string name; - // Whether or not a type is mutable - bool _mutable = false; - // A type implementation - std::vector impls; - - public: - enum Kind { - TYPE, - CLASS, - REF, - INTERFACE, - ENUM, - } kind; - - public: - explicit Type(Kind p_kind, bool isMutable = false); - explicit Type(Kind p_kind, std::string p_name, bool isMutable = false); - - Type& operator=(const Type&) = delete; - Type(const Type& other) = default; - - ~Type() noexcept = default; - - /// @param other another type - /// @return true if this type is equal to the argument type - virtual bool is(Type* other) const { return getName() == other->getName(); } - /// @return current's type name - virtual std::string getName() const { return name; } - /// @return type's pretty names, commonly used for output - virtual std::string getPrettyName() const { return (_mutable ? "mut " : "") + name; }; - /// @return Get a mangled version of the current type - virtual std::string getMangledName() const { return "T" + std::to_string(name.size()) + name; }; - - /// @return if a type can be casted to this type - virtual bool canCast(Type* ty) const { return false; } - - /// @brief Create a *new* reference type with this type as base - /// @return a std::shared_ptr but casted into a `Type` - virtual Type* getReferenceTo(); - /// @brief Create a *new* pointer type with this type as base - /// @return a std::shared_ptr but casted into a `Type` - virtual Type* getPointerTo(bool isMutable); - - /// @brief Create a new copy of this type - /// @return a Type* but casted into a `Type` - virtual Type* copy() const; - - /// @brief Transform the type into a syntax type reference node. - /// This is useful for cases such as class methods where the first - /// argument needs to be "self" (aka. A type reference to it's - /// parent class) - virtual Syntax::Expression::TypeRef* toRef(); - - /// @return If the function is mutable - virtual bool isMutable() const { return _mutable; } - /// @brief Set the mutability of the type - virtual void setMutable(bool m); - - /// @return The size of the type in bytes - virtual std::int64_t sizeOf() const { assert(!"called sizeOf to not-specialised type!"); } - /// @return The alignment of the type in bytes - virtual std::int64_t alignmentOf() const { assert(!"called alignmentOf to not-specialised type!"); } - - /// @brief Get the type's implementation - std::vector getImpls() const { return impls; } - /// @brief Add a type implementation - void addImpl(InterfaceType* impl) { impls.push_back(impl); } -}; - -}; // namespace types -}; // namespace snowball - -#endif // __SNOWBALL_AST_TYPE_H_ diff --git a/src/ast/types/TypeAlias.cc b/src/ast/types/TypeAlias.cc deleted file mode 100644 index 5d249811..00000000 --- a/src/ast/types/TypeAlias.cc +++ /dev/null @@ -1,45 +0,0 @@ - -#include "TypeAlias.h" - -#include "../../common.h" -#include "../../constants.h" -#include "../../ir/values/Func.h" -#include "../../utils/utils.h" -#include "../syntax/common.h" -#include "Type.h" - -#include -#include -#include -#include - -namespace snowball { -namespace types { - -TypeAlias::TypeAlias(const std::string name, Type* base) : AcceptorExtend(Kind::TYPE, name), base(base) { } -std::string TypeAlias::getPrettyName() const { - auto baseName = base->getPrettyName(); - auto base = module->isMain() ? "" : module->getName() + "::"; - auto n = base + getName(); - std::string genericString; // Start args tag - if (generics.size() > 0) { - genericString = "<"; - for (auto g : generics) { genericString += g->getPrettyName(); } - genericString += ">"; - } - return n + genericString + " { aka " + baseName + " }"; -} - -std::string TypeAlias::getMangledName() const { return base->getMangledName(); } - -Syntax::Expression::TypeRef* TypeAlias::toRef() { - auto tRef = Syntax::TR(getName(), nullptr, this, getUUID()); - return tRef; -} - -Type* TypeAlias::getBaseType() const { return base; } - -bool TypeAlias::canCast(Type* ty) const { return base->canCast(ty); } - -}; // namespace types -}; // namespace snowball diff --git a/src/ast/types/TypeAlias.h b/src/ast/types/TypeAlias.h deleted file mode 100644 index 67827740..00000000 --- a/src/ast/types/TypeAlias.h +++ /dev/null @@ -1,63 +0,0 @@ - -#include "../../common.h" -#include "../../constants.h" -#include "../../ir/id.h" -#include "../../ir/module/Module.h" -#include "../../utils/utils.h" -#include "../syntax/common.h" -#include "../syntax/nodes.h" -#include "BaseType.h" -#include "Type.h" - -#include -#include -#include - -#ifndef __SNOWBALL_AST_ALIAS_TYPES_H_ -#define __SNOWBALL_AST_ALIAS_TYPES_H_ - -namespace snowball { -namespace types { - -class TypeAlias : public AcceptorExtend { - friend AcceptorExtend; - - private: - /// @brief Base class that this type is pointing to - Type* base = nullptr; - - public: - TypeAlias(const std::string name, Type* base); - TypeAlias(const TypeAlias& other) = default; - - /** - * @param other another type to check. - */ - virtual bool is(Type* other) const override { return base->is(other); } - - /// @brief Get the type represented as a "human-readable" string - std::string getPrettyName() const override; - /// @return the mangled version of the type - std::string getMangledName() const override; - /// @return The pointed type this type is pointing to - Type* getBaseType() const; - - /// @c Type::toRef() for information about this function. - /// @note It essentially does the same thing except it adds - /// generics if needed - Syntax::Expression::TypeRef* toRef() override; - - /// @brief override function. All numeric types - /// can cast to any other numeric types. - bool canCast(Type* ty) const override; - - virtual std::int64_t sizeOf() const override { return base->sizeOf(); } - virtual std::int64_t alignmentOf() const override { return base->alignmentOf(); } - - SNOWBALL_TYPE_COPIABLE(TypeAlias) -}; - -}; // namespace types -}; // namespace snowball - -#endif // __SNOWBALL_AST_ALIAS_TYPES_H_ diff --git a/src/ast/visitor/ASTContext.h b/src/ast/visitor/ASTContext.h deleted file mode 100644 index 89ec17a0..00000000 --- a/src/ast/visitor/ASTContext.h +++ /dev/null @@ -1,139 +0,0 @@ - - -#include "../errors/error.h" -#include "../types/PrimitiveTypes.h" - -#include -#include -#include -#include -#include -#include -#include - -#ifndef __SNOWBALL_AST_CONTEXT_H_ -#define __SNOWBALL_AST_CONTEXT_H_ - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wformat-security" - -namespace snowball { -namespace Syntax { - -template -class ASTContext { - using Item = std::shared_ptr; - using Scope = std::map; - - protected: - /** A scope is a representation of a "block" where all - * the variables are stored into it. Variables can be - * accessed from parent scopes and the order of finding - * them is from start to end. - * - * fn ...() { - * var a = 2; - * - * if (a == 2) { - * a = 3 - * } - * } - * - * This would be equal to the following stack: - * if-stmt scope > fn scope > global scope - * (no vars) (var a) (types, etc) - */ - std::list stack = {}; - - public: - ASTContext() { - // Create a global scope for primitive types - addScope(); - } - ~ASTContext() noexcept = default; - /** - * @brief Insert an item into the current stack - * - * @param name Identifier for the item - * @param item Item to be stored - */ - void addItem(const std::string& name, Item item) { - DEBUG_SYMTABLE(1, FMT(" Adding to scope: %s", name.c_str()).c_str()) - auto f = stack.front(); - auto val = f.find(name); - if (val != f.end()) - E(item, FMT("Item '%s' is already defined!", name.c_str())); - stack.front().insert(std::make_pair(name, item)); - } - /** - * @brief Get the Item from the stack - * - * @param name Item to search for - * @return {item or nullptr, if found} - */ - std::pair getItem(const std::string name) const { - for (auto s : stack) { - auto[val, found] = getInScope(name, s); - if (found) { - DEBUG_SYMTABLE(1, FMT("[symtable]: Successfully fetched %s", name.c_str()).c_str()) - return {val, true}; - } - } - DEBUG_SYMTABLE(1, FMT("[symtable]: Coudn't fetch '%s'", name.c_str()).c_str()) - return {std::shared_ptr(nullptr), false}; - } - /** - * @brief Search for an item in a certain scope - * - * @param name item to search for - * @param s scope where search is performed - * @return {item or nullptr, if found} - */ - std::pair getInScope(const std::string name, Scope s) const { - auto val = s.find(name); - if (val != s.end()) { return {val->second, true}; } - return {std::shared_ptr(nullptr), false}; - } - /** - * @brief Get the Item from the current scope - * - * @param name Item to search for - * @return {item or nullptr, if found} - */ - std::pair getInCurrentScope(const std::string name) const { - return getInScope(name, currentScope()); - } - /// @return the current scope the programm is into - Scope currentScope() const { return stack.front(); } - /// @brief Create a new scope and append it. - void addScope() { - DEBUG_SYMTABLE(0, "Creating new scope") - Scope newScope{}; - stack.insert(stack.begin(), newScope); - } - /// @brief Run a function inside a scope - void withScope(std::function func) { - addScope(); - func(); - delScope(); - } - /** - * @brief Delete the current scope - * @return Scope The deleted scope - */ - void delScope() { - DEBUG_SYMTABLE(0, "Deleting scope") - stack.pop_front(); - } - /// @brief If the scope is the global scope - bool isGlobalScope() { return stack.size() == 2; } - /// @brief Get the scope index - int getScopeIndex() { return stack.size() - 1; } -}; - -} // namespace Syntax -} // namespace snowball - -#pragma GCC diagnostic pop - -#endif // __SNOWBALL_AST_CONTEXT_H_ diff --git a/src/ast/visitor/Visitor.cc b/src/ast/visitor/Visitor.cc deleted file mode 100644 index d27c4234..00000000 --- a/src/ast/visitor/Visitor.cc +++ /dev/null @@ -1,15 +0,0 @@ - -#include "Visitor.h" - -#include "../syntax/nodes.h" - -namespace snowball { -namespace Syntax { - -void Visitor::visitGlobal(std::vector p_list) { - for (auto node : p_list) - node->accept(this); -} - -} // namespace Syntax -} // namespace snowball diff --git a/src/ast/visitor/Visitor.h b/src/ast/visitor/Visitor.h deleted file mode 100644 index 0e482cc7..00000000 --- a/src/ast/visitor/Visitor.h +++ /dev/null @@ -1,30 +0,0 @@ - -#include "../../sourceInfo/SourcedObject.h" -#include "../syntax/nodes.h" - -#include -#include -#include - -#ifndef __SNOWBALL_AST_VISITOR_H_ -#define __SNOWBALL_AST_VISITOR_H_ - -#define ACCEPT(Node) \ - virtual void visit(Node* p_node) { assert(false && "BUG: Visitor::visit called"); } - -namespace snowball { -namespace Syntax { - -class Visitor : public SrcObject { - public: - Visitor(const SourceInfo* srci) : SrcObject(srci) {}; - virtual void visitGlobal(std::vector); - -#include "../../defs/accepts.def" -}; - -} // namespace Syntax -} // namespace snowball - -#undef ACCEPT -#endif // __SNOWBALL_AST_VISITOR_H_ diff --git a/src/builder/linker/Linker.h b/src/builder/linker/Linker.h deleted file mode 100644 index 94fde837..00000000 --- a/src/builder/linker/Linker.h +++ /dev/null @@ -1,109 +0,0 @@ -#include "../../compiler.h" -#include - -#ifndef __SNOWBALL_CODEGEN_LINKER_H_ -#define __SNOWBALL_CODEGEN_LINKER_H_ - -namespace snowball { -namespace linker { - -/** - * @class Linker - * @brief The Linker class provides functionality for linking object files and generating executables. - * - * The Linker class takes in a list of object files, linker options, and an output file name, - * and performs the linking process to create an executable file. It utilizes an internal - * vector to store the linker arguments. - */ -class Linker { - /// @brief Vector to store the linker arguments. - std::vector linkerArgs; - /// @brief The path to the linker executable. - std::string ldPath; - /// @brief Vector to store the names of linked libraries. - std::vector linkedLibraries; - /// @brief Pointer to the global context. - GlobalContext ctx; - /// @brief The target triple. - llvm::Triple target; - /// @brief A list of rpaths to be added to the executable. -#ifdef __APPLE__ - std::vector rpaths = { - "@executable_path/../lib", "@executable_path/../Frameworks", "/usr/local/lib", "/usr/lib" - }; -#else - std::vector rpaths = { - "/usr/local/lib", "/usr/lib", "/usr/lib/x86_64-linux-gnu", "/lib/x86_64-linux-gnu", "/lib" - }; -#endif - - public: - /** - * @brief Default constructor for the Linker class. - * - * This constructor initializes the Linker object with default settings. - */ - Linker(GlobalContext ctx, std::string ldPath = LD_PATH); - /** - * @brief Default destructor for the Linker class. - * - * The destructor is set to default, and it will be automatically called when the - * Linker object goes out of scope or is explicitly deleted. - */ - ~Linker() = default; - /** - * @brief Links the given object files and generates an executable. - * - * This function takes in a vector of object files, an output file name, and - * a vector of additional linker arguments. It then performs the linking process - * using the provided arguments and generates an executable with the specified output name. - * - * @param[in] files A reference to a vector of strings containing the paths to object files. - * @param[in] output A reference to a string representing the desired output file name. - * @param[in] args A reference to a vector of strings containing additional linker arguments. - */ - int link(std::string& input, std::string& output, std::vector& args); - /** - * @brief Adds a library to the list of linked libraries. - * - * This function takes in a string representing the name of a library and adds it to the - * list of linked libraries. The library name should not include the "lib" prefix or the - * file extension. - * - * @param[in] library A reference to a string representing the name of the library. - */ - void addLibrary(std::string& library); - /** - * @brief It returns the name for a shared library. - */ - static std::string getSharedLibraryName(std::string& library); - - private: - /** - * @brief Constructs the linker arguments based on input, output, and additional arguments. - * - * This private function constructs the linker arguments based on the provided input, - * output file name, and additional arguments. The resulting linker arguments are stored - * in the internal linkerArgs vector. - * - * @param[in] input A reference to a string representing the input file name. - * @param[in] output A reference to a string representing the output file name. - * @param[in] args A reference to a vector of strings containing additional linker arguments. - */ - void constructLinkerArgs(std::string& input, std::string& output, std::vector& args); - /** - * @brief Transform an llvm triple into a platform triple. - * - */ - std::string getPlatformTriple(); -}; - -// check if we are in a supported platform -#if !(defined(__linux__) || defined(__unix__) || defined(__unix) || defined(__APPLE__)) -#error "Unsupported platform for linking!" -#endif - -} // namespace linker -} // namespace snowball - -#endif // __SNOWBALL_CODEGEN_LINKER_H_ \ No newline at end of file diff --git a/src/builder/linker/common/ld.cc b/src/builder/linker/common/ld.cc deleted file mode 100644 index 6543473d..00000000 --- a/src/builder/linker/common/ld.cc +++ /dev/null @@ -1,46 +0,0 @@ -#include "../../../constants.h" -#include "../../../utils/utils.h" -#include "../Linker.h" - -#include - -namespace snowball { -namespace linker { - -Linker::Linker(GlobalContext ctx, std::string ldPath) : ctx(ctx), ldPath(ldPath) { - target = llvm::Triple(llvm::sys::getProcessTriple()); -} -void Linker::addLibrary(std::string& library) { linkedLibraries.push_back(library); } - -int Linker::link(std::string& input, std::string& output, std::vector& args) { - auto current = utils::get_lib_folder(); - rpaths.insert(rpaths.begin(), (current / ".." / "lib").string()); - constructLinkerArgs(input, output, args); - linkerArgs.insert(linkerArgs.begin(), ldPath); - DEBUG_CODEGEN("Invoking linker (" LD_PATH " with stdlib at " STATICLIB_DIR ")"); - DEBUG_CODEGEN("Linker command: %s", utils::join(linkerArgs.begin(), linkerArgs.end(), " ").c_str()); - int ldstatus = os::Driver::run(linkerArgs); - if (ldstatus) { throw SNError(LINKER_ERR, Logger::format("Linking with " LD_PATH " failed with code %d", ldstatus)); } -#if __APPLE__ - if (ctx.opt == app::Options::Optimization::OPTIMIZE_O0) os::Driver::run({"dsymutil", output}); -#endif - return EXIT_SUCCESS; -} - -std::string Linker::getPlatformTriple() { - switch (target.getArch()) { - case llvm::Triple::arm: - case llvm::Triple::thumb: return "arm-linux-gnueabi"; - case llvm::Triple::armeb: - case llvm::Triple::thumbeb: return "armeb-linux-gnueabi"; - case llvm::Triple::x86: return "i386-linux-gnu"; - case llvm::Triple::x86_64: return "x86_64-linux-gnu"; - case llvm::Triple::aarch64: return "aarch64-linux-gnu"; - case llvm::Triple::aarch64_be: return "aarch64_be-linux-gnu"; - default: return ""; - }; - return ""; -} - -} // namespace linker -} // namespace snowball diff --git a/src/builder/linker/linux/ld.cc b/src/builder/linker/linux/ld.cc deleted file mode 100644 index 43a1fdaa..00000000 --- a/src/builder/linker/linux/ld.cc +++ /dev/null @@ -1,131 +0,0 @@ -// only generate for linux -#if defined(__linux__) || defined(__gnu_linux__) || defined(__linux) || defined(__LINUX__) - -#include "../../../ast/errors/error.h" -#include "../../../constants.h" -#include "../Linker.h" -#include - -#include -namespace fs = std::filesystem; - -namespace snowball { -namespace linker { - -void Linker::constructLinkerArgs(std::string& input, std::string& output, std::vector& args) { - const bool isIAMCU = target.isOSIAMCU(); - linkerArgs.clear(); - if (ctx.isDynamic) { - // linkerArgs.push_back("-pic"); - linkerArgs.push_back("--export-dynamic"); - linkerArgs.push_back("-m"); - linkerArgs.push_back("elf_x86_64"); - // linkerArgs.push_back("-Bdynamic"); - } else { - linkerArgs.push_back("-static"); - linkerArgs.push_back("-pie"); - linkerArgs.push_back("--no-dynamic-linker"); - linkerArgs.push_back("-z"); - linkerArgs.push_back("text"); - } - if (ctx.withStd) { - // TODO: check if this works for all platforms - linkerArgs.push_back("-dynamic-linker"); - fs::path ld_linux_path; - void* ld_linux_handle = dlopen("ld-linux-x86-64.so.2", RTLD_LAZY); - if (!ld_linux_handle) { Syntax::E(FMT("Error getting library path: %s", dlerror())); } - Dl_info ld_linux_info; - if (dladdr(ld_linux_handle, &ld_linux_info)) { - ld_linux_path = ld_linux_info.dli_fname; - } else { - Syntax::E(FMT("Error getting library path: %s", dlerror())); - } - linkerArgs.push_back(ld_linux_path); - auto path = std::string("/usr") + PATH_SEPARATOR + _SNOWBALL_LIBRARY_OBJ; - auto triple = getPlatformTriple(); - assert(!triple.empty() && "Unsupported platform for linking!"); - if (!dlopen("crt1.o", RTLD_LAZY)) { - // dlopen returns `/crt1.o: only ET_DYN and ET_EXEC can be loaded` - // this is abusing that fact to get the absolute path - std::string err = dlerror(); - std::size_t delim = err.find(':'); - if (delim != std::string::npos) { - linkerArgs.push_back(err.substr(0, delim)); - } else { - Syntax::E(err); - } - } else { - Syntax::E("crt1.o was loaded as a shared library"); - } - if (!dlopen("crti.o", RTLD_LAZY)) { - // dlopen returns `/crt1.o: only ET_DYN and ET_EXEC can be loaded` - // this is abusing that fact to get the absolute path - std::string err = dlerror(); - std::size_t delim = err.find(':'); - if (delim != std::string::npos) { - linkerArgs.push_back(err.substr(0, delim)); - } else { - Syntax::E(err); - } - } else { - Syntax::E("crti.o was loaded as a shared library"); - } - if (!isIAMCU) { - if (!dlopen("crtn.o", RTLD_LAZY)) { - // dlopen returns `/crt1.o: only ET_DYN and ET_EXEC can be loaded` - // this is abusing that fact to get the absolute path - std::string err = dlerror(); - std::size_t delim = err.find(':'); - if (delim != std::string::npos) { - linkerArgs.push_back(err.substr(0, delim)); - } else { - Syntax::E(err); - } - } else { - Syntax::E("crtn.o was loaded as a shared library"); - } - } else { - // TODO: add crtbegin.o and crtend.o - } - } - linkerArgs.push_back(input); - if (ctx.isThreaded) linkerArgs.push_back("-lpthread"); - for (auto& arg : args) linkerArgs.push_back(arg); - // TODO: should this be with ctc->withStd? - linkerArgs.push_back("--eh-frame-hdr"); - if (ctx.withStd) { - for (auto llvmArg : utils::split(LLVM_LDFLAGS, " ")) { linkerArgs.push_back(llvmArg); } - } - if (!ctx.isDynamic) linkerArgs.push_back("-static"); - for (auto& rpath : rpaths) linkerArgs.push_back("--rpath=" + rpath); - for (auto& lib : linkedLibraries) { - linkerArgs.push_back("-l:" + lib); - DEBUG_CODEGEN("Linking library: %s", lib.c_str()); - } - if (ctx.withCXXStd) { - auto libs = utils::get_lib_folder() / ".." / _SNOWBALL_LIBRARY_OBJ; - linkerArgs.push_back("-L/usr/lib/../lib64"); - linkerArgs.push_back("-L/lib/../lib64"); - linkerArgs.push_back("-L/usr/bin/../lib/gcc/x86_64-linux-gnu/12"); - linkerArgs.push_back("-L/usr/lib/x86_64-linux-gnu"); - linkerArgs.push_back("-L/lib/x86_64-linux-gnu"); - linkerArgs.push_back("-L/lib"); - linkerArgs.push_back("-L/usr/lib"); - linkerArgs.push_back("-lsnowballrt"); - linkerArgs.push_back("-lm"); - linkerArgs.push_back("-lc"); - linkerArgs.push_back("-L" + libs.string()); - } - linkerArgs.push_back("-o"); - linkerArgs.push_back(output); -#if _SNOWBALL_CODEGEN_DEBUG - linkerArgs.push_back("--verbose"); -#endif -} - -std::string Linker::getSharedLibraryName(std::string& library) { return library + ".so"; } - -} // namespace linker -} // namespace snowball - -#endif diff --git a/src/builder/linker/macos/ld.cc b/src/builder/linker/macos/ld.cc deleted file mode 100644 index 64da4202..00000000 --- a/src/builder/linker/macos/ld.cc +++ /dev/null @@ -1,55 +0,0 @@ -// only generate for macos -#if defined(__APPLE__) || defined(__MACH__) || defined(__DARWIN__) || defined(__darwin__) || defined(__APPLE_CC__) || \ - defined(__OSX__) || defined(__MACH) || defined(__MACOS__) - -#include "../../../constants.h" -#include "../Linker.h" - -#include -namespace fs = std::filesystem; - -namespace snowball { -namespace linker { - -void Linker::constructLinkerArgs(std::string& input, std::string& output, std::vector& args) { - const bool isIAMCU = target.isOSIAMCU(); - linkerArgs.clear(); - for (auto& lib : linkedLibraries) { - linkerArgs.push_back("-l:" + lib); - DEBUG_CODEGEN("Linking library: %s", lib.c_str()); - } - if (ctx.withCXXStd) { - auto libs = utils::get_lib_folder() / ".." / _SNOWBALL_LIBRARY_OBJ; - linkerArgs.push_back("-L" + libs.string()); - linkerArgs.push_back("-lsnowballrt"); - } - linkerArgs.push_back(input); - for (auto& arg : args) linkerArgs.push_back(arg); - if (ctx.withStd) { - for (auto llvmArg : utils::split(LLVM_LDFLAGS, " ")) { linkerArgs.push_back(llvmArg); } - } - if (!ctx.isDynamic) - linkerArgs.push_back("-static"); - linkerArgs.push_back("-arch"); - // TODO: check this out: https://codebrowser.dev/llvm/clang/lib/Driver/ToolChain.cpp.html - linkerArgs.push_back(target.getArchName().str()); - linkerArgs.push_back("-L."); - linkerArgs.push_back("-L/opt/homebrew/lib"); - // TODO: we might not find it and we will need to search for System.B - for (auto& rpath : rpaths) { - linkerArgs.push_back("-L" + rpath); - linkerArgs.push_back("-Wl,-rpath," + rpath); - } - linkerArgs.push_back("-o"); - linkerArgs.push_back(output); -#if _SNOWBALL_CODEGEN_DEBUG - linkerArgs.push_back("--verbose"); -#endif -} - -std::string Linker::getSharedLibraryName(std::string& library) { return library + ".dylib"; } - -} // namespace linker -} // namespace snowball - -#endif \ No newline at end of file diff --git a/src/builder/llvm/DIHelpers.cc b/src/builder/llvm/DIHelpers.cc deleted file mode 100644 index e3649ac8..00000000 --- a/src/builder/llvm/DIHelpers.cc +++ /dev/null @@ -1,167 +0,0 @@ - -#include "../../ast/errors/error.h" -#include "../../ast/types/Interface.h" -#include "../../ast/types/EnumType.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" -#include "../../visitors/Transformer.h" -#include "../../../runtime/libs/exceptions.h" -#include -#include -#include -#include - -using namespace snowball::utils; - -namespace snowball { -namespace codegen { - -llvm::DISubprogram* LLVMBuilder::getDISubprogramForFunc(ir::Func* x) { - const auto& srcInfo = x->getDBGInfo(); - auto file = dbg.getFile(srcInfo->getSourceInfo()->getPath()); - auto derivedType = llvm::cast(getDIType(x->getType())); - auto subroutineType = llvm::cast(derivedType->getRawBaseType()); - std::string baseName = x->getNiceName(); - llvm::DISubprogram* subprogram = dbg.builder->createFunction( - file, - baseName, - x->getMangle(), - file, - srcInfo->line, - llvm::cast(subroutineType), - /*ScopeLine=*/0, - llvm::DINode::FlagPrototyped, - llvm::DISubprogram::toSPFlags( - /*IsLocalToUnit=*/true, - /*IsDefinition=*/true, - /*IsOptimized=*/!dbg.debug - ) - ); - return subprogram; -} - -llvm::DIType* LLVMBuilder::getDIType(types::Type* ty) { - auto llvmType = getLLVMType(ty); - auto layout = module->getDataLayout(); - if (auto intTy = cast(ty)) { - return dbg.builder->createBasicType(ty->getName(), llvmType->getPrimitiveSizeInBits(), - intTy->isSigned() ? llvm::dwarf::DW_ATE_signed : llvm::dwarf::DW_ATE_unsigned); - } else if (is(ty)) { - return dbg.builder->createBasicType(ty->getName(), llvmType->getPrimitiveSizeInBits(), llvm::dwarf::DW_ATE_float); - } else if (cast(ty)) { - return nullptr; - } else if (auto x = cast(ty)) { - auto type = getDIType(x->getPointedType()); - return dbg.builder->createReferenceType(llvm::dwarf::DW_TAG_reference_type, type, x->sizeOf() * 8); - } else if (auto x = cast(ty)) { - auto type = getDIType(x->getPointedType()); - return dbg.builder->createPointerType(type, ty->sizeOf() * 8, ty->alignmentOf(), std::nullopt, ty->getPrettyName()); - } else if (auto f = Syntax::Transformer::getFunctionType(ty)) { - std::vector argTypes = {getDIType(f->getRetType())}; - for (auto argType : f->getArgs()) { argTypes.push_back(getDIType(argType)); } - auto subroutineType = dbg.builder->createSubroutineType(llvm::MDTuple::get(*context, argTypes)); - return dbg.builder->createPointerType(subroutineType, ty->sizeOf()); - } else if (auto c = cast(ty)) { - return getDIType(c->getBaseType()); - } else if (auto e = cast(ty)) { - auto dbgInfo = e->getDBGInfo(); - auto file = dbg.getFile(dbgInfo->getSourceInfo()->getPath()); - int enumIndex = 0; - auto debugType = dbg.builder->createEnumerationType( - file, - e->getPrettyName(), - file, - dbgInfo->line, - 8, - ty->alignmentOf(), - dbg.builder->getOrCreateArray(vector_iterate( - e->getFields(), - [&](types::EnumType::EnumField t) { - return dbg.builder->createEnumerator(t.name, enumIndex++); - } - )), - nullptr - ); - return debugType; - } else if (auto c = cast(ty)) { - auto asDefinedType = utils::cast(c); - auto asInterfaceType = utils::cast(c); - // TODO: add "VTableHolder" as argument - auto dbgInfo = c->getDBGInfo(); - auto file = dbg.getFile(dbgInfo->getSourceInfo()->getPath()); - std::vector generatedFields; - llvm::DICompositeType* debugType; - auto structLayout = layout.getStructLayout(llvm::cast(llvmType)); - int fieldIndex = (-1) + c->hasVtable; - if (asDefinedType) { - generatedFields = vector_iterate( - asDefinedType->getFields(), - [&](types::DefinedType::ClassField * t) { - fieldIndex++; - return dbg.builder->createMemberType( - nullptr, - t->name, - file, - dbgInfo->line, - layout.getTypeAllocSizeInBits(getLLVMType(t->type)), - 0, - structLayout->getElementOffsetInBits(fieldIndex), - llvm::DINode::FlagZero, - getDIType(t->type) - ); - } - ); - } else if (asInterfaceType) { - generatedFields = vector_iterate( - asInterfaceType->getFields(), - [&](types::InterfaceType::Member * t) { - fieldIndex++; - return dbg.builder->createMemberType( - nullptr, - t->name, - file, - dbgInfo->line, - layout.getTypeAllocSizeInBits(getLLVMType(t->type)), - 0, - structLayout->getElementOffsetInBits(fieldIndex), - llvm::DINode::FlagZero, - getDIType(t->type) - ); - } - ); - } else { - Syntax::E(FMT("Undefined fields type! (dbg) ('%s')", ty->getName().c_str())); - } - llvm::DIType* parentDIType = nullptr; - if (asDefinedType) - if (auto p = asDefinedType->getParent()) { parentDIType = getDIType(p); } - // TODO: create struct type if it's a struct - debugType = dbg.builder->createStructType( - file, - c->getPrettyName(), - file, - dbgInfo->line, - c->sizeOf() * 8, - 0, - llvm::DINode::FlagZero, - parentDIType, - dbg.builder->getOrCreateArray(generatedFields), - 0, - c->hasVtable ? - dbg.builder->createPointerType( - dbg.builder->createBasicType("void", 8, llvm::dwarf::DW_ATE_signed), - 8, - 0 - ) : nullptr, - c->getUUID() - ); - return debugType; - } else { - Syntax::E(FMT("Undefined type! (dbg) ('%s')", ty->getName().c_str())); - } - assert(false); - return nullptr; // to avoid warnings -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/LLVMBuilder.cc b/src/builder/llvm/LLVMBuilder.cc deleted file mode 100644 index 0ed82e47..00000000 --- a/src/builder/llvm/LLVMBuilder.cc +++ /dev/null @@ -1,306 +0,0 @@ - -#include "LLVMBuilder.h" - -#include "../../errors.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace snowball { -using namespace utils; - -namespace codegen { - -llvm::Value* LLVMBuilder::build(ir::Value* v) { - ctx->doNotLoadInMemory = false; - setDebugInfoLoc(v); - v->visit(this); - return this->value; -} - -llvm::Value* LLVMBuilder::load(llvm::Value* v, types::Type* ty) { - auto llvmType = getLLVMType(ty); - // TODO: not sure about global variable - if (ctx->doNotLoadInMemory || (llvm::isa(v) && !llvm::isa(v))) { - ctx->doNotLoadInMemory = false; - return v; - } - // TODO: not sure about alloca - // We don't need to load a value if it's not an alloca instruction. - // because this reference could from a function call. - // example: malloc(10); // do not load - // if (llvmType->isPointerTy() && llvm::isa(v)) - // return v; - if (v->getType()->isPointerTy()) return builder->CreateLoad(llvmType, v, ".ptr-load"); - return v; -} - -LLVMBuilder::LLVMBuilder( - std::shared_ptr mod, app::Options::Optimization optimizationLevel, bool testMode, bool benchMode -) - : iModule(mod) { - ctx->testMode = testMode; - ctx->benchmarkMode = benchMode; - ctx->optimizationLevel = optimizationLevel; - dbg.debug = ctx->optimizationLevel == app::Options::Optimization::OPTIMIZE_O0; - llvm::InitializeAllTargetInfos(); - llvm::InitializeAllTargets(); - llvm::InitializeAllTargetMCs(); - llvm::InitializeAllAsmParsers(); - llvm::InitializeAllAsmPrinters(); - llvm::InitializeNativeTarget(); - llvm::InitializeNativeTargetAsmPrinter(); - llvm::InitializeNativeTargetAsmParser(); - // Initialize passes - auto& registry = *llvm::PassRegistry::getPassRegistry(); - llvm::initializeCore(registry); - llvm::initializeScalarOpts(registry); - llvm::initializeVectorization(registry); - llvm::initializeIPO(registry); - llvm::initializeAnalysis(registry); - llvm::initializeTransformUtils(registry); - llvm::initializeInstCombine(registry); - llvm::initializeXRayInstrumentationPass(registry); - llvm::initializeTarget(registry); - llvm::initializeExpandMemCmpPassPass(registry); - llvm::initializeScalarizeMaskedMemIntrinLegacyPassPass(registry); - llvm::initializeSelectOptimizePass(registry); - llvm::initializeCodeGenPreparePass(registry); - llvm::initializeAtomicExpandPass(registry); - llvm::initializeMergeICmpsLegacyPassPass(registry); - llvm::initializeWinEHPreparePass(registry); - llvm::initializeDwarfEHPrepareLegacyPassPass(registry); - llvm::initializeSafeStackLegacyPassPass(registry); - llvm::initializeSjLjEHPreparePass(registry); - llvm::initializePreISelIntrinsicLoweringLegacyPassPass(registry); - llvm::initializeGlobalMergePass(registry); - llvm::initializeIndirectBrExpandPassPass(registry); - llvm::initializeInterleavedLoadCombinePass(registry); - llvm::initializeInterleavedAccessPass(registry); - llvm::initializeUnreachableBlockElimLegacyPassPass(registry); - llvm::initializeExpandReductionsPass(registry); - llvm::initializeExpandVectorPredicationPass(registry); - llvm::initializeWasmEHPreparePass(registry); - llvm::initializeWriteBitcodePassPass(registry); - llvm::initializeHardwareLoopsPass(registry); - llvm::initializeReplaceWithVeclibLegacyPass(registry); - llvm::initializeTypePromotionLegacyPass(registry); - newContext(); - module = newModule(); -} - -std::unique_ptr LLVMBuilder::newModule() { - auto m = std::make_unique("snowball compiled project", *context); - auto engine = llvm::EngineBuilder(); - target = engine.selectTarget(); - m->setDataLayout(target->createDataLayout()); - m->setTargetTriple(target->getTargetTriple().str()); - builder = std::make_unique>(*context); - auto srcInfo = iModule->getSourceInfo(); - m->setSourceFileName(srcInfo->getPath()); - // debug info setup - dbg.builder = std::make_unique(*m); - llvm::DIFile* file = dbg.getFile(srcInfo->getPath()); - dbg.unit = dbg.builder->createCompileUnit( - llvm::dwarf::DW_LANG_C_plus_plus, - file, - ("Snowball version " _SNOWBALL_VERSION), - !dbg.debug, - {}, - /*RV=*/0 - ); - m->addModuleFlag(llvm::Module::Warning, "Debug Info Version", llvm::DEBUG_METADATA_VERSION); - m->addModuleFlag(llvm::Module::Warning, "Snowball Compiler ID", _SNOWBALL_VERSION_NUMBER); - m->addModuleFlag( - llvm::Module::Warning, - "Snowball Compiler Version", - llvm::ConstantDataArray::getString(*context, _SNOWBALL_VERSION, true) - ); - // darwin only supports dwarf2 - if (llvm::Triple(m->getTargetTriple()).isOSDarwin()) { m->addModuleFlag(llvm::Module::Warning, "Dwarf Version", 2); } - return m; -} - -void LLVMBuilder::newContext() { - context = std::make_unique(); - // context->setOpaquePointers(false); -} - -llvm::DIFile* LLVMBuilder::DebugInfo::getFile(const std::string& path) { - std::string filename; - std::string directory; - auto pos = path.find_last_of("/"); - if (pos != std::string::npos) { - filename = path.substr(pos + 1); - directory = path.substr(0, pos); - } else { - filename = path; - directory = "."; - } - return builder->createFile(filename, directory); -} - -void LLVMBuilder::dump() { this->print(llvm::errs()); } -void LLVMBuilder::print(llvm::raw_fd_ostream& s) { module->print(s, nullptr); } - -#define ITERATE_FUNCTIONS for (auto fn = functions.begin(); fn != functions.end(); ++fn) -#define ITERATE_RFUNCTIONS for (auto fn = functions.rbegin(); fn != functions.rend(); ++fn) -void LLVMBuilder::codegen() { - auto generateModule = [&](std::shared_ptr m, bool build) { - // reset context - ctx->doNotLoadInMemory = false; - this->iModule = m; - // Generate the functions from the end to the front. - auto functions = m->getFunctions(); - if (!build) { - // Iterate every function with a reversed iterator. - // This first loop will declare all of the functions - // to the module, it does not matter whether they are - // bodied or not. - ITERATE_FUNCTIONS { visit(fn->get()); } - } else { - // Generate all the variables defined in this module. - for (auto v : m->getVariables()) { addGlobalVariable(v); } - // Terminate the global ctor if exists - if (auto x = getGlobalCTOR(false)) { - auto& ctorBody = x->getEntryBlock(); - builder->SetInsertPoint(&ctorBody); - builder->CreateRetVoid(); - } - // This second loop will generate all the functions that - // are bodied. We do 2 loops in order to prevent any weird - // situation when a function calls an undefined function that - // has not been generated yet. - ITERATE_RFUNCTIONS { - auto f = fn->get(); - if (!f->isDeclaration() && !f->hasAttribute(Attributes::BUILTIN)) { - auto llvmFn = funcs.at(f->getId()); - if (utils::is(f->getRetTy())) { - auto bytes = f->getRetTy()->sizeOf(); - auto dereferenceable = llvm::Attribute::get(*context, llvm::Attribute::Dereferenceable, bytes); - auto noundef = llvm::Attribute::get(*context, llvm::Attribute::NoUndef); - auto aligment = llvm::Attribute::get(*context, llvm::Attribute::Alignment, 8); - llvmFn->addRetAttr(dereferenceable); - llvmFn->addRetAttr(noundef); - llvmFn->addRetAttr(aligment); - } - if (f->hasAttribute(Attributes::LLVM_FUNC)) { - auto old = buildLLVMFunction(llvmFn, f); - funcs.at(f->getId()) = old; - } else { - buildBodiedFunction(llvmFn, f); - setPersonalityFunction(llvmFn); - std::string module_error_string; - llvm::raw_string_ostream module_error_stream(module_error_string); - llvm::verifyFunction(*llvmFn, &module_error_stream); - if (!module_error_string.empty()) { -#ifdef _SNOWBALL_BYTECODE_DEBUG - dump(); -#endif - throw SNError(Error::LLVM_INTERNAL, module_error_string); - } - } - } - } - } - }; - auto mainModule = utils::dyn_cast(iModule); - assert(mainModule); -#define INIT_MODULES(build) \ - for (auto m : mainModule->getModules()) generateModule(m, build); \ - generateModule(mainModule, build); - for (const auto& m : mainModule->getModules()) { - ctx->typeInfo.insert(m->typeInformation.begin(), m->typeInformation.end()); - } - ctx->typeInfo.insert(mainModule->typeInformation.begin(), mainModule->typeInformation.end()); - for (const auto& ty : ctx->typeInfo) { - auto t = ty.second.get(); - if (auto c = utils::cast(t)) { - auto& staticFields = c->getStaticFields(); - for (auto& f : staticFields) { - addGlobalVariable(f, c); - } - } - } - INIT_MODULES(false); // Create function declarations - INIT_MODULES(true); // Create function bodies - initializeRuntime(); - dbg.builder->finalize(); - DEBUG_CODEGEN("Finished codegen, proceeding to verify module"); - std::string module_error_string; - llvm::raw_string_ostream module_error_stream(module_error_string); - llvm::verifyModule(*module.get(), &module_error_stream); - if (!module_error_string.empty()) { -#ifdef _SNOWBALL_BYTECODE_DEBUG - dump(); -#endif - throw SNError(Error::LLVM_INTERNAL, module_error_string); - } - DEBUG_CODEGEN("Finished verifying module, proceeding to optimize module (if requested)"); -} -#undef LOOP_FUNCTIONS - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/LLVMBuilder.h b/src/builder/llvm/LLVMBuilder.h deleted file mode 100644 index 127db79d..00000000 --- a/src/builder/llvm/LLVMBuilder.h +++ /dev/null @@ -1,525 +0,0 @@ - -#include "../../../app/cli.h" -#include "../../ValueVisitor/Visitor.h" -#include "../../ast/types/DefinedType.h" -#include "../../ast/types/FunctionType.h" -#include "../../ast/types/Interface.h" -#include "../../ast/types/EnumType.h" -#include "../../ast/types/PointerType.h" -#include "../../ast/types/ReferenceType.h" -#include "../../ast/types/TypeAlias.h" -#include "../../ast/errors/error.h" -#include "../../ir/id.h" -#include "../../ir/module/MainModule.h" -#include "../../ir/values/Func.h" -#include "../../ir/values/ReferenceTo.h" -#include "../../ir/values/Value.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#ifndef __SNOWBALL_LLVM_BUILDER_H_ -#define __SNOWBALL_LLVM_BUILDER_H_ - -namespace snowball { -namespace codegen { - -namespace llvm_utils { -int typeIdxLookup(const std::string& name); -} // namespace llvm_utils - -using namespace llvm_utils; - -/** - * @brief Some context so that we can know - * where in the program we are located. - */ -class LLVMBuilderContext { - // Current function being generated - llvm::Function* currentFunction = nullptr; - // Current IR function being generated - ir::Func* currentIRFunction = nullptr; - - // All variables used around the program. - // note: all of the llvm values are actually - // "alloca" instructions. - std::map symbols; - // A map containing all the vtables for every single - // type. - std::map vtables; - // A container for all the vtable struct types. - std::map vtableType; - - public: - // A value used to return a struct from a function - bool retValueUsedFromArg = false; - // A value used to store a value into a variable - llvm::Value* callStoreValue = nullptr; - // A map of test functions containing their names - std::vector> tests; - // A map of benchmark functions containing their names - std::vector> benchmarks; - // If the module is compiled in test mode - bool testMode = false; - // If the module is compiled in benchmark mode - bool benchmarkMode = false; - /// @return Current function being generated - auto getCurrentFunction() { return currentFunction; } - /// @return Change the current function to a new one - void setCurrentFunction(llvm::Function* fn) { currentFunction = fn; } - /// @brief Reset the current function to a null pointer - void clearCurrentFunction() { currentFunction = nullptr; } - /// @return Current IR function being generated - auto getCurrentIRFunction() { return currentIRFunction; } - /// @return Change the current IR function to a new one - void setCurrentIRFunction(ir::Func* fn) { currentIRFunction = fn; } - /// @brief Reset the current IR function to a null pointer - void clearCurrentIRFunction() { currentIRFunction = nullptr; } - - /// @return A full list of symbols used around the program - auto& getAllSymbols() { return symbols; } - /// @return Add a new symbol to the symbol map - void addSymbol(ir::id_t i, llvm::Value* s) { symbols.emplace(i, s); } - /// @brief Get the corresponding symbol to an id - auto getSymbol(ir::id_t i) -> llvm::Value* { return symbols.at(i); } - /// @brief Clear the symbol table - void clearSymbols() { return symbols.clear(); } - /// @return Add a new vtable to the vtable map - void addVtable(ir::id_t i, llvm::GlobalVariable* s) { vtables.emplace(i, s); } - /// @brief Get the corresponding vtable to an id - auto getVtable(ir::id_t i) -> llvm::GlobalVariable* { - auto item = vtables.find(i); - return item == vtables.end() ? nullptr : item->second; - } - /// @return Add a new vtable to the vtable map - void addVtableTy(ir::id_t i, llvm::StructType* s) { vtableType.emplace(i, s); } - /// @brief Get the corresponding vtable to an id - auto getVtableTy(ir::id_t i) -> llvm::StructType* { - auto item = vtableType.find(i); - return item == vtableType.end() ? nullptr : item->second; - } - // TODO: add a function to clear functions, symbols, etc as cleanup - /// @brief A flag to avoid loading a value in memory - bool doNotLoadInMemory = false; - /// @brief Optimization level - app::Options::Optimization optimizationLevel = app::Options::Optimization::OPTIMIZE_O0; - // Type information about ALLLL the types being used - std::map> typeInfo; - /// @brief Type info for closures - struct ClosureContext { - std::vector variables; - llvm::Value* closure = nullptr; // Closure allocation - llvm::StructType* closureType = nullptr; - }; - /// @brief Closure map for all the closures - std::map closures; - /// @brief Loop information - struct { - // The continue block for the current loop - llvm::BasicBlock* continueBlock = nullptr; - // The break block for the current loop - llvm::BasicBlock* breakBlock = nullptr; - } loop; -}; - -/** - * An LLVM builder that will transform the internal - * representation of the program into a LLVM module. - * This module can then be compiled into many different - * things. - * @see https://llvm.org/docs/LangRef.html - */ -class LLVMBuilder : AcceptorExtend { - // A global map to keep track of all processed - // functions. - std::map funcs; - // Some sort of cache to prevent struct-like types - // from being generated over and over again. - std::map types; - // Internal module given by the internal representation - // of the program. - std::shared_ptr iModule; - // Context used all around the codegen process - std::unique_ptr ctx = std::make_unique(); - /** - * Struct containing all debug information - * tools needed. - */ - struct DebugInfo { - /// Current compilation unit - llvm::DICompileUnit* unit = nullptr; - /// Debug info builder - std::unique_ptr builder = nullptr; - // Debug flag - bool debug = false; - - // Create a new DIFile for llvm - llvm::DIFile* getFile(const std::string& path); - } dbg; - /** - * Helper struct containing all the llvm helper functions - * needed. This is used to avoid having to write a lot of - * boilerplate code. - * @see https://llvm.org/doxygen/classllvm_1_1IRBuilder.html - */ - struct { - /** - * Create a new llvm value. - * @return Created llvm value. - */ - template - static Inst* create(Args&&... args) { - return Inst::Create(std::forward(args)...); - } - /** - * Create a new llvm instruction. - * @return Created llvm struction. - */ - template - static Inst* insert(Args&&... args) { - return new Inst(std::forward(args)...); - } - } h; - /// Create a new alloca instruction - llvm::AllocaInst* createAlloca(llvm::Type* ty, std::string name = "") { - auto backupBlock = builder->GetInsertBlock(); - auto entryBlock = ctx->getCurrentFunction()->getEntryBlock().getTerminator(); - if (entryBlock) { - builder->SetInsertPoint(entryBlock); - } - auto alloca = builder->CreateAlloca(ty, nullptr, name); - builder->SetInsertPoint(backupBlock); - return alloca; - } - /// Information for each try-catch block. - struct TryCatchInfo { - /// The catch block - llvm::BasicBlock* catchBlock; - /// Catch route block - llvm::BasicBlock* catchRouteBlock; - /// All handlers for this try-catch block - std::vector handlers; - /// All catch variables for this try-catch block - std::vector> catchVars; - /// Stores the exception pad - llvm::Value* exceptionPad = nullptr; - }; - /// A stack containing all the try-catch blocks - std::vector tryCatchStack; - // LLVM IR module that acts as a top level container of - // all other LLVM Intermediate Representation (IR) objects - std::unique_ptr module; - // An unique pointer for an instruction builder. - std::unique_ptr> builder; - // LLVM context for the module - std::unique_ptr context; - // Last compiled (generated) value - llvm::Value* value; - // Target machine that the module will be compiled into - llvm::TargetMachine* target; - - public: - // Create a new instance of a llvm builder - LLVMBuilder( - std::shared_ptr mod, - app::Options::Optimization optimizationLevel = app::Options::Optimization::OPTIMIZE_O0, - bool testMode = false, - bool benchmarkMode = false - ); - /** - * @brief Dump the LLVM IR code to stdout. - * - * note: this must only be used for debug - * purposes. - * - * @see LLVMBuilder::print - */ - void dump(); - /** - * @brief Print the llvm IR module into a stream - */ - void print(llvm::raw_fd_ostream& s); - /** - * @brief get a type info struct type - */ - llvm::StructType* getTypeInfoType(); - /** - * @brief Start the codegen process - * - * Transform the value tree into a LLVM module - * that can then be compiled to many more things. - */ - void codegen() override; - /** - * @brief It executes the built in LLVM-IR optimization passes into - * the resultant module - * @note If the optimization level has been to '0', it will obiously - * will not execute those optimization passes - */ - void optimizeModule(); - /** - * @brief Compile the LLVM-IR code into an object file into the - * desired file. - */ - int emitObjectFile(std::string out, bool log, bool object = true); - /** - * @brief It builds a value as an expression. - * @param v Value to build - */ - llvm::Value* expr(ir::Value* v) { - this->ctx->doNotLoadInMemory = false; - return load(build(v), v->getType()); - } - - // mark: build functions - using AcceptorExtend::AcceptorExtend; - -#define VISIT(n) void visit(ir::n*) override; -#include "../../defs/visits.def" -#undef VISIT - - private: - /** - * @brief Create a new LLVM module - * @return An unique ptr to a new module - */ - std::unique_ptr newModule(); - /** - * @brief Utility function to create a new LLVM module context - * @return An unique pointer to the new context. - */ - void newContext(); - /** - * It loads a value if it's a pointer type. - * @param v Value to load - * @param ty Type to load - * @return llvm::Value* Resultant llvm value - */ - llvm::Value* load(llvm::Value* v, types::Type* ty); - /** - * Helper function to create a new function declaration - * - * @param fn Function value to generate - * @return llvm::Function* Resultant llvm function - */ - llvm::Function* createLLVMFunction(ir::Func* fn); - /** - * @brief It converts a value into a boolean value - */ - llvm::Value* toBool(llvm::Value* v, bool isSigned = false); - /** - * @brief Transform a built in snowball type - * to an llvm type. - */ - llvm::Type* getLLVMType(types::Type* t, bool translateVoid = false, bool ignoreMemorySize = false); - /** - * @brief Fetch the C stdlib printf function - */ - llvm::Function* getPrintfFunction(); - /** - * @brief A allocates a new object inside the LLVM IR code and cast - * it into the desired type. - */ - llvm::Value* allocateObject(types::DefinedType* ty); - /** - * @brief It creates a new struct type and a new constant struct - * value for a virtual table for @param ty - */ - llvm::GlobalVariable* createVirtualTable(types::BaseType* ty, llvm::StructType* vtableType); - /** - * @brief It generates intrinsic functions for a given function call. - * @param call The function call to generate the intrinsic function for. - * @return true if the intrinsic function was generated successfully, - */ - bool buildIntrinsic(ir::Call* call); - /** - * @brief It creates a new enum type and a new constant struct - * value for a virtual table for @param call - */ - llvm::Value* createEnumInit(ir::Call* call); - /** - * @brief Create a cond branch instruction that supports memory-sized types (i8 -> i1) - * @param cond Condition to branch - * @param thenBlock Block to branch if condition is true - * @param elseBlock Block to branch if condition is false - */ - void createCondBr(llvm::Value* cond, llvm::BasicBlock* thenBlock, llvm::BasicBlock* elseBlock); - /** - * @brief It creates a new enum field type - * @param ty The enum type - * @param field The enum field - */ - llvm::Type* createEnumFieldType(types::EnumType* ty, std::string field); - /** - * @brief Get llvm corresponding function type from an - * already generate snowball type. - */ - llvm::FunctionType* getLLVMFunctionType(types::FunctionType* fn, const ir::Func* func = nullptr); - /** - * @brief It creates a new vtable type for a given type. - */ - llvm::StructType* getVtableType(types::BaseType* ty); - /** - * @brief Generate a bodied function. Notes: bodied - * functions will have it's own scope meaning that we - * cant get any variables from this function after it - * has been generated. Also take note that this function - * does not declare a new one, it just declares it's body. - * thats why we need @param llvmFn as an already declared - * llvm function. - */ - llvm::Function* buildBodiedFunction(llvm::Function* llvmFn, ir::Func* fn); - /** - * @brief Set a "personality" function attached to a snowball - * generated function. - * - * Personality functions can be really helpful in order to - * implement an throw/catch exception runtime. - */ - void setPersonalityFunction(llvm::Function* func); - /** - * @brief It generates the test functions for the current module. - */ - void createTests(llvm::Function* mainFunction); - /** - * @brief It generates the benchmark functions for the current module. - */ - void createBenchmark(llvm::Function* mainFunction); - /** - * @brief It generates a function call or an invoke instruction - * depending on the current context. - */ - llvm::Value* createCall(llvm::FunctionType* ty, llvm::Value* callee, llvm::ArrayRef args); - /** - * @brief It generates the LLVM IR contents that the user has - * manually inserted by using "inline LLVM". - */ - llvm::Function* buildLLVMFunction(llvm::Function* llvmFn, ir::Func* fn); - /** - * @brief Builds an operator call. - * - * @param call The IR call instruction to build. - * @return true if the operator was built successfully, false - * otherwise. - * - * This function builds an operator call using the given IR call - * instruction. It returns true if the operator was built - * successfully and false otherwise. - */ - bool buildOperator(ir::Call* call); - /** - * @brief Get a wrapper for a function. Subprogram is considered - * also as a function description. - * - * from the llvm docs: - * > llvm::DISubprogram - * > This is a wrapper for a subprogram - */ - llvm::DISubprogram* getDISubprogramForFunc(ir::Func* fn); - /** - * Add a global variable to the program. - * - * This function adds the specified variable declaration to the - * global scope of the program. The variable can be accessed from - * any function within the program. - * - * @param var A shared pointer to the variable declaration to add. - * @param ty The type of the variable, or nullptr if the type should - */ - void addGlobalVariable(std::shared_ptr var, types::DefinedType* ty = nullptr); - /** - * Get the global constructor function. - * - * This function returns a pointer to the global constructor - * function for the current LLVM module. The global constructor is a - * special function that is called automatically when the program - * starts up, before the main function is called. The global - * constructor is typically used to initialize global variables or - * perform other initialization tasks that need to happen before the - * program can start running. - * - * @return A pointer to the global constructor function, or nullptr - * if no such function exists in the current LLVM module. - */ - llvm::Function* getGlobalCTOR(bool createIfNone = true); - /** - * @brief Get the "debug-information" equivalent of a snowball type. - * @param ty type to convert for the debugger. - */ - llvm::DIType* getDIType(types::Type* ty); - /** - * @brief LLVM wrapper to set a debug information - * location breakpoint - */ - void setDebugInfoLoc(ir::Value* v); - /** - * Initialize a variable with a constant struct value. - * @param var The variable to get the initializer for. - */ - void initializeVariable(llvm::Value* var, llvm::Type* ty, unsigned int size); - /** - * @brief Creates (if it does not exist) or fetches a function - * declaration used to allocate new bytes into memory. - * @example This can be used to create a new instance of an object. - */ - llvm::Function* getAllocaFunction(); - /** - * @brief Creates (if it does not exist) or fetches a function - * declaration used to throw an exception. - */ - std::pair getThrowFunction(); - /** - * @brief Creates a new instance of an exception. - */ - llvm::Value* createException(llvm::Value* val, types::Type* type); - /** - * @brief It initializes the runtime. This function is called - * before any other function is generated. - */ - void initializeRuntime(); - /** - * @brief Generate the current value given - * - * note: for the result of this function, `value` - * can be accessed. This used instead of a return - * value because c++ wants to make my life misserable. - * - * @note It may not return "value" if the value is a - * statement. - */ - llvm::Value* build(ir::Value* v); - /** - * @brief Fetch the base type of a pointer type. - * @param ty Pointer type to fetch the base type from. - * @note if the type is not a pointer type, it will return the - * same type. - */ - types::Type* getBasePointerType(types::Type* ty) { - if (auto x = utils::cast(ty)) return x->getBaseType(); - return ty; - } - /** - * @brief It creates a name that can be used to reference an exported - * function from another shared library. - */ - std::string getSharedLibraryName(std::string name); - /** - * @brief Lambda function context struct type information - */ - llvm::StructType* getLambdaContextType(); -}; - -} // namespace codegen -} // namespace snowball - -#endif // __SNOWBALL_LLVM_BUILDER_H_ diff --git a/src/builder/llvm/LLVMIRChunk.h b/src/builder/llvm/LLVMIRChunk.h deleted file mode 100644 index bcd19a6a..00000000 --- a/src/builder/llvm/LLVMIRChunk.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef __SNOWBALL_LLVM_IR_CHUNK_H_ -#define __SNOWBALL_LLVM_IR_CHUNK_H_ - -// we use it to avoid include loops -namespace snowball { -namespace Syntax { - -/// @brief A node representing a chunk of the LLVM IR block. -struct LLVMIRChunk { - enum { - LLCode, - TypeAccess - } type; - std::string code = ""; - types::Type* ty = nullptr; -}; - -} // namespace Syntax -} // namespace snowball - -#endif // __SNOWBALL_LLVM_IR_CHUNK_H_ \ No newline at end of file diff --git a/src/builder/llvm/addGlobalVariable.cc b/src/builder/llvm/addGlobalVariable.cc deleted file mode 100644 index d7e7dd0f..00000000 --- a/src/builder/llvm/addGlobalVariable.cc +++ /dev/null @@ -1,74 +0,0 @@ -#include "../../ir/values/Constants.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include - -namespace snowball { -namespace codegen { - -void LLVMBuilder::addGlobalVariable(std::shared_ptr var, types::DefinedType* parent) { - auto ty = getLLVMType(var->getType()); - std::string name; - if (parent) { - name = "const." + parent->getUUID() + ":" + utils::gen_random<32>() + ":" + var->getIdentifier(); - } else { - name = "gvar." + iModule->getUniqueName() + ":" + utils::gen_random<32>() + ":" + var->getIdentifier(); - } - auto srcInfo = var->getDBGInfo(); - auto file = dbg.getFile(var->getSourceInfo()->getPath()); - auto debugVar = dbg.builder->createGlobalVariableExpression( - dbg.unit, var->getIdentifier(), var->getIdentifier(), file, srcInfo->line, getDIType(var->getType()), - var->isExternDecl() - ); - if (var->isExternDecl()) { - auto gvar = new llvm::GlobalVariable( - /*Module=*/*module, - /*Type=*/ty, - /*isConstant=*/!var->getVariable()->isMutable(), - /*Linkage=*/llvm::GlobalValue::ExternalLinkage, - /*Initializer=*/nullptr, - /*Name=*/var->getIdentifier() - ); - ctx->addSymbol(var->getId(), gvar); - gvar->addDebugInfo(debugVar); - return; - } - if (utils::dyn_cast(var->getValue())) { - auto c = build(var->getValue().get()); - auto gvar = new llvm::GlobalVariable( - /*Module=*/*module, - /*Type=*/ty, - /*isConstant=*/!var->getVariable()->isMutable(), - /*Linkage=*/llvm::GlobalValue::InternalLinkage, - /*Initializer=*/llvm::cast(c), // has initializer, specified below - /*Name=*/name - ); - gvar->setDSOLocal(true); - ctx->addSymbol(var->getId(), gvar); - gvar->addDebugInfo(debugVar); - return; - } - auto ctor = getGlobalCTOR(); - auto& ctorBody = ctor->getEntryBlock(); - builder->SetInsertPoint(&ctorBody); - auto gvar = new llvm::GlobalVariable( - /*Module=*/*module, - /*Type=*/ty, - /*isConstant=*/0,// !var->getVariable()->isMutable(), note: this doesn't work because we are not fully detecting constant values (2 + 2 is not a constant) - /*Linkage=*/llvm::GlobalValue::InternalLinkage, - /*Initializer=*/llvm::Constant::getNullValue(ty), // has initializer, specified below - /*Name=*/name - ); - gvar->setDSOLocal(true); - ctx->addSymbol(var->getId(), gvar); - ctx->setCurrentFunction(ctor); - auto val = expr(var->getValue().get()); - builder->CreateStore(val, gvar); - ctx->clearCurrentFunction(); - gvar->addDebugInfo(debugVar); -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/allocateObject.cc b/src/builder/llvm/allocateObject.cc deleted file mode 100644 index be3ad9a8..00000000 --- a/src/builder/llvm/allocateObject.cc +++ /dev/null @@ -1,18 +0,0 @@ -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include - -namespace snowball { -namespace codegen { - -llvm::Value* LLVMBuilder::allocateObject(types::DefinedType* ty) { - auto llvmType = llvm::cast(getLLVMType(ty)); - llvm::Value* cast = createAlloca(llvmType, FMT(".alloc.%s", llvmType->getStructName())); - initializeVariable(cast, llvmType, ty->sizeOf()); - return cast; -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/buildArgument.cc b/src/builder/llvm/buildArgument.cc deleted file mode 100644 index 5d1b5cd4..00000000 --- a/src/builder/llvm/buildArgument.cc +++ /dev/null @@ -1,19 +0,0 @@ - -#include "../../ir/values/Argument.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include "varFetchImpl.h" - -#include -#include - -namespace snowball { -namespace codegen { - -void LLVMBuilder::visit(ir::Argument* variable) { - GET_VAR_IMPL(variable, value) -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/buildBlock.cc b/src/builder/llvm/buildBlock.cc deleted file mode 100644 index 009513a3..00000000 --- a/src/builder/llvm/buildBlock.cc +++ /dev/null @@ -1,17 +0,0 @@ - -#include "../../ir/values/Call.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include - -namespace snowball { -namespace codegen { - -void LLVMBuilder::visit(ir::Block* block) { - for (auto i : block->getBlock()) build(i.get()); -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/buildCall.cc b/src/builder/llvm/buildCall.cc deleted file mode 100644 index 020bfe8b..00000000 --- a/src/builder/llvm/buildCall.cc +++ /dev/null @@ -1,197 +0,0 @@ - -#include "../../ir/values/Call.h" -#include "../../ir/values/EnumInit.h" -#include "../../ir/values/Dereference.h" -#include "../../ir/values/ReferenceTo.h" -#include "../../services/OperatorService.h" -#include "../../services/ImportService.h" -#include "../../visitors/Transformer.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include -#include -#include - -namespace snowball { -namespace codegen { - -void LLVMBuilder::visit(ir::Call* call) { - bool isConstructor = false; - if (buildOperator(call)) return; // TODO: maybe jump to cleanup? - if (utils::is(call)) { - this->value = llvm::Constant::getNullValue(getLLVMType(call->getType())); - return; - } - if (utils::is(call)) { - auto instance = utils::cast(call); - if (instance->isConstantStruct()) { - auto instanceType = getLLVMType(instance->getType()); - assert(utils::cast(instance->getType()) && "Instance type is not a defined type!"); - auto alloca = ctx->callStoreValue ? ctx->callStoreValue : createAlloca(instanceType); - int i = 0; - for (auto& arg : instance->getArguments()) { - auto gep = builder->CreateStructGEP(instanceType, alloca, i++); - auto value = expr(arg.get()); - builder->CreateStore(value, gep); - } - this->value = builder->CreateLoad(instanceType, alloca); - return; - } - } else if (utils::is(call->getCallee().get())) { - this->value = createEnumInit(call); - return; - } else if (buildIntrinsic(call)) { - return; - } - auto calleeValue = call->getCallee(); - auto fnType = Syntax::Transformer::getFunctionType(calleeValue->getType()); - auto asFunction = utils::dyn_cast(calleeValue); - auto isLambda = !utils::is(calleeValue->getType()) ? utils::startsWith( - utils::cast(calleeValue->getType())->getUUID(), - services::ImportService::CORE_UUID + "std.Function") : false; - auto calleeType = getLLVMFunctionType(fnType, asFunction.get()); - llvm::Value* llvmCall = nullptr; - llvm::Value* allocatedValue = nullptr; - //setDebugInfoLoc(nullptr); - if ((fnType && utils::cast(fnType->getRetType())) || ctx->callStoreValue) { - if (ctx->callStoreValue) { - allocatedValue = ctx->callStoreValue; - ctx->callStoreValue = nullptr; - } else { - auto retType = fnType->getRetType(); - if (ctx->retValueUsedFromArg) { - allocatedValue = ctx->getCurrentFunction()->getArg(0); - ctx->retValueUsedFromArg = false; - } else { - // It's a function returning a type that's not a pointer - // We need to allocate the value - allocatedValue = createAlloca(getLLVMType(retType), ".ret-temp"); - } - } - } - auto callee = build(calleeValue.get()); - auto args = utils::vector_iterate, llvm::Value*>( - call->getArguments(), [this](std::shared_ptr arg) { return expr(arg.get()); } - ); - bool doNotAddAnonContext = false; - if (isLambda && asFunction && asFunction->usesParentScope()) { - auto closure = ctx->closures.at(ctx->getCurrentIRFunction()->getId()); - auto alloca = createAlloca(getLambdaContextType(), ".lambda-context"); - auto firstGep = builder->CreateStructGEP(getLambdaContextType(), alloca, 0); - builder->CreateStore(callee, firstGep); - auto gep = builder->CreateStructGEP(getLambdaContextType(), alloca, 1); - builder->CreateStore(closure.closure, gep); - args.insert(args.begin(), alloca); - doNotAddAnonContext = true; - } - if (allocatedValue) - args.insert(args.begin(), allocatedValue); - setDebugInfoLoc(nullptr); - if (asFunction != nullptr && asFunction->isConstructor()) { - auto instance = utils::cast(call); - isConstructor = true; - assert(instance); - assert(asFunction->hasParent()); - llvm::Value* object = allocatedValue; - if (instance->createdObject) { - object = build(instance->createdObject.get()); - } else if (!allocatedValue) { - auto classType = utils::cast(instance->getType()); - assert(classType && "Class type is not a defined type!"); - object = allocateObject(classType); - ctx->doNotLoadInMemory = true; - } - if (!allocatedValue) - args.insert(args.begin(), load(object, instance->getType()->getReferenceTo())); - setDebugInfoLoc(call); // TODO: - llvmCall = createCall(calleeType, callee, args); - this->value = object; - } else if (asFunction != nullptr && asFunction->inVirtualTable()) { - assert(asFunction->hasParent()); - auto index = asFunction->getVirtualIndex() + 2; // avoid class info - // note: allocatedValue != nullptr is because there are 2 possible cases: - // 1. The function returns a type that's not a pointer (meaning self is at index 1) - // 2. The function does not return a type that's not a pointer (meaning self is at index 0) - auto parentValue = args.at(/* self = */ allocatedValue != nullptr); - auto parentIR = call->getArguments().at(/* self = */ 0); - auto parentType = parentIR->getType(); - auto definedType = utils::cast(parentType); - if (auto x = utils::cast(parentType)) - definedType = utils::cast(x->getPointedType()); - else - assert(false && "Parent type is not a reference type!"); - assert(definedType && "Parent type is not a defined type!"); - getVtableType(definedType); // generate vtable type (if not generated yet) - auto vtableType = ctx->getVtableTy(definedType->getId()); - // vtable structure: - // class instance = { [0] = vtable, ... } - // vtable = { [size x ptr] } { [0] = fn1, [1] = fn2, ... } } - auto vtable = builder->CreateLoad(vtableType->getPointerTo(), parentValue); - auto fn = builder->CreateLoad( - calleeType->getPointerTo(), builder->CreateConstInBoundsGEP1_32(vtableType->getPointerTo(), vtable, index) - ); - builder->CreateAssumption(builder->CreateIsNotNull(fn)); - setDebugInfoLoc(call); - llvmCall = createCall(calleeType, (llvm::Function*) fn, args); - this->value = allocatedValue ? allocatedValue : llvmCall; - } else { - setDebugInfoLoc(call); - if (!isLambda) { - if (!llvm::isa(callee)) { - // we are calling a value instead of a direct function. - // this means we need to dereference the value first - // and then call it. - callee = load(callee, fnType); - } - llvmCall = createCall(calleeType, callee, args); - } else { - auto loadFunction = builder->CreateStructGEP(getLambdaContextType(), callee, 0); - auto loadFunctionValue = builder->CreateLoad(calleeType->getPointerTo(), loadFunction); - llvm::FunctionType* newType = nullptr; - if (!doNotAddAnonContext) { - if (allocatedValue) { - auto oldArgs = calleeType->params().vec(); - // second arg, first is the sret arg - oldArgs.insert(oldArgs.begin() + 1, getLambdaContextType()->getPointerTo()); - newType = llvm::FunctionType::get(calleeType->getReturnType(), oldArgs, calleeType->isVarArg()); - args.insert(args.begin() + 1, callee); - } else { - auto oldArgs = calleeType->params().vec(); - oldArgs.insert(oldArgs.begin(), getLambdaContextType()->getPointerTo()); - newType = llvm::FunctionType::get(calleeType->getReturnType(), oldArgs, calleeType->isVarArg()); - args.insert(args.begin(), callee); - } - } - if (asFunction && asFunction->isAnon()) { - newType = calleeType; // We've already added the context in getLLVMFunctionType - } - llvmCall = createCall(newType, loadFunctionValue, args); - } - this->value = allocatedValue ? allocatedValue : llvmCall; - } -#define SET_CALL_ATTRIBUTES(type) \ - if (llvm::isa(llvmCall)) { \ - auto call = llvm::cast(llvmCall); \ - auto calledFunction = call->getCalledFunction(); \ - bool retIsReference = false; \ - if (auto f = utils::dyn_cast(calleeValue); f && llvm::isa(callee)) { \ - auto valBackup = this->value; \ - retIsReference = utils::cast(f->getRetTy()) != nullptr; \ - calledFunction = llvm::cast(callee); \ - this->value = valBackup; \ - } \ - if (calledFunction) { \ - auto attrSet = calledFunction->getAttributes(); \ - if (retIsReference) { attrSet = attrSet.addRetAttribute(*context, llvm::Attribute::NonNull); } \ - call->setAttributes(attrSet); \ - } \ - } - SET_CALL_ATTRIBUTES(llvm::CallInst) - else SET_CALL_ATTRIBUTES(llvm::InvokeInst) else { assert(false); } - if (!allocatedValue && !isConstructor) ctx->doNotLoadInMemory = true; -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/buildCast.cc b/src/builder/llvm/buildCast.cc deleted file mode 100644 index 377923f0..00000000 --- a/src/builder/llvm/buildCast.cc +++ /dev/null @@ -1,75 +0,0 @@ - -#include "../../ir/values/Cast.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include - -#define IS_INTEGER(x) (utils::is(x)) -#define IS_FLOAT(x) (utils::is(x)) -#define IS_DEFINED(x) (utils::is(x) || utils::is(x)) - -namespace snowball { -namespace codegen { - -void LLVMBuilder::visit(ir::Cast* c) { - auto v = build(c->getExpr().get()); - auto vTy = c->getExpr()->getType(); - auto ty = c->getCastType(); - auto llvmType = getLLVMType(ty); - setDebugInfoLoc(c); - v = load(v, vTy); - if (v->getType() == llvmType) { - // note: this will always be true for pointer casting since llvm 15 (using opaque pointers) - this->ctx->doNotLoadInMemory = true; - this->value = v; - return; - } - // Check if both types are integers - if (IS_INTEGER(vTy) && IS_INTEGER(ty)) { // i[n] <-> i[n] - // utils::cast(vTy)->isSigned() - if (types::isIntType(vTy, 1)) { - // We use ZExt for bools because i1 can be considered as a sign, so - // it will be extended accross all the bits, for example if you cast - // i1 '1' to i8, you will get 111...1110, which is -1. - this->value = builder->CreateZExt(v, llvmType); - } else { - this->value = builder->CreateIntCast(v, llvmType, - utils::cast(ty)->isSigned()); // TODO: check if it's actually signed - } - } else if (IS_INTEGER(vTy) && IS_FLOAT(ty)) { // i[n] -> float - // cast signed integer to float - this->value = utils::cast(vTy)->isSigned() ? - builder->CreateSIToFP(v, llvmType) : - builder->CreateUIToFP(v, llvmType); - } else if (IS_FLOAT(vTy) && IS_INTEGER(ty)) { // float -> i[n] - // cast float to signed integer - this->value = utils::cast(ty)->isSigned() ? - builder->CreateFPToSI(v, llvmType) : - builder->CreateFPToUI(v, llvmType); - } else if (IS_FLOAT(ty) && IS_FLOAT(vTy)) { // float <-> float - // cast float to another float - this->value = builder->CreateFPCast(v, llvmType); - } else if (IS_INTEGER(vTy) && utils::cast(ty)) { // i[n] -> * - this->value = builder->CreateIntToPtr(v, llvmType); - this->ctx->doNotLoadInMemory = true; - } else if (IS_DEFINED(vTy) && IS_DEFINED(ty)) { - if (llvm::isa(v)) { - auto ptr = llvm::cast(v)->getPointerOperand(); - this->value = builder->CreateLoad(llvmType, ptr); - } else if (llvm::isa(v)) { - this->value = builder->CreateLoad(llvmType, v); - ctx->doNotLoadInMemory = true; - } else { - assert(!"Unreachable type case found!"); - } - } else { - assert(utils::cast(ty) || utils::cast(ty)); - this->value = builder->CreatePointerCast(v, llvmType); - this->ctx->doNotLoadInMemory = true; - } -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/buildConditional.cc b/src/builder/llvm/buildConditional.cc deleted file mode 100644 index 64aef65e..00000000 --- a/src/builder/llvm/buildConditional.cc +++ /dev/null @@ -1,32 +0,0 @@ -#include "../../ir/values/Conditional.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include - -#define CREATE_CONTINUE(x) \ - if (x || !builder->GetInsertBlock()->getTerminator()) { builder->CreateBr(continueBB); } - -namespace snowball { -namespace codegen { - -void LLVMBuilder::visit(ir::Conditional* c) { - auto parent = ctx->getCurrentFunction(); - assert(parent); - auto trueBB = h.create(*context, "cond.then", parent); - auto falseBB = h.create(*context, "cond.else", parent); - auto continueBB = h.create(*context, "cond.cont", parent); - auto cond = expr(c->getCondition().get()); - createCondBr(cond, trueBB, falseBB); - builder->SetInsertPoint(trueBB); - build(c->getBlock().get()); - CREATE_CONTINUE(false) - builder->SetInsertPoint(falseBB); - if (auto x = c->getElse()) { build(x.get()); } - CREATE_CONTINUE((c->getElse() == nullptr)) - builder->SetInsertPoint(continueBB); -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/buildConstant.cc b/src/builder/llvm/buildConstant.cc deleted file mode 100644 index 0334a589..00000000 --- a/src/builder/llvm/buildConstant.cc +++ /dev/null @@ -1,30 +0,0 @@ - -#include "../../ir/values/Constants.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include - -namespace snowball { -namespace codegen { - -void LLVMBuilder::visit(ir::StringValue* value) { - ctx->doNotLoadInMemory = true; - auto str = builder->CreateGlobalStringPtr(value->getConstantValue(), ".str__" + utils::gen_random<30>()); - auto arr = llvm::ArrayType::get(builder->getInt8Ty(), value->getConstantValue().size() + 1); - this->value = builder->CreateConstInBoundsGEP1_32(arr, str, 0); -} - -void LLVMBuilder::visit(ir::BooleanValue* value) { this->value = builder->getInt8(value->getConstantValue()); } - -void LLVMBuilder::visit(ir::CharValue* value) { this->value = builder->getInt8(value->getConstantValue()); } - -void LLVMBuilder::visit(ir::NumberValue* value) { this->value = llvm::ConstantInt::get(getLLVMType(value->getType()), value->getConstantValue()); } - -void LLVMBuilder::visit(ir::FloatValue* value) { - this->value = llvm::ConstantFP::get(builder->getDoubleTy(), value->getConstantValue()); -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/buildDereferenceTo.cc b/src/builder/llvm/buildDereferenceTo.cc deleted file mode 100644 index 0f86b9ea..00000000 --- a/src/builder/llvm/buildDereferenceTo.cc +++ /dev/null @@ -1,21 +0,0 @@ - -#include "../../ir/values/Dereference.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include - -namespace snowball { -namespace codegen { - -void LLVMBuilder::visit(ir::DereferenceTo* ref) { - auto val = ref->getValue(); - auto type = ref->getType(); - auto llvmVal = expr(val.get()); - this->value = builder->CreateLoad(getLLVMType(type), llvmVal, ".deref"); - ctx->doNotLoadInMemory = true; -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/buildEnumInit.cc b/src/builder/llvm/buildEnumInit.cc deleted file mode 100644 index 38a99b09..00000000 --- a/src/builder/llvm/buildEnumInit.cc +++ /dev/null @@ -1,17 +0,0 @@ - -#include "../../ir/values/EnumInit.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include - -namespace snowball { -namespace codegen { - -void LLVMBuilder::visit(ir::EnumInit* ref) { - Syntax::E("EnumInit should not be visited!"); -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/buildFunc.cc b/src/builder/llvm/buildFunc.cc deleted file mode 100644 index 4b19ef25..00000000 --- a/src/builder/llvm/buildFunc.cc +++ /dev/null @@ -1,268 +0,0 @@ - -#include "../../ast/errors/error.h" -#include "../../errors.h" -#include "../../ir/values/Argument.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include -#include - -namespace snowball { -namespace codegen { - -void LLVMBuilder::visit(ir::Func* func) { - if (func->hasAttribute(Attributes::BUILTIN) || func->hasAttribute(Attributes::INTRINSIC)) { - this->value = nullptr; - return; - } - if (auto it = funcs.find(func->getId()); it != funcs.end()) { - if (!func->isAnon()) - this->value = it->second; - else { - auto layout = module->getDataLayout(); - auto alloca = builder->CreateCall(getAllocaFunction(), {builder->getInt32(layout.getTypeAllocSize(getLambdaContextType()))}); - auto funcGep = builder->CreateStructGEP(getLambdaContextType(), alloca, 0, ".func.use.gep"); - builder->CreateStore(it->second, funcGep); - llvm::Value* body = nullptr; - if (func->isAnon() && func->usesParentScope()) { - auto closure = ctx->closures.at(ctx->getCurrentIRFunction()->getId()); - body = closure.closure; - } else { - body = llvm::Constant::getNullValue(builder->getPtrTy()); - } - auto bodyGep = builder->CreateStructGEP(getLambdaContextType(), alloca, 1, ".func.use.gep"); - builder->CreateStore(body, bodyGep); - this->value = alloca; - } - return; - } - setDebugInfoLoc(func); - auto fn = createLLVMFunction(func); - if (func->hasAttribute(Attributes::ALLOW_FOR_TEST)) { - fn->addFnAttr(llvm::Attribute::NoInline); - ctx->tests.push_back(std::make_pair(func, fn)); - } else if (func->hasAttribute(Attributes::ALLOW_FOR_BENCH)) { - fn->addFnAttr(llvm::Attribute::NoInline); - ctx->benchmarks.push_back(std::make_pair(func, fn)); - } - funcs.insert({func->getId(), fn}); - this->value = fn; -} - -llvm::Function* LLVMBuilder::buildBodiedFunction(llvm::Function* llvmFn, ir::Func* fn) { - ctx->setCurrentFunction(llvmFn); - ctx->setCurrentIRFunction(fn); - ctx->doNotLoadInMemory = false; - auto returnType = getLLVMType(fn->getRetTy()); - bool retIsArg = false; - bool anon = fn->isAnon(); - if (utils::is(fn->getRetTy())) { - returnType = builder->getVoidTy(); - retIsArg = true; - } - auto entry = h.create(*context, "entry", llvmFn); - auto body = h.create(*context, "body", llvmFn); - // mark: entry block - builder->SetInsertPoint(entry); - setDebugInfoLoc(nullptr); - auto fnArgs = fn->getArgs(); - auto llvmArgsIter = llvmFn->arg_begin() + retIsArg + anon; - auto selfArg = (llvm::Value*) nullptr; - auto selfArgVal = std::shared_ptr(nullptr); - llvm::StructType* closureType = nullptr; -#define CREATE_CLOSURE_TYPE() \ - if (closureType == nullptr) { \ - closureType = llvm::StructType::create(*context, "_closure." + fn->getMangle()); \ - } - for (auto arg : fn->getArgs()) { - if (arg.second->isUsedInLambda()) { - CREATE_CLOSURE_TYPE() - auto body = closureType->elements().vec(); - body.push_back(getLLVMType(arg.second->getType())); - closureType->setBody(body); - } - } - for (auto v : fn->getSymbols()) { - if (v->getVariable()->isUsedInLambda()) { - CREATE_CLOSURE_TYPE() - auto body = closureType->elements().vec(); - body.push_back(getLLVMType(v->getType())); - closureType->setBody(body); - } - } -#undef CREATE_CLOSURE_TYPE - if (closureType) { - auto layout = module->getDataLayout(); - auto alloca = builder->CreateCall(getAllocaFunction(), {builder->getInt32(layout.getTypeAllocSize(closureType))}); - auto defaultBody = module->getGlobalVariable("closure.__default_body"); - if (!defaultBody) { - auto bodyTy = llvm::StructType::create(*context, "_closure.__default_body"); - bodyTy->setBody({builder->getInt8PtrTy(), builder->getInt8PtrTy()}); - defaultBody = new llvm::GlobalVariable(*module, bodyTy, false, llvm::GlobalValue::ExternalLinkage, nullptr, - "closure.__default_body"); - defaultBody->setInitializer(llvm::ConstantStruct::get(bodyTy, { - llvm::ConstantPointerNull::get(builder->getInt8PtrTy()), - llvm::ConstantPointerNull::get(builder->getInt8PtrTy()), - })); - } - builder->CreateMemCpy(alloca, llvm::MaybeAlign(1), defaultBody, llvm::MaybeAlign(1), - layout.getTypeAllocSize(closureType)); - //auto structAlloca = createAlloca(closureType->getPointerTo()); - alloca->setDebugLoc(llvm::DILocation::get(*context, 0, 0, llvmFn->getSubprogram())); - //builder->CreateStore(alloca, structAlloca); - ctx->closures.insert({fn->getId(), LLVMBuilderContext::ClosureContext { - .variables = {}, - .closure = alloca, - .closureType = closureType, - }}); - } - for (auto arg : fn->getArgs()) { - if (arg.second->isUsedInLambda()) { - assert(closureType != nullptr); - auto& closure = ctx->closures.at(fn->getId()); - closure.variables.push_back(arg.second->getId()); - } - } - for (auto v : fn->getSymbols()) { - if (v->getVariable()->isUsedInLambda()) { - assert(closureType != nullptr); - auto& closure = ctx->closures.at(fn->getId()); - closure.variables.push_back(v->getVariable()->getId()); - } - } - for (auto varIter = fnArgs.begin(); varIter != fnArgs.end(); ++varIter) { - auto var = varIter->second; - llvm::Value* storage = nullptr; - if (var->isUsedInLambda()) { - auto closure = ctx->closures.at(fn->getId()); - auto index = std::distance( - closure.variables.begin(), - std::find_if( - closure.variables.begin(), - closure.variables.end(), - [&](auto v2) { return v2 == var->getId(); } - ) - ); - storage = builder->CreateStructGEP(closureType, closure.closure, index, "arg." + var->getIdentifier()); - } else { - storage = builder->CreateAlloca(getLLVMType(var->getType()), nullptr, "arg." + var->getIdentifier()); - ctx->addSymbol(var->getId(), storage); - } - builder->CreateStore(llvmArgsIter, storage); - if (var->getIdentifier() == "self" && var->getIndex() == 0) { - selfArg = storage; - selfArgVal = varIter->second; - } - // debug info - auto src = var->getSourceInfo(); - auto dbgInfo = var->getDBGInfo(); - auto file = dbg.getFile(src->getPath()); - auto scope = llvmFn->getSubprogram(); - auto debugVar = dbg.builder->createParameterVariable( - scope, - var->getIdentifier(), - var->getIndex() + 1 + retIsArg + anon, // lua vibes... :] - file, - dbgInfo->line, - getDIType(var->getType()), - dbg.debug, - llvm::DINode::FlagArtificial | llvm::DINode::FlagObjectPointer - ); - dbg.builder->insertDeclare( - storage, - debugVar, - dbg.builder->createExpression(), - llvm::DILocation::get(*context, dbgInfo->line, dbgInfo->pos.second, scope), - entry - ); - ++llvmArgsIter; - } - // Generate all the used variables - for (auto v : fn->getSymbols()) { - auto llvmType = getLLVMType(v->getType()); - llvm::Value* storage = nullptr; - if (v->getVariable()->isUsedInLambda()) { - auto closure = ctx->closures.at(fn->getId()); - auto index = std::distance( - closure.variables.begin(), - std::find_if( - closure.variables.begin(), - closure.variables.end(), - [v](auto v2) { return v2 == v->getVariable()->getId(); } - ) - ); - storage = builder->CreateStructGEP(closureType, closure.closure, index); - } else { - storage = builder->CreateAlloca(llvmType, nullptr, "var." + v->getIdentifier()); - ctx->addSymbol(v->getId(), storage); - } - if (utils::is(v->getType())) { - initializeVariable(storage, llvmType, v->getType()->sizeOf()); - } - } - if (fn->isConstructor()) { - assert(selfArg != nullptr); - assert(selfArgVal != nullptr); - auto self = selfArgVal->getType(); - if (utils::is(self)) { self = utils::cast(self)->getPointedType(); } - if (fn->superCall) { - auto superBranch = h.create(*context, "super-call", llvmFn); - builder->CreateBr(superBranch); - builder->SetInsertPoint(superBranch); - (void) build((ir::Value*) fn->superCall.get()); - } - assert(utils::is(self) && "Constructor self type is not a defined type!"); - if (ctx->typeInfo.at(utils::cast(self)->getId())->hasVtable) { - auto storeBranch = h.create(*context, "vtable-store", llvmFn); - builder->CreateBr(storeBranch); - builder->SetInsertPoint(storeBranch); - auto ty = utils::cast(self); - if (!ty) { Syntax::E("Constructor self type is not a defined type!"); } - auto llvmType = llvm::cast(getLLVMType(ty)); - auto cast = builder->CreateLoad(llvmType->getPointerTo(), selfArg); - llvm::Value* vtablePointer = nullptr; - if (auto v = ctx->getVtable(ty->getId())) { - vtablePointer = v; - } else { - auto t = ctx->getVtableTy(ty->getId()); - if (!t) { t = getVtableType(ty); } - vtablePointer = createVirtualTable(ty, t); - // insert vtable to the start of the type declaration - auto body = llvm::cast(llvmType)->elements().vec(); - llvm::cast(llvmType)->setBody(body); - } - auto vtableSpot = builder->CreateStructGEP(llvmType, cast, 0); - builder->CreateStore(vtablePointer, vtableSpot); - } - } - builder->CreateBr(body); - // mark: body block - builder->SetInsertPoint(body); - // Codegen for the current body - (void) build(fn->getBody().get()); - setDebugInfoLoc(nullptr); - // Create return type - if (!builder->GetInsertBlock()->getTerminator()) { - if (utils::cast(fn->getRetTy()) || utils::cast(fn->getRetTy())) { - builder->CreateRetVoid(); - } else if (fn->isConstructor()) { - // note: 0 should be always the "self" parameter - assert(!llvmFn->args().empty()); - builder->CreateRet(llvmFn->getArg(0)); - } else { - // TODO: warning - builder->CreateRet(llvm::Constant::getNullValue(returnType)); - } - } - // mark: clean up - ctx->clearCurrentFunction(); - ctx->clearCurrentIRFunction(); - auto DISubprogram = llvmFn->getSubprogram(); - dbg.builder->finalizeSubprogram(DISubprogram); - return llvmFn; -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/buildIndexExtract.cc b/src/builder/llvm/buildIndexExtract.cc deleted file mode 100644 index 6f0d3712..00000000 --- a/src/builder/llvm/buildIndexExtract.cc +++ /dev/null @@ -1,35 +0,0 @@ - -#include "../../ir/values/IndexExtract.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include - -namespace snowball { -namespace codegen { - -void LLVMBuilder::visit(ir::IndexExtract* index) { - auto indexValue = index->getValue(); - auto valueType = indexValue->getType(); - auto basedType = valueType; - if (auto x = utils::cast(basedType)) basedType = x->getPointedType(); - if (auto x = utils::cast(basedType)) basedType = x->getPointedType(); - auto defiendType = utils::cast(basedType); - assert(defiendType); - // We add "1" becasue index #0 is a pointer to the virtual - // table. - // TODO: support for structs without vtable. - // we do ctx->getVtableTy instead of x->hasVtable to avoid any issues when cloning - auto i = index->getIndex() + (ctx->typeInfo.find(defiendType->getId())->second->hasVtable); - auto leftArray = expr(indexValue.get()); - // if (utils::is(index->getType()) || utils::is(index->getType())) - // leftArray = builder->CreateLoad(getLLVMType(basedType), leftArray); - if ((!leftArray->getType()->isPointerTy()) && llvm::isa(leftArray)) - leftArray = llvm::cast(leftArray)->getPointerOperand(); - auto extract = builder->CreateStructGEP(getLLVMType(basedType), leftArray, i); - this->value = extract; -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/buildIntrinsic.cc b/src/builder/llvm/buildIntrinsic.cc deleted file mode 100644 index 6ca5bb86..00000000 --- a/src/builder/llvm/buildIntrinsic.cc +++ /dev/null @@ -1,52 +0,0 @@ - -#include "../../ir/values/IndexExtract.h" -#include "../../ir/values/Call.h" -#include "../../ir/values/Func.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include - -namespace snowball { -namespace codegen { - -bool LLVMBuilder::buildIntrinsic(ir::Call* call) { - auto callee = utils::dyn_cast(call->getCallee()); - if (!callee) return false; - if (!callee->hasAttribute(Attributes::INTRINSIC)) return false; - auto name = callee->getMangle(); - auto& args = call->getArguments(); - if (name == "write_via_move") { - assert(args.size() == 2); - auto ptr = expr(args[0].get()); - auto value = expr(args[1].get()); - //auto load = builder->CreateLoad(value->getType()->getPointerTo(), ptr); - builder->CreateStore(value, ptr); - } else if (name == "sn.memcpy") { - assert(args.size() == 3); - auto dest = expr(args[0].get()); - auto src = expr(args[1].get()); - auto count = expr(args[2].get()); - builder->CreateMemCpy(dest, llvm::MaybeAlign(1), src, llvm::MaybeAlign(1), count); - } else if (name == "sn.memmove") { - assert(args.size() == 3); - auto dest = expr(args[0].get()); - auto src = expr(args[1].get()); - auto count = expr(args[2].get()); - builder->CreateMemMove(dest, llvm::MaybeAlign(1), src, llvm::MaybeAlign(1), count); - } else if (name == "sn.memset") { - assert(args.size() == 3); - auto dest = expr(args[0].get()); - auto value = expr(args[1].get()); - auto count = expr(args[2].get()); - builder->CreateMemSet(dest, value, count, llvm::MaybeAlign(1)); - } else if (name == "sn.debugbreak") { - assert(args.size() == 0); - builder->CreateIntrinsic(llvm::Intrinsic::debugtrap, {}, {}); - } else Syntax::E(call, FMT("unknown intrinsic: %s", name.c_str())); - return true; -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/buildLLVMFunction.cc b/src/builder/llvm/buildLLVMFunction.cc deleted file mode 100644 index eef24bf1..00000000 --- a/src/builder/llvm/buildLLVMFunction.cc +++ /dev/null @@ -1,112 +0,0 @@ - -#include "../../errors.h" -#include "../../ir/values/Argument.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" -#include "LLVMIRChunk.h" - -#include -#include -#include -#include -#include -#include -#include - -namespace snowball { -namespace codegen { - -namespace { -void addTypeToModule(std::vector& addedTypes, llvm::Type* type, llvm::raw_string_ostream& buf) { - if (auto structType = llvm::dyn_cast(type)) { - if (std::find(addedTypes.begin(), addedTypes.end(), structType->getStructName().str()) != addedTypes.end()) { - return; - } - for (auto& elem : structType->elements()) { - addTypeToModule(addedTypes, elem, buf); - } - structType->print(buf); - buf << "\n"; - addedTypes.emplace_back(structType->getStructName().str()); - } -} -} // namespace - -llvm::Function* LLVMBuilder::buildLLVMFunction(llvm::Function* llvmFn, ir::Func* fn) { - // auto existant = module->getFunction(fn->getMangle()); - // if (existant) return existant; - ctx->setCurrentFunction(nullptr); - // llvmFn->getDe - std::string bufStr; - llvm::raw_string_ostream buf(bufStr); - std::vector addedTypes; - for (const auto& chunk : fn->getLLVMBody()) { - if (chunk.type == Syntax::LLVMIRChunk::TypeAccess) { - auto type = getLLVMType(chunk.ty); - addTypeToModule(addedTypes, type, buf); - } - } - buf << "define "; - llvmFn->getReturnType()->print(buf, false, true); - buf << " @\"" << llvmFn->getName() << "\"("; - auto args = fn->getArgs(); - for (int i = 0; i < (int)args.size(); i++) { - auto l_front = args.begin(); - std::advance(l_front, i); - llvmFn->getArg(i)->getType()->print(buf, false, true); - buf << " %" << l_front->first; - if (i < (int)(args.size() - 1)) buf << ", "; - } - buf << ") { \nentry:\n\t"; - for (const auto& chunk : fn->getLLVMBody()) { - if (chunk.type == Syntax::LLVMIRChunk::TypeAccess) { - auto type = getLLVMType(chunk.ty, true); - type->print(buf, false, true); - } else { - assert(chunk.type == Syntax::LLVMIRChunk::LLCode); - buf << chunk.code; - } - } - buf << "\n}"; - auto code = buf.str(); - bufStr.clear(); - auto llvmBuffer = llvm::MemoryBuffer::getMemBuffer(code); - llvm::SMDiagnostic err; - std::unique_ptr sub = llvm::parseIR(llvmBuffer->getMemBufferRef(), err, *context); - if (!sub) { - std::string bufStr; - llvm::raw_string_ostream buf(bufStr); - err.print("LLVM", buf); - Logger::error("Error generating user-defined llvm function"); - for (auto line : utils::split(code, "\n")) { Logger::error(line); } - throw SNError(Error::LLVM_INTERNAL, buf.str()); - } - sub->setDataLayout(module->getDataLayout()); - llvm::Linker linker(*module); - const bool fail = linker.linkInModule(std::move(sub)); - assert(!fail); - auto func = module->getFunction(fn->getMangle()); - assert(func && "function not linked in"); - func->setLinkage(llvm::GlobalValue::InternalLinkage); - func->addFnAttr(llvm::Attribute::AttrKind::NoInline); // TODO: user decides, - // this is default - func->setSubprogram(getDISubprogramForFunc(fn)); - if (utils::cast(fn->getRetTy())) { - auto bytes = fn->getRetTy()->sizeOf(); - auto dereferenceable = llvm::Attribute::get(*context, llvm::Attribute::Dereferenceable, bytes); - auto noundef = llvm::Attribute::get(*context, llvm::Attribute::NoUndef); - auto nonnull = llvm::Attribute::get(*context, llvm::Attribute::NonNull); - auto aligment = llvm::Attribute::get(*context, llvm::Attribute::Alignment, 8); - llvmFn->addRetAttr(dereferenceable); - llvmFn->addRetAttr(noundef); - llvmFn->addRetAttr(aligment); - llvmFn->addRetAttr(nonnull); - } - llvmFn->replaceAllUsesWith(func); - llvmFn->eraseFromParent(); - setDebugInfoLoc(nullptr); - return func; -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/buildLoopFlow.cc b/src/builder/llvm/buildLoopFlow.cc deleted file mode 100644 index d5e64b3a..00000000 --- a/src/builder/llvm/buildLoopFlow.cc +++ /dev/null @@ -1,25 +0,0 @@ -#include "../../ir/values/LoopFlow.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include - -namespace snowball { -namespace codegen { - -void LLVMBuilder::visit(ir::LoopFlow* c) { - switch (c->getFlowType()) { - case ir::LoopFlowType::Break: - builder->CreateBr(ctx->loop.breakBlock); - break; - case ir::LoopFlowType::Continue: - builder->CreateBr(ctx->loop.continueBlock); - break; - default: - assert(false); - } -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/buildOperator.cc b/src/builder/llvm/buildOperator.cc deleted file mode 100644 index fc0ca952..00000000 --- a/src/builder/llvm/buildOperator.cc +++ /dev/null @@ -1,257 +0,0 @@ - -#include "../../ir/values/Call.h" -#include "../../ir/values/Dereference.h" -#include "../../ir/values/Func.h" -#include "../../ir/values/IndexExtract.h" -#include "../../ir/values/ReferenceTo.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include - -#define OPERATOR_CALL(f) \ - this->value = builder->f(load(left, baseType), right); -#define U_OPERATOR_CALL(f) \ - this->value = builder->f(load(left, baseType)); - -#define SIGNED_DEPENDANT(x, s, u) \ - case services::OperatorService::x: \ - if (utils::cast(realType)->isSigned()) { \ - OPERATOR_CALL(s) \ - } else { \ - OPERATOR_CALL(u) \ - } \ - break; - -#define U_SIGNED_DEPENDANT(x, s, u) \ - case services::OperatorService::x: \ - if (utils::cast(realType)->isSigned()) { \ - U_OPERATOR_CALL(s) \ - } else { \ - U_OPERATOR_CALL(u) \ - } \ - break; - -#define OPERATOR_INSTANCE(x, f) \ - case services::OperatorService::x: \ - OPERATOR_CALL(f) \ - break; -#define OPERATOR_UINSTANCE(x, f) \ - case services::OperatorService::x: U_OPERATOR_CALL(f); break; - -namespace snowball { -namespace codegen { - -bool LLVMBuilder::buildOperator(ir::Call* call) { - if (auto fn = utils::dyn_cast(call->getCallee())) { - if (!fn->hasAttribute(Attributes::BUILTIN)) return false; - auto args = call->getArguments(); - auto opName = fn->getName(true); - if (services::OperatorService::isOperator(opName) && - !services::OperatorService::opEquals(opName)) { - auto left = build(args.at(0).get()); - llvm::Value* right = nullptr; - { - if (args.size() > 1 && !services::OperatorService::opEquals(opName) - && !services::OperatorService::opEquals(opName)) { - ctx->doNotLoadInMemory = false; - right = expr(args.at(1).get()); - } - if (services::OperatorService::opEquals(opName)) { - if (utils::is(args.at(0).get()) && - llvm::isa(left)) { - left = ((llvm::LoadInst*) left)->getPointerOperand(); - } - } - } - auto baseType = args.at(0)->getType(); - auto realType = baseType; - if (auto x = utils::cast(baseType)) { - baseType = x->getPointedType(); - realType = x->getBaseType(); - } - if (utils::is(realType)) { - switch (services::OperatorService::operatorID(opName)) { - OPERATOR_INSTANCE(EQEQ, CreateICmpEQ) - OPERATOR_INSTANCE(PLUS, CreateAdd) - OPERATOR_INSTANCE(MINUS, CreateSub) - OPERATOR_INSTANCE(MUL, CreateMul) - OPERATOR_INSTANCE(DIV, CreateSDiv) - OPERATOR_INSTANCE(MOD, CreateSRem) - OPERATOR_INSTANCE(NOTEQ, CreateICmpNE) - OPERATOR_INSTANCE(BIT_LSHIFT, CreateShl) - //OPERATOR_INSTANCE(BIT_LSHIFT_EQ, CreateShl) - OPERATOR_INSTANCE(BIT_RSHIFT, CreateLShr) - //OPERATOR_INSTANCE(BIT_RSHIFT_EQ, CreateAShr) - OPERATOR_INSTANCE(BIT_OR, CreateOr) - //OPERATOR_INSTANCE(BIT_OR_EQ, CreateOr) - OPERATOR_INSTANCE(BIT_AND, CreateAnd) - //OPERATOR_INSTANCE(BIT_AND_EQ, CreateAnd) - OPERATOR_INSTANCE(BIT_XOR, CreateXor) - //OPERATOR_INSTANCE(BIT_XOR_EQ, CreateXor) - OPERATOR_UINSTANCE(BIT_NOT, CreateNot) - SIGNED_DEPENDANT(LT, CreateICmpSLT, CreateICmpULT) - SIGNED_DEPENDANT(GT, CreateICmpSGT, CreateICmpUGT) - SIGNED_DEPENDANT(LTEQ, CreateICmpSLE, CreateICmpULE) - SIGNED_DEPENDANT(GTEQ, CreateICmpSGE, CreateICmpUGE) - U_SIGNED_DEPENDANT(UMINUS, CreateNSWNeg, CreateNUWNeg) - case services::OperatorService::AND: { - left = toBool(load(left, baseType), utils::cast(realType)->isSigned()); - auto currentBlock = builder->GetInsertBlock(); - auto trueBlock = h.create(*context, "and.true", ctx->getCurrentFunction()); - auto continueBlock = h.create(*context, "and.cont", ctx->getCurrentFunction()); - createCondBr(left, trueBlock, continueBlock); - builder->SetInsertPoint(trueBlock); - right = toBool(expr(args.at(1).get()), utils::cast(realType)->isSigned()); - auto trueNode = builder->GetInsertBlock(); - auto cmp = builder->CreateICmpNE(right, llvm::ConstantInt::get(right->getType(), 0, - utils::cast(realType)->isSigned())); - builder->CreateBr(continueBlock); - builder->SetInsertPoint(continueBlock); - auto phi = builder->CreatePHI(builder->getInt1Ty(), 2); - phi->addIncoming(builder->getFalse(), currentBlock); - phi->addIncoming(cmp, trueNode); - this->value = phi; - break; - } - case services::OperatorService::OR: { - left = toBool(load(left, baseType), utils::cast(realType)->isSigned()); - auto currentBlock = builder->GetInsertBlock(); - auto trueBlock = h.create(*context, "or.true", ctx->getCurrentFunction()); - auto continueBlock = h.create(*context, "or.cont", ctx->getCurrentFunction()); - createCondBr(left, continueBlock, trueBlock); - builder->SetInsertPoint(trueBlock); - right = toBool(expr(args.at(1).get()), utils::cast(realType)->isSigned()); - auto trueNode = builder->GetInsertBlock(); - auto cmp = builder->CreateICmpNE(right, llvm::ConstantInt::get(right->getType(), 0, - utils::cast(realType)->isSigned())); - builder->CreateBr(continueBlock); - builder->SetInsertPoint(continueBlock); - auto phi = builder->CreatePHI(builder->getInt1Ty(), 2); - phi->addIncoming(builder->getTrue(), currentBlock); - phi->addIncoming(cmp, trueNode); - this->value = phi; - break; - } - case services::OperatorService::NOT: { - left = toBool(load(left, baseType)); - auto size_in_bits = ((llvm::IntegerType*) left->getType())->getBitWidth(); - if (left->getType()->isPointerTy()) - this->value = builder->CreateICmpEQ( - left, llvm::ConstantPointerNull::get(builder->getIntNTy((unsigned) size_in_bits)->getPointerTo()) - ); - else - this->value = builder->CreateICmpEQ( - left, llvm::ConstantInt::get(builder->getIntNTy((unsigned) size_in_bits), 0, false) - ); - break; - } - // TODO: remainder oeprators (!, +=, etc...) - case services::OperatorService::EQ: { - builder->CreateStore(right, left); - break; - } - default: assert(false && "Unknown operator"); - } - return true; - } else if (utils::is(realType)) { - // this->value = builder->Create - switch (services::OperatorService::operatorID(opName)) { - OPERATOR_INSTANCE(EQEQ, CreateFCmpUEQ) - OPERATOR_INSTANCE(PLUS, CreateFAdd) - OPERATOR_INSTANCE(MINUS, CreateFSub) - OPERATOR_INSTANCE(MUL, CreateFMul) - OPERATOR_INSTANCE(DIV, CreateFDiv) - OPERATOR_INSTANCE(MOD, CreateFRem) - OPERATOR_INSTANCE(NOTEQ, CreateFCmpUNE) - OPERATOR_INSTANCE(BIT_LSHIFT, CreateShl) - //OPERATOR_INSTANCE(BIT_LSHIFT_EQ, CreateShl) - OPERATOR_INSTANCE(BIT_RSHIFT, CreateLShr) - //OPERATOR_INSTANCE(BIT_RSHIFT_EQ, CreateAShr) - OPERATOR_INSTANCE(BIT_OR, CreateOr) - //OPERATOR_INSTANCE(BIT_OR_EQ, CreateOr) - OPERATOR_INSTANCE(BIT_AND, CreateAnd) - //OPERATOR_INSTANCE(BIT_AND_EQ, CreateAnd) - OPERATOR_INSTANCE(BIT_XOR, CreateXor) - OPERATOR_UINSTANCE(BIT_NOT, CreateNot) - //OPERATOR_INSTANCE(BIT_XOR_EQ, CreateXor) - OPERATOR_INSTANCE(LT, CreateFCmpOLT) - OPERATOR_INSTANCE(GT, CreateFCmpOGT) - OPERATOR_INSTANCE(LTEQ, CreateFCmpOLE) - OPERATOR_INSTANCE(GTEQ, CreateFCmpOGE) - case services::OperatorService::AND: { - left = toBool(load(left, baseType)); - auto currentBlock = builder->GetInsertBlock(); - auto trueBlock = h.create(*context, "and.true", ctx->getCurrentFunction()); - auto continueBlock = h.create(*context, "and.cont", ctx->getCurrentFunction()); - createCondBr(left, trueBlock, continueBlock); - builder->SetInsertPoint(trueBlock); - right = toBool(expr(args.at(1).get())); - auto trueNode = builder->GetInsertBlock(); - auto cmp = builder->CreateFCmpUNE(right, llvm::ConstantFP::get(right->getType(), 0)); - builder->CreateBr(continueBlock); - builder->SetInsertPoint(continueBlock); - auto phi = builder->CreatePHI(builder->getInt1Ty(), 2); - phi->addIncoming(builder->getFalse(), currentBlock); - phi->addIncoming(cmp, trueNode); - this->value = phi; - break; - } - case services::OperatorService::OR: { - left = toBool(load(left, baseType)); - auto currentBlock = builder->GetInsertBlock(); - auto trueBlock = h.create(*context, "or.true", ctx->getCurrentFunction()); - auto continueBlock = h.create(*context, "or.cont", ctx->getCurrentFunction()); - createCondBr(left, continueBlock, trueBlock); - builder->SetInsertPoint(trueBlock); - right = toBool(expr(args.at(1).get())); - auto trueNode = builder->GetInsertBlock(); - auto cmp = builder->CreateFCmpUNE(right, llvm::ConstantFP::get(right->getType(), 0)); - builder->CreateBr(continueBlock); - builder->SetInsertPoint(continueBlock); - auto phi = builder->CreatePHI(builder->getInt1Ty(), 2); - phi->addIncoming(builder->getTrue(), currentBlock); - phi->addIncoming(cmp, trueNode); - this->value = phi; - break; - } - OPERATOR_UINSTANCE(UMINUS, CreateFNeg) - case services::OperatorService::NOT: { - this->value = - builder->CreateFCmpOEQ(load(left, baseType), llvm::ConstantFP::get(builder->getFloatTy(), 0.0f)); - break; - } - // TODO: remainder oeprators (!, +=, etc...) - case services::OperatorService::EQ: { - builder->CreateStore(right, left); - break; - } - default: assert(false); - } - return true; - } else { - switch (services::OperatorService::operatorID(opName)) { - case services::OperatorService::EQ: { - if (llvm::isa(left)) { - if (llvm::isa(right)) { - right = ((llvm::LoadInst*) right)->getPointerOperand(); - } - builder->CreateMemCpy( - left, llvm::MaybeAlign(), right, llvm::MaybeAlign(), - module->getDataLayout().getTypeSizeInBits(getLLVMType(realType)) / 8 - ); - } else builder->CreateStore(right, left); - break; - } - default: return false; - } - return true; - } - } - } - return false; -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/buildReferenceTo.cc b/src/builder/llvm/buildReferenceTo.cc deleted file mode 100644 index 652baae1..00000000 --- a/src/builder/llvm/buildReferenceTo.cc +++ /dev/null @@ -1,38 +0,0 @@ - -#include "../../ir/values/ReferenceTo.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include - -namespace snowball { -namespace codegen { - -void LLVMBuilder::visit(ir::ReferenceTo* ref) { - auto val = ref->getValue(); - auto llvmReferencedValue = build(val.get()); - auto tempVal = (llvm::Value*) nullptr; - if (llvm::isa(llvmReferencedValue) && !llvm::isa(llvmReferencedValue)) { - auto var = new llvm::GlobalVariable( - *module, - getLLVMType(val->getType()), - false, - llvm::GlobalValue::LinkageTypes::InternalLinkage, - llvm::cast(llvmReferencedValue), - "alloca_" + utils::gen_random<32>() - ); - var->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - tempVal = var; - } else { - if (llvm::isa(llvmReferencedValue)) { - llvmReferencedValue = llvm::cast(llvmReferencedValue)->getPointerOperand(); - } - tempVal = llvmReferencedValue; - } - ctx->doNotLoadInMemory = true; - this->value = tempVal; -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/buildReturn.cc b/src/builder/llvm/buildReturn.cc deleted file mode 100644 index 4175366d..00000000 --- a/src/builder/llvm/buildReturn.cc +++ /dev/null @@ -1,64 +0,0 @@ - -#include "../../ast/types/ReferenceType.h" -#include "../../ir/values/Call.h" -#include "../../ir/values/IndexExtract.h" -#include "../../ir/values/EnumInit.h" -#include "../../ir/values/Return.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include - -namespace snowball { -namespace codegen { - -using namespace utils; - -void LLVMBuilder::visit(ir::Return* ret) { - auto exprValue = ret->getExpr(); - llvm::Value* val = nullptr; - if (exprValue != nullptr) { - // case: "let a = x();" where x is a function returning a type that's not a pointer - // We store the value into the first argument of the function. - // This is because we can't return a struct that's not a pointer. - // read more here: https://discourse.llvm.org/t/c-returning-struct-by-value/40518 - if (utils::is(ret->getType())) { - auto retArg = ctx->getCurrentFunction()->getArg(0); - bool doNotMove = false; - if (is(exprValue.get()) && !is(exprValue.get()) && - !is(exprValue.get())) { - //ctx->retValueUsedFromArg = true; - //doNotMove = true; - } - auto e = build(exprValue.get()); - ctx->retValueUsedFromArg = false; - auto sretBB = llvm::BasicBlock::Create(*context, "sret", ctx->getCurrentFunction()); - builder->CreateBr(sretBB); - builder->SetInsertPoint(sretBB); - if (llvm::isa(e)) { e = llvm::cast(e)->getPointerOperand(); } - if (!doNotMove) { - auto layout = module->getDataLayout().getStructLayout( - llvm::cast(getLLVMType(ret->getType()))); - builder->CreateMemCpy( - retArg, llvm::MaybeAlign(), e, llvm::MaybeAlign(), builder->getInt64(layout->getSizeInBytes()) - ); - //builder->CreateStore(builder->CreateLoad(getLLVMType(ret->getType()), e), retArg); - } else { - assert(false); - builder->CreateUnreachable(); - } - // auto store = builder->CreateStore(load(e, ret->getType()), retArg); - builder->CreateRetVoid(); - return; - } - auto e = expr(exprValue.get()); - val = builder->CreateRet(e); - } else { - val = builder->CreateRetVoid(); - } - this->value = val; -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/buildSwitch.cc b/src/builder/llvm/buildSwitch.cc deleted file mode 100644 index 5bb0b9d6..00000000 --- a/src/builder/llvm/buildSwitch.cc +++ /dev/null @@ -1,92 +0,0 @@ - -#include "../../ir/values/Variable.h" -#include "../../ir/values/Switch.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" -#include "varFetchImpl.h" -#include "../../ast/errors/error.h" - -#include -#include - -namespace snowball { -namespace codegen { - -void LLVMBuilder::visit(ir::Switch* switchStmt) { - auto parent = ctx->getCurrentFunction(); - assert(parent); - auto initExpr = (llvm::Value*)nullptr; - auto exprValue = (llvm::Value*)nullptr; - auto enumType = utils::cast(switchStmt->getExpr()->getType()); - if (!switchStmt->isCStyleSwitch()) { - assert(enumType != nullptr); - initExpr = build(switchStmt->getExpr().get()); - if (!initExpr->getType()->isPointerTy() && llvm::isa(initExpr)) { - initExpr = llvm::cast(initExpr)->getPointerOperand(); - } - auto exprIndex = builder->CreateStructGEP(getLLVMType(enumType), initExpr, 0); - exprValue = builder->CreateLoad(builder->getInt8Ty(), exprIndex, ".switch-index"); - } else exprValue = expr(switchStmt->getExpr().get()); - std::vector blocks; - for (auto& c : switchStmt->getCases().first) { - blocks.push_back(h.create(*context, "switch-case-" + c.name, parent)); - } - for (size_t cSwitchIndex = 0; cSwitchIndex < switchStmt->getCases().second.size(); cSwitchIndex++) { - blocks.push_back(h.create(*context, "switch-case-" + std::to_string(cSwitchIndex), parent)); - } - auto defaultBlock = h.create(*context, "switch-default", parent); - auto continueBlock = h.create(*context, "switch-continue", parent); - auto switchInst = builder->CreateSwitch(exprValue, defaultBlock, blocks.size()); - // non-c-style switch - for (size_t i = 0; i < switchStmt->getCases().first.size(); i++) { - assert(enumType != nullptr); - assert(initExpr != nullptr); - auto c = switchStmt->getCases().first[i]; - size_t enumIndex = 0; - for (size_t j = 0; j < enumType->getFields().size(); j++) { - if (enumType->getFields()[j].name == c.name) { - enumIndex = j; - break; - } - } - auto field = c.name; - auto vars = c.args; - auto block = blocks[i]; - auto enumField = std::find_if(enumType->getFields().begin(), enumType->getFields().end(), [&](auto f) { - return f.name == field; - }); - assert(enumField != enumType->getFields().end()); - builder->SetInsertPoint(block); - size_t j = 1; - for (auto& v : vars) { - auto var = ctx->getSymbol(v->getVariable()->getId()); - auto enumGep = builder->CreateStructGEP(createEnumFieldType(enumType, field), initExpr, j); - auto enumValue = builder->CreateLoad(getLLVMType((*enumField).types[j - 1]), enumGep); - builder->CreateStore(enumValue, var); - j++; - } - build(c.block.get()); - if (!builder->GetInsertBlock()->getTerminator()) { builder->CreateBr(continueBlock); } - switchInst->addCase(builder->getInt8(enumIndex), block); - } - // c-style switch - for (size_t i = 0; i < switchStmt->getCases().second.size(); i++) { - auto c = switchStmt->getCases().second[i]; - auto block = blocks[switchStmt->getCases().first.size() + i]; - builder->SetInsertPoint(block); - build(c.block.get()); - if (!builder->GetInsertBlock()->getTerminator()) { builder->CreateBr(continueBlock); } - switchInst->addCase(llvm::cast(build(c.value.get())), block); - } - builder->SetInsertPoint(defaultBlock); - if (auto defaultCase = switchStmt->getDefaultCase()) { - build(defaultCase.get()); - if (!builder->GetInsertBlock()->getTerminator()) { builder->CreateBr(continueBlock); } - } else { - builder->CreateBr(continueBlock); - } - builder->SetInsertPoint(continueBlock); -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/buildThrow.cc b/src/builder/llvm/buildThrow.cc deleted file mode 100644 index 08c8a008..00000000 --- a/src/builder/llvm/buildThrow.cc +++ /dev/null @@ -1,22 +0,0 @@ - -#include "../../ir/values/Throw.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include -#include - -namespace snowball { -namespace codegen { - -void LLVMBuilder::visit(ir::Throw* extract) { - auto expr = extract->getExpr(); - auto value = build(expr.get()); - auto exception = createException(value, expr->getType()); - auto[type, throwFunction] = getThrowFunction(); - this->value = createCall(type, throwFunction, {exception}); -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/buildTryCatch.cc b/src/builder/llvm/buildTryCatch.cc deleted file mode 100644 index e54f4a15..00000000 --- a/src/builder/llvm/buildTryCatch.cc +++ /dev/null @@ -1,142 +0,0 @@ - -#include "../../ir/values/TryCatch.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include - -#include "../../../runtime/libs/exceptions.h" - -namespace snowball { -namespace codegen { - -void LLVMBuilder::visit(ir::TryCatch* node) { - auto parentFunc = ctx->getCurrentFunction(); - auto padType = llvm::StructType::get(builder->getInt8PtrTy(), builder->getInt32Ty()); - auto unwindType = llvm::StructType::get(builder->getInt64Ty()); - auto execType = llvm::StructType::get(getTypeInfoType(), builder->getInt8PtrTy()); - auto ourExceptionThrownState = llvm::ConstantInt::get(llvm::Type::getInt8Ty(*context), 1); - // Create the try block - auto tryBlock = llvm::BasicBlock::Create(*context, "try", parentFunc); - builder->CreateBr(tryBlock); - TryCatchInfo info; - info.catchBlock = llvm::BasicBlock::Create(*context, "catch", parentFunc); - info.catchRouteBlock = llvm::BasicBlock::Create(*context, "catch.route", parentFunc); - llvm::Value* exceptionCaughtFlag = NULL; - llvm::Value* exceptionStorage = NULL; - llvm::Value* caughtResultStorage = NULL; - auto externalExcBlock = llvm::BasicBlock::Create(*context, "catch.external", parentFunc); - auto unwindResumeBlock = llvm::BasicBlock::Create(*context, "catch.unwind", parentFunc); - auto endBlock = llvm::BasicBlock::Create(*context, "try.end", parentFunc); - // MARK: entry block - builder->SetInsertPoint(parentFunc->getEntryBlock().getTerminator()); - exceptionCaughtFlag = builder->CreateAlloca(builder->getInt8Ty()); - exceptionStorage = builder->CreateAlloca(builder->getInt8PtrTy()); - caughtResultStorage = builder->CreateAlloca(builder->getInt8PtrTy()); - info.exceptionPad = builder->CreateAlloca(padType); - builder->CreateStore(llvm::ConstantAggregateZero::get(padType), info.exceptionPad); - auto catchInstances = node->getCatchBlocks(); - auto catchVars = node->getCatchVars(); - assert(catchInstances.size() == catchVars.size()); - // MARK: try block - builder->SetInsertPoint(tryBlock); - tryCatchStack.push_back(std::move(info)); - build(node->getBlock().get()); - tryCatchStack.pop_back(); - for (int i = 0; i < (int)catchInstances.size(); i++) { - auto catchBlock = catchInstances[i]; - auto catchVar = catchVars[i]; - auto catchBlockBB = llvm::BasicBlock::Create(*context, "catch.block", parentFunc); - info.handlers.push_back(catchBlockBB); - info.catchVars.push_back(catchVar); - } - if (builder->GetInsertBlock()->getTerminator() == nullptr) - builder->CreateBr(endBlock); - // MARK: unwind resume block - builder->SetInsertPoint(unwindResumeBlock); - builder->CreateResume(builder->CreateLoad(padType, info.exceptionPad)); - // MARK: catch block - std::vector typeIndices; - builder->SetInsertPoint(info.catchBlock); - auto caughtException = builder->CreateLandingPad(padType, catchInstances.size()); - caughtException->setCleanup(true); - for (auto catchVar : info.catchVars) { - auto varName = "snowball.typeidx." + catchVar->getType()->getMangledName(); - llvm::GlobalVariable* tidx = module->getGlobalVariable(varName); - if (!tidx) { - tidx = new llvm::GlobalVariable( - *module, - llvm::StructType::get(builder->getInt32Ty()), - /*isConstant=*/true, - llvm::GlobalValue::PrivateLinkage, - llvm::ConstantStruct::get( - getTypeInfoType(), builder->getInt32(typeIdxLookup(catchVar->getType()->getMangledName())) - ), - varName - ); - tidx->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - } - caughtException->addClause(tidx); - } - auto unwindException = builder->CreateExtractValue(caughtException, 0); - builder->CreateStore(caughtException, info.exceptionPad); - builder->CreateStore(caughtResultStorage, caughtResultStorage); - builder->CreateStore(unwindException, exceptionStorage); - builder->CreateStore(ourExceptionThrownState, exceptionCaughtFlag); - // auto depthMax = builder->getInt64(trycatch.size()); - // builder->CreateStore(depthMax, tc.delegateDepth); - auto unwindExceptionClass = builder->CreateLoad( - builder->getInt64Ty(), - builder->CreateStructGEP( - unwindType, builder->CreatePointerCast(unwindException, unwindType->getPointerTo()), 0 - ) - ); - createCondBr( - builder->CreateICmpEQ(unwindExceptionClass, builder->getInt64(exception_class())), - info.catchRouteBlock, - externalExcBlock - ); - // MARK: external exception block - builder->SetInsertPoint(externalExcBlock); - builder->CreateUnreachable(); - // MARK: catch route block - builder->SetInsertPoint(info.catchRouteBlock); - unwindException = builder->CreateExtractValue(builder->CreateLoad(padType, info.exceptionPad), 0); - llvm::Value* execVal = builder->CreatePointerCast( - builder->CreateConstGEP1_64(builder->getInt8Ty(), unwindException, (uint64_t) exception_offset()), - execType->getPointerTo() - ); - auto loadedExc = builder->CreateLoad(execType, execVal); - auto objType = builder->CreateExtractValue(loadedExc, 0); - objType = builder->CreateExtractValue(objType, 0); - auto objPtr = builder->CreateExtractValue(loadedExc, 1); - auto defaultRouteBlock = llvm::BasicBlock::Create(*context, "trycatch.fdepth", parentFunc); - builder->SetInsertPoint(defaultRouteBlock); - builder->CreateBr(endBlock); - builder->SetInsertPoint(info.catchRouteBlock); - auto castSwitch = builder->CreateSwitch(objType, defaultRouteBlock, (unsigned) catchInstances.size()); - // TODO: support for "catch all" - for (int i = 0; i < (int)info.handlers.size(); i++) { - // set finally depth - auto mangledType = catchVars[i]->getType()->getMangledName(); - auto type = getLLVMType(catchVars[i]->getType()); - auto BBlock = info.handlers[i]; - // builder->CreateBr((i < info.handlers.size()) ? info.handlers[i] : endBlock); - castSwitch->addCase(builder->getInt32((uint64_t) typeIdxLookup(mangledType)), BBlock); - auto block = catchInstances[i]; - builder->SetInsertPoint(BBlock); - auto var = catchVars[i]; - if (var) { - auto obj = builder->CreateLoad(type, objPtr); - auto varPtr = ctx->getSymbol(var->getId()); - builder->CreateStore(obj, varPtr); - } - build(block.get()); - if (BBlock->getTerminator() == nullptr) builder->CreateBr(endBlock); - } - builder->SetInsertPoint(endBlock); -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/buildValueExtract.cc b/src/builder/llvm/buildValueExtract.cc deleted file mode 100644 index 41506318..00000000 --- a/src/builder/llvm/buildValueExtract.cc +++ /dev/null @@ -1,31 +0,0 @@ - -#include "../../ir/values/ValueExtract.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include -#include -#include "varFetchImpl.h" - -namespace snowball { -namespace codegen { - -void LLVMBuilder::visit(ir::ValueExtract* extract) { - auto var = extract->getValue(); - llvm::Value* value = nullptr; - if (auto f = utils::dyn_cast(var)) { - ctx->doNotLoadInMemory = true; - auto fn = funcs.at(f->getId()); - this->value = fn; - return; - } else if (auto v = utils::dyn_cast(var)) { - GET_VAR_IMPL(v, value); - } else { - assert(false && "BUG: Value extract type not supported!"); - } - this->value = value; -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/buildVariable.cc b/src/builder/llvm/buildVariable.cc deleted file mode 100644 index b3ff0388..00000000 --- a/src/builder/llvm/buildVariable.cc +++ /dev/null @@ -1,19 +0,0 @@ - -#include "../../ir/values/Variable.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" -#include "varFetchImpl.h" -#include "../../ast/errors/error.h" - -#include -#include - -namespace snowball { -namespace codegen { - -void LLVMBuilder::visit(ir::Variable* variable) { - GET_VAR_IMPL(variable, value); -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/buildVariableDecl.cc b/src/builder/llvm/buildVariableDecl.cc deleted file mode 100644 index e206a1b7..00000000 --- a/src/builder/llvm/buildVariableDecl.cc +++ /dev/null @@ -1,68 +0,0 @@ - -#include "../../ir/values/Argument.h" -#include "../../ir/values/EnumInit.h" -#include "../../ir/values/Call.h" -#include "../../ir/values/VariableDeclaration.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include - -namespace snowball { -namespace codegen { - -void LLVMBuilder::visit(ir::VariableDeclaration* variable) { - llvm::Value* store = nullptr; - ctx->doNotLoadInMemory = false; - if (auto a = utils::cast(variable->getValue().get())) { - auto id = a->getId(); - store = ctx->getSymbol(id); - } else { - if (variable->getVariable()->isUsedInLambda()) { - auto closure = ctx->closures.at(ctx->getCurrentIRFunction()->getId()); - auto index = std::distance( - closure.variables.begin(), - std::find_if( - closure.variables.begin(), - closure.variables.end(), - [variable](auto & v) { return v == variable->getVariable()->getId(); } - ) - ); - store = builder->CreateStructGEP(closure.closureType, closure.closure, index); - } else { - auto id = variable->getId(); - store = ctx->getSymbol(id); - } - } - // debug info - if (auto llvmFn = ctx->getCurrentFunction()) { - auto dbgInfo = variable->getDBGInfo(); - auto src = variable->getSourceInfo(); - auto file = dbg.getFile(src->getPath()); - auto scope = llvmFn->getSubprogram(); - auto debugVar = dbg.builder->createAutoVariable( - scope, variable->getIdentifier(), file, dbgInfo->line, getDIType(variable->getType()), dbg.debug - ); - dbg.builder->insertDeclare( - store, - debugVar, - dbg.builder->createExpression(), - llvm::DILocation::get(*context, dbgInfo->line, dbgInfo->pos.second, scope), - builder->GetInsertBlock() - ); - } - if (utils::is(variable->getValue().get()) - && !utils::is(utils::dyn_cast(variable->getValue())->getCallee().get()) - && utils::is(variable->getType())) { - ctx->callStoreValue = store; - build(variable->getValue().get()); - ctx->callStoreValue = nullptr; - } else { - auto generatedValue = expr(variable->getValue().get()); - builder->CreateStore(generatedValue, store); - } -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/buildWhileLoop.cc b/src/builder/llvm/buildWhileLoop.cc deleted file mode 100644 index 6ccad216..00000000 --- a/src/builder/llvm/buildWhileLoop.cc +++ /dev/null @@ -1,65 +0,0 @@ -#include "../../ir/values/WhileLoop.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include - -namespace snowball { -namespace codegen { - -void LLVMBuilder::visit(ir::WhileLoop* c) { - auto parent = ctx->getCurrentFunction(); - assert(parent); - auto condBB = h.create(*context, "", parent); - auto whileBB = h.create(*context, "", parent); - auto continueBB = h.create(*context, "", parent); - auto backupLoop = ctx->loop; - ctx->loop = { - .continueBlock = condBB, - .breakBlock = continueBB, - }; - if (c->isDoWhile()) { - builder->CreateBr(whileBB); - builder->SetInsertPoint(whileBB); - (void) build(c->getBlock().get()); - if (!builder->GetInsertBlock()->getTerminator()) { builder->CreateBr(condBB); } - builder->SetInsertPoint(condBB); - auto cond = expr(c->getCondition().get()); - createCondBr(cond, whileBB, continueBB); - builder->SetInsertPoint(continueBB); - } else { - if (auto x = c->getForCond()) { - // Using "continue" must execute the for condition - // before jumping to the next iteration - // "x" is `for i; i < 10; i++ {}` - // ^^^ <- this - auto forCondBB = h.create(*context, "for.cond", parent); - builder->CreateBr(condBB); - builder->SetInsertPoint(condBB); - auto cond = expr(c->getCondition().get()); - ctx->loop.continueBlock = forCondBB; - createCondBr(cond, whileBB, continueBB); - builder->SetInsertPoint(whileBB); - (void) build(c->getBlock().get()); - if (!builder->GetInsertBlock()->getTerminator()) { builder->CreateBr(forCondBB); } - builder->SetInsertPoint(forCondBB); - (void)build(x.get()); - builder->CreateBr(condBB); - builder->SetInsertPoint(continueBB); - } else { - builder->CreateBr(condBB); - builder->SetInsertPoint(condBB); - auto cond = expr(c->getCondition().get()); - createCondBr(cond, whileBB, continueBB); - builder->SetInsertPoint(whileBB); - (void) build(c->getBlock().get()); - if (!builder->GetInsertBlock()->getTerminator()) { builder->CreateBr(condBB); } - builder->SetInsertPoint(continueBB); - } - } - ctx->loop = backupLoop; -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/call.cc b/src/builder/llvm/call.cc deleted file mode 100644 index 9521428e..00000000 --- a/src/builder/llvm/call.cc +++ /dev/null @@ -1,25 +0,0 @@ - -#include "../../ir/values/WhileLoop.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include - -namespace snowball { -namespace codegen { - -llvm::Value* LLVMBuilder::createCall(llvm::FunctionType* ty, llvm::Value* callee, llvm::ArrayRef args) { - if (tryCatchStack.empty()) { - return builder->CreateCall(ty, callee, args); - } else { - auto normalBlock = llvm::BasicBlock::Create(*context, "invoke.normal", ctx->getCurrentFunction()); - auto unwindBlock = tryCatchStack.back().catchBlock; - auto result = builder->CreateInvoke(ty, callee, normalBlock, unwindBlock, args); - builder->SetInsertPoint(normalBlock); - return result; - } -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/createBenchmark.cc b/src/builder/llvm/createBenchmark.cc deleted file mode 100644 index a931d292..00000000 --- a/src/builder/llvm/createBenchmark.cc +++ /dev/null @@ -1,75 +0,0 @@ - -#include "../../errors.h" -#include "../../ir/values/Argument.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include -#include - -namespace snowball { -namespace codegen { - -void LLVMBuilder::createBenchmark(llvm::Function* mainFunction) { - assert(ctx->benchmarkMode); - auto printFunction = getPrintfFunction(); - mainFunction->addFnAttr(llvm::Attribute::NoInline); - mainFunction->addFnAttr(llvm::Attribute::OptimizeNone); - builder->CreateCall( - printFunction, { - builder->CreateGlobalStringPtr( - FMT("\nExecuting %s%i%s benchmark(s)... \n %snote:%s this can take a while! " - "you wont see any output until benchmarks are done.\n", - BBLU, - ctx->benchmarks.size(), - RESET, - BOLD, - RESET), - "bench.msg" - ) - } - ); - if (ctx->benchmarks.empty()) { - builder->CreateCall( - printFunction, - {builder->CreateGlobalStringPtr(FMT(" %soh no!%s No benchmarks found! 😿\n\n", BOLD, RESET), "bench.msg")} - ); - builder->CreateRet(builder->getInt32(0)); - return; - } - auto benchFunc = module->getFunction("sn.bench.run"); // Always match this - auto llvmBenchmarks = std::vector(); - auto benchmarkNames = std::vector(); - for (auto[fn, llvmFunc] : ctx->benchmarks) { - llvmBenchmarks.push_back(llvmFunc); - benchmarkNames.push_back(builder->CreateGlobalStringPtr(fn->getNiceName(), "bench.name")); - } - auto array = llvm::ConstantArray::get( - llvm::ArrayType::get(builder->getInt8PtrTy(), llvmBenchmarks.size()), llvmBenchmarks - ); - auto arrayGlobal = new llvm::GlobalVariable( - *module, array->getType(), true, llvm::GlobalValue::PrivateLinkage, array, "bench.array" - ); - auto nameArray = llvm::ConstantArray::get( - llvm::ArrayType::get(builder->getInt8PtrTy(), benchmarkNames.size()), benchmarkNames - ); - auto globalNameArray = new llvm::GlobalVariable( - *module, nameArray->getType(), true, llvm::GlobalValue::PrivateLinkage, nameArray, "bench.name.array" - ); - builder->CreateCall(benchFunc, {arrayGlobal, globalNameArray, builder->getInt32(llvmBenchmarks.size())}); - // TODO: dynamic if tests fail - builder->CreateRet(builder->getInt32(0)); - std::string module_error_string; - llvm::raw_string_ostream module_error_stream(module_error_string); - llvm::verifyFunction(*mainFunction, &module_error_stream); - if (!module_error_string.empty()) { -#ifdef _SNOWBALL_BYTECODE_DEBUG - dump(); -#endif - throw SNError(Error::LLVM_INTERNAL, module_error_string); - } -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/createCondBr.cc b/src/builder/llvm/createCondBr.cc deleted file mode 100644 index ac186c22..00000000 --- a/src/builder/llvm/createCondBr.cc +++ /dev/null @@ -1,22 +0,0 @@ - -#include "../../ir/values/WhileLoop.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" -#include "../../ir/values/EnumInit.h" -#include "../../ir/values/Call.h" - -#include -#include - -namespace snowball { -namespace codegen { - -void LLVMBuilder::createCondBr(llvm::Value* cond, llvm::BasicBlock* thenBlock, llvm::BasicBlock* elseBlock) { - if (cond->getType()->isIntegerTy(8)) { - cond = builder->CreateTrunc(cond, builder->getInt1Ty()); - } - builder->CreateCondBr(cond, thenBlock, elseBlock); -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/createEnumInit.cc b/src/builder/llvm/createEnumInit.cc deleted file mode 100644 index 6cba4645..00000000 --- a/src/builder/llvm/createEnumInit.cc +++ /dev/null @@ -1,36 +0,0 @@ - -#include "../../ir/values/WhileLoop.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" -#include "../../ir/values/EnumInit.h" -#include "../../ir/values/Call.h" - -#include -#include - -namespace snowball { -namespace codegen { - -llvm::Value* LLVMBuilder::createEnumInit(ir::Call* call) { - auto enumInit = utils::dyn_cast(call->getCallee()); - auto enumType = utils::cast(enumInit->getType()); - auto enumTypeLLVM = createEnumFieldType(enumType, enumInit->getName()); - int idx = 0; - for (auto field : enumType->getFields()) { - if (field.name == enumInit->getName()) break; - idx++; - } - auto enumInitLLVM = createAlloca(enumTypeLLVM, ".enum-init"); - auto enumInitPtr = builder->CreateStructGEP(enumTypeLLVM, enumInitLLVM, 0, ".enum-init-ptr"); - builder->CreateStore(builder->getInt8(idx), enumInitPtr); - int i = 1; - for (auto& arg : call->getArguments()) { - auto gep = builder->CreateStructGEP(enumTypeLLVM, enumInitLLVM, i, ".enum-init-gep"); - builder->CreateStore(expr(arg.get()), gep); - i++; - } - return enumInitLLVM; -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/createException.cc b/src/builder/llvm/createException.cc deleted file mode 100644 index 103ef138..00000000 --- a/src/builder/llvm/createException.cc +++ /dev/null @@ -1,27 +0,0 @@ - -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include -#include - -namespace snowball { -namespace codegen { - -llvm::Value* LLVMBuilder::createException(llvm::Value* value, types::Type* type) { - auto ty = llvm::FunctionType::get(builder->getInt8PtrTy(), {builder->getInt8PtrTy(), builder->getInt32Ty()}, false); - auto f = - llvm::cast(module->getOrInsertFunction(getSharedLibraryName("sn.eh.create"), ty).getCallee()); - f->addRetAttr(llvm::Attribute::NonNull); - f->addRetAttr(llvm::Attribute::NoAlias); - f->addRetAttr(llvm::Attribute::NoUndef); - f->setDoesNotThrow(); - auto usedValue = value; // use LLVMBuilder::load instead? - int typeId = typeIdxLookup(type->getMangledName()); - auto cast = builder->CreatePointerCast(usedValue, builder->getInt8PtrTy()); - return builder->CreateCall(f, {cast, builder->getInt32(typeId)}); -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/createLLVMFunction.cc b/src/builder/llvm/createLLVMFunction.cc deleted file mode 100644 index 04d171ff..00000000 --- a/src/builder/llvm/createLLVMFunction.cc +++ /dev/null @@ -1,82 +0,0 @@ - -#include "../../ast/errors/error.h" -#include "../../visitors/Transformer.h" -#include "../../ir/values/Argument.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include -#include -#include - -using namespace snowball::utils; - -namespace snowball { -namespace codegen { - -namespace { -void setDereferenceableAttribute(llvm::Argument& arg, unsigned bytes) { - auto dereferenceable = llvm::Attribute::get(arg.getContext(), llvm::Attribute::Dereferenceable, bytes); - auto noundef = llvm::Attribute::get(arg.getContext(), llvm::Attribute::NoUndef); - auto nonull = llvm::Attribute::get(arg.getContext(), llvm::Attribute::NonNull); - arg.addAttr(dereferenceable); - arg.addAttr(noundef); - arg.addAttr(nonull); -} -} // namespace - -llvm::Function* LLVMBuilder::createLLVMFunction(ir::Func* func) { - auto innerFnType = Syntax::Transformer::getFunctionType(func->getType()); - assert(innerFnType != nullptr); - if (auto x = module->getFunction(func->getMangle()); x != nullptr) { return x; } - auto fnType = llvm::cast(getLLVMFunctionType(innerFnType, func)); - if (func->getMangle() == "main") { - fnType = llvm::FunctionType::get(builder->getInt32Ty(), {builder->getInt32Ty(), builder->getInt8PtrTy()->getPointerTo()}, - false); - } - auto name = func->getMangle(); - auto fn = llvm::Function::Create( - fnType, - ((func->isStatic() && (!func->hasParent())) || - (func->hasAttribute(Attributes::INTERNAL_LINKAGE) && !func->isDeclaration())) ? - llvm::Function::InternalLinkage : - llvm::Function::ExternalLinkage, - name, - module.get() - ); - auto callee = (llvm::Function*) fn; - auto attrSet = callee->getAttributes(); - if (func->hasAttribute(Attributes::INLINE)) { - auto newAttrSet = attrSet.addFnAttribute(callee->getContext(), llvm::Attribute::AlwaysInline); - callee->setAttributes(newAttrSet); - // TODO: other attributes - } else if (func->hasAttribute(Attributes::NO_INLINE)) { - auto newAttrSet = attrSet.addFnAttribute(callee->getContext(), llvm::Attribute::NoInline); - callee->setAttributes(newAttrSet); - } - if (!func->isDeclaration()) { - auto DISubprogram = getDISubprogramForFunc(func); - callee->setSubprogram(DISubprogram); - } - bool retIsArg = utils::is(func->getRetTy()); - if (retIsArg) { - auto arg = fn->arg_begin(); - auto attrBuilder = llvm::AttrBuilder(*context); - attrBuilder.addStructRetAttr(getLLVMType(func->getRetTy())); - attrBuilder.addAttribute(llvm::Attribute::NoUndef); - attrBuilder.addAttribute(llvm::Attribute::NonNull); - arg->addAttrs(attrBuilder); - } - for (int i = 0; i < (int)func->getArgs().size(); ++i) { - auto llvmArg = fn->arg_begin() + i + retIsArg + func->isAnon(); - auto arg = utils::at(func->getArgs(), i); - if (auto ref = utils::cast(arg.second->getType())) { - setDereferenceableAttribute(*llvmArg, ref->getPointedType()->sizeOf() / 8); - } - } - return callee; -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/createTests.cc b/src/builder/llvm/createTests.cc deleted file mode 100644 index c2d27a8d..00000000 --- a/src/builder/llvm/createTests.cc +++ /dev/null @@ -1,156 +0,0 @@ - -#include "../../errors.h" -#include "../../ir/values/Argument.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include -#include - -namespace snowball { -namespace codegen { - -void LLVMBuilder::createTests(llvm::Function* mainFunction) { - assert(ctx->testMode); - auto printFunction = getPrintfFunction(); - mainFunction->addFnAttr(llvm::Attribute::NoInline); - mainFunction->addFnAttr(llvm::Attribute::OptimizeNone); - builder->CreateCall( - printFunction, { - builder->CreateGlobalStringPtr( - FMT("\nExecuting %s%i%s test(s)...\n\n", BBLU, ctx->tests.size(), RESET), "test.msg" - ) - } - ); - auto successCount = builder->CreateAlloca(builder->getInt32Ty(), nullptr, "success.count"); - auto failCount = builder->CreateAlloca(builder->getInt32Ty(), nullptr, "fail.count"); - auto skipCount = 0; - auto totalCount = builder->getInt32(ctx->tests.size()); - builder->CreateStore(builder->getInt32(0), successCount); - builder->CreateStore(builder->getInt32(0), failCount); - auto end = llvm::BasicBlock::Create(builder->getContext(), "end", mainFunction); - auto testFunction = module->getFunction("sn.test.try"); // Always match this - int testIndex = 1; - for (auto[fn, llvmFunc] : ctx->tests) { - std::string name = fn->getNiceName(); - auto attrArgs = fn->getAttributeArgs(Attributes::TEST); - auto shouldSkip = attrArgs.find("skip") != attrArgs.end(); - auto doesExpect = attrArgs.find("expect") != attrArgs.end(); - auto expect = doesExpect ? std::stoi(attrArgs["expect"]) : 1; - auto namePtr = builder->CreateGlobalStringPtr(name, "test.alloca"); - auto expectStr = builder->CreateGlobalStringPtr(expect == 1 ? "should pass" : FMT("expect %i", expect), "test.alloca"); - auto call = builder->CreateCall( - testFunction, - {llvmFunc, namePtr, builder->getInt32(testIndex), builder->getInt8(shouldSkip), builder->getInt32(expect), expectStr, totalCount} - ); - auto shouldContinue = builder->CreateICmpEQ(call, builder->getInt32(1)); - if (shouldSkip) { - skipCount++; - } else { - auto successBlock = llvm::BasicBlock::Create(builder->getContext(), "success", mainFunction); - auto failBlock = llvm::BasicBlock::Create(builder->getContext(), "fail", mainFunction); - auto continueBlock = llvm::BasicBlock::Create(builder->getContext(), "continue", mainFunction); - createCondBr(shouldContinue, successBlock, failBlock); - builder->SetInsertPoint(successBlock); - builder->CreateStore( - builder->CreateAdd(builder->CreateLoad(builder->getInt32Ty(), successCount), builder->getInt32(1)), - successCount - ); - builder->CreateBr(continueBlock); - builder->SetInsertPoint(failBlock); - builder->CreateStore( - builder->CreateAdd(builder->CreateLoad(builder->getInt32Ty(), failCount), builder->getInt32(1)), failCount - ); - builder->CreateBr(continueBlock); - builder->SetInsertPoint(continueBlock); - } - testIndex++; - } - if (ctx->tests.size() == 0) { - builder->CreateCall( - printFunction, { - builder->CreateGlobalStringPtr( - FMT("\n%s" - " Oops! It seems like our tests have gone on vacation!\n\n" - " They must be off sunbathing on a tropical beach or enjoying some\n" - " well-deserved rest.\n\n" - " While they're out having fun, why don't you \n" - " take this opportunity to show off your code's confidence by giving\n" - " it a high-five?\n\n" - " Remember, real programmers write self-assured code that\n" - " doesn't need tests to prove its awesomeness! 😉%s\n", - BYEL, - RESET), - "test.msg" - ) - } - ); - } - builder->CreateCall(printFunction, {builder->CreateGlobalStringPtr(FMT("\nTest results:\n"), "test.msg")}); - builder->CreateCall( - printFunction, { - builder->CreateGlobalStringPtr(FMT(" %s+ %%i%s test(s) passed; ", BGRN, RESET), "test.msg"), - builder->CreateLoad(builder->getInt32Ty(), successCount) - } - ); - builder->CreateCall( - printFunction, { - builder->CreateGlobalStringPtr(FMT("\n %s- %%i%s test(s) failed; ", BRED, RESET), "test.msg"), - builder->CreateLoad(builder->getInt32Ty(), failCount) - } - ); - builder->CreateCall( - printFunction, { - builder->CreateGlobalStringPtr(FMT("\n %s? %%i%s test(s) skipped; ", BYEL, RESET), "test.msg"), - builder->getInt32(skipCount) - } - ); - builder->CreateCall( - printFunction, { - builder->CreateGlobalStringPtr( - FMT("\n %s= %%i%s executed test(s) total\n" - " %s=> %%i%%%s of the tests passed. 🧪\n\n", - BOLD, - RESET, - BOLD, - RESET), - "test.msg" - ), - builder->CreateAdd( - builder->CreateLoad(builder->getInt32Ty(), successCount), - builder->CreateLoad(builder->getInt32Ty(), failCount) - ), - testIndex == 1 ? builder->getInt32(0) // Prevent division by zero - : - builder->CreateMul( - builder->CreateSDiv( - builder->CreateLoad(builder->getInt32Ty(), successCount), - builder->CreateAdd( - builder->CreateLoad(builder->getInt32Ty(), successCount), - builder->CreateLoad(builder->getInt32Ty(), failCount) - ) - ), - builder->getInt32(100) - ) - } - ); - builder->CreateBr(end); - builder->SetInsertPoint(end); - // TODO: dynamic if tests fail - builder->CreateRet(builder->getInt32(0)); - // auto DISubprogram = llvmFn->getSubprogram(); - // dbg.builder->finalizeSubprogram(DISubprogram); - std::string module_error_string; - llvm::raw_string_ostream module_error_stream(module_error_string); - llvm::verifyFunction(*mainFunction, &module_error_stream); - if (!module_error_string.empty()) { -#ifdef _SNOWBALL_BYTECODE_DEBUG - dump(); -#endif - throw SNError(Error::LLVM_INTERNAL, module_error_string); - } -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/createVirtualTable.cc b/src/builder/llvm/createVirtualTable.cc deleted file mode 100644 index 1b5db4bd..00000000 --- a/src/builder/llvm/createVirtualTable.cc +++ /dev/null @@ -1,54 +0,0 @@ - -#include "../../ir/values/Call.h" -#include "../../services/OperatorService.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include -#include -#include -#include -#include - -namespace snowball { -namespace codegen { - -llvm::GlobalVariable* LLVMBuilder::createVirtualTable(types::BaseType* ty, llvm::StructType* vtableType) { - auto structName = (std::string) _SN_VTABLE_PREFIX + ty->getMangledName(); - std::vector functions = { - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(*context)), - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(*context)), // TODO: class info - }; - ty = ctx->typeInfo.at(ty->getId()).get(); - for (auto fn : ty->getVTable()) { - if (fn->isDeclaration()) { - functions.push_back(llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(*context))); - continue; - } - auto c = llvm::cast(funcs.at(fn->getId())); - functions.push_back(c); - } - auto vTy = ctx->getVtableTy(ty->getId()); - assert(vTy && "Vtable type not found!"); - vTy->setBody(llvm::ArrayType::get(llvm::Type::getInt8PtrTy(*context), functions.size())); - module->getOrInsertGlobal(structName, vtableType); - auto vTable = module->getNamedGlobal(structName); - vTable->setLinkage(llvm::GlobalValue::LinkageTypes::InternalLinkage); - vTable->setConstant(true); - vTable->setDSOLocal(true); - vTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - // set comdat any -#ifdef __linux__ - vTable->setComdat(module->getOrInsertComdat(structName)); -#endif - auto arr = llvm::ConstantArray::get( - llvm::ArrayType::get(llvm::Type::getInt8PtrTy(*context), functions.size()), functions - ); - auto s = llvm::ConstantStruct::get(vtableType, arr); - vTable->setInitializer(s); - return vTable; -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/getAllocaFunction.cc b/src/builder/llvm/getAllocaFunction.cc deleted file mode 100644 index 7ddb7b99..00000000 --- a/src/builder/llvm/getAllocaFunction.cc +++ /dev/null @@ -1,26 +0,0 @@ - -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include -#include -#include - -namespace snowball { -namespace codegen { - -llvm::Function* LLVMBuilder::getAllocaFunction() { - auto ty = llvm::FunctionType::get(builder->getInt8PtrTy(), {builder->getInt32Ty()}, false); - auto f = llvm::cast(module->getOrInsertFunction("malloc", ty).getCallee()); - f->addRetAttr(llvm::Attribute::NonNull); - f->addRetAttr(llvm::Attribute::NoAlias); - f->addRetAttr(llvm::Attribute::NoUndef); - f->setDoesNotThrow(); - f->setCannotDuplicate(); - f->setDoesNotRecurse(); - return f; -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/getGlobalCTOR.cc b/src/builder/llvm/getGlobalCTOR.cc deleted file mode 100644 index 81b2c3d0..00000000 --- a/src/builder/llvm/getGlobalCTOR.cc +++ /dev/null @@ -1,55 +0,0 @@ - -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include -#include -#include - -namespace snowball { -namespace codegen { - -llvm::Function* LLVMBuilder::getGlobalCTOR(bool createIfNone) { - auto mangle = (std::string) "_GLOBAL__I" + ".GlobalInit.Snowball:" + iModule->getUniqueName(); - auto fn = module->getFunction(mangle); - if ((!fn) && createIfNone) { - auto prototype = llvm::FunctionType::get(builder->getVoidTy(), {}); - fn = h.create(prototype, llvm::Function::InternalLinkage, mangle, *module); -#ifdef __linux__ - fn->setSection(".text.startup"); -#elif __APPLE__ - fn->setSection("__TEXT,__text"); -#endif - fn->setCallingConv(llvm::CallingConv::C); - auto file = dbg.getFile(iModule->getSourceInfo()->getPath()); - auto subroutineType = dbg.builder->createSubroutineType(llvm::MDTuple::get(*context, {})); - auto subprogram = dbg.builder->createFunction( - file, - FMT("Global constructor for module %s", iModule->getName().c_str()), - mangle, - file, - 0, - llvm::cast(subroutineType), - /*ScopeLine=*/0, - llvm::DINode::FlagPrototyped, - llvm::DISubprogram::toSPFlags( - /*IsLocalToUnit=*/true, - /*IsDefinition=*/true, - /*IsOptimized=*/!dbg.debug - ) - ); - fn->setSubprogram(subprogram); - // TODO: set di info - } else if (fn) { - return fn; - } else if (!fn && (!createIfNone)) { - return nullptr; - } - h.create(builder->getContext(), "body", fn); - llvm::appendToGlobalCtors(*module, fn, 65535); - return fn; -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/getLambdaContextType.cc b/src/builder/llvm/getLambdaContextType.cc deleted file mode 100644 index ec15fe25..00000000 --- a/src/builder/llvm/getLambdaContextType.cc +++ /dev/null @@ -1,17 +0,0 @@ - -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include -#include - -namespace snowball { -namespace codegen { - -llvm::StructType* LLVMBuilder::getLambdaContextType() { - return llvm::StructType::get(builder->getInt8PtrTy(), builder->getInt8PtrTy()); -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/getPrintfFunction.cc b/src/builder/llvm/getPrintfFunction.cc deleted file mode 100644 index e7e29cd1..00000000 --- a/src/builder/llvm/getPrintfFunction.cc +++ /dev/null @@ -1,19 +0,0 @@ - -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include -#include - -namespace snowball { -namespace codegen { - -llvm::Function* LLVMBuilder::getPrintfFunction() { - auto ty = llvm::FunctionType::get(builder->getInt32Ty(), {builder->getInt8PtrTy()}, true); - auto f = llvm::cast(module->getOrInsertFunction("printf", ty).getCallee()); - return f; -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/getSharedLibraryName.cc b/src/builder/llvm/getSharedLibraryName.cc deleted file mode 100644 index f27b026d..00000000 --- a/src/builder/llvm/getSharedLibraryName.cc +++ /dev/null @@ -1,21 +0,0 @@ - -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include -#include - -namespace snowball { -namespace codegen { - -std::string LLVMBuilder::getSharedLibraryName(std::string name) { -#if defined(__APPLE__) - return "\x01" + name; -#else - return name; -#endif -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/getThrowFunction.cc b/src/builder/llvm/getThrowFunction.cc deleted file mode 100644 index 6e99f1b8..00000000 --- a/src/builder/llvm/getThrowFunction.cc +++ /dev/null @@ -1,19 +0,0 @@ - -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include -#include - -namespace snowball { -namespace codegen { - -std::pair LLVMBuilder::getThrowFunction() { - auto ty = llvm::FunctionType::get(builder->getVoidTy(), {builder->getInt8PtrTy()}, false); - auto f = llvm::cast(module->getOrInsertFunction(getSharedLibraryName("sn.eh.throw"), ty).getCallee()); - return {ty, f}; -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/getTypeInfoType.cc b/src/builder/llvm/getTypeInfoType.cc deleted file mode 100644 index a4266e82..00000000 --- a/src/builder/llvm/getTypeInfoType.cc +++ /dev/null @@ -1,15 +0,0 @@ - -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include -#include - -namespace snowball { -namespace codegen { - -llvm::StructType* LLVMBuilder::getTypeInfoType() { return llvm::StructType::get(builder->getInt32Ty()); } - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/getVtableType.cc b/src/builder/llvm/getVtableType.cc deleted file mode 100644 index 17f0b88d..00000000 --- a/src/builder/llvm/getVtableType.cc +++ /dev/null @@ -1,21 +0,0 @@ - -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include -#include - -namespace snowball { -namespace codegen { - -llvm::StructType* LLVMBuilder::getVtableType(types::BaseType* ty) { - auto t = llvm::StructType::create(*context, (std::string) _SN_VTABLE_PREFIX + ty->getMangledName()); - auto arrType = llvm::ArrayType::get(llvm::Type::getInt8PtrTy(*context), ty->getVtableSize() + 2); - t->setBody(arrType); - ctx->addVtableTy(ty->getId(), t); - return t; -} - -} // namespace codegen -} // namespace snowball \ No newline at end of file diff --git a/src/builder/llvm/helpers/emitObjectFile.cc b/src/builder/llvm/helpers/emitObjectFile.cc deleted file mode 100644 index c18a2eb6..00000000 --- a/src/builder/llvm/helpers/emitObjectFile.cc +++ /dev/null @@ -1,57 +0,0 @@ - -#include "../../../errors.h" -#include "../../../utils/utils.h" -#include "../LLVMBuilder.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace snowball { -namespace codegen { - -int LLVMBuilder::emitObjectFile(std::string out, bool log, bool object) { - std::error_code EC; - llvm::raw_fd_ostream dest(out, EC, llvm::sys::fs::OF_None); - if (EC) { throw SNError(Error::IO_ERROR, FMT("Could not open file: %s", EC.message().c_str())); } - llvm::legacy::PassManager pass; - auto FileType = object ? llvm::CGFT_ObjectFile : llvm::CGFT_AssemblyFile; - DEBUG_CODEGEN("Emitting object file... (%s)", out.c_str()); - if (target->addPassesToEmitFile(pass, dest, nullptr, FileType)) { - remove(out.c_str()); - throw SNError(Error::LLVM_INTERNAL, "TargetMachine can't emit a file of this type"); - } - if (log) Logger::success("Snowball project compiled to an object file! ✨\n"); - DEBUG_CODEGEN("Running object pass manager..."); - pass.run(*module.get()); - dest.flush(); - return EXIT_SUCCESS; -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/helpers/optimizeModule.cc b/src/builder/llvm/helpers/optimizeModule.cc deleted file mode 100644 index af79a5b7..00000000 --- a/src/builder/llvm/helpers/optimizeModule.cc +++ /dev/null @@ -1,142 +0,0 @@ - -#include "../../../common.h" -#include "../../../utils/utils.h" -#include "../LLVMBuilder.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace snowball { - -namespace { -void applyDebugTransformations(llvm::Module* module, bool debug) { - if (debug) { - // remove tail calls and fix linkage for stack traces - for (auto& f : *module) { - //#ifdef __APPLE__ - //f.setLinkage(llvm::GlobalValue::ExternalLinkage); - //#endif - if (!f.hasFnAttribute(llvm::Attribute::AttrKind::AlwaysInline)) - f.addFnAttr(llvm::Attribute::AttrKind::NoInline); - f.setUWTableKind(llvm::UWTableKind::Default); - f.addFnAttr("no-frame-pointer-elim", "true"); - f.addFnAttr("no-frame-pointer-elim-non-leaf"); - f.addFnAttr("no-jump-tables", "false"); - } - } else { - llvm::StripDebugInfo(*module); - } -} -} // namespace - -#ifndef PERFORM_SIMPLE_OPTS -#define PERFORM_SIMPLE_OPTS 1 -#endif - -namespace codegen { - -void LLVMBuilder::optimizeModule() { - llvm::LoopAnalysisManager loop_analysis_manager; - llvm::FunctionAnalysisManager function_analysis_manager; - llvm::CGSCCAnalysisManager c_gscc_analysis_manager; - llvm::ModuleAnalysisManager module_analysis_manager; - // Create the new pass manager builder. - // Take a look at the PassBuilder constructor parameters for more - // customization, e.g. specifying a TargetMachine or various - // debugging options. - llvm::PassBuilder pass_builder; - // Register all the basic analyses with the managers. - pass_builder.registerModuleAnalyses(module_analysis_manager); - pass_builder.registerCGSCCAnalyses(c_gscc_analysis_manager); - pass_builder.registerFunctionAnalyses(function_analysis_manager); - pass_builder.registerLoopAnalyses(loop_analysis_manager); - llvm::Triple moduleTriple(module->getTargetTriple()); - llvm::TargetLibraryInfoImpl tlii(moduleTriple); - // cross register them too? - pass_builder.crossRegisterProxies( - loop_analysis_manager, function_analysis_manager, c_gscc_analysis_manager, module_analysis_manager - ); - function_analysis_manager.registerPass([&] { return llvm::TargetLibraryAnalysis(tlii); }); - llvm::OptimizationLevel level; - switch (ctx->optimizationLevel) { - case app::Options::Optimization::OPTIMIZE_O0: level = llvm::OptimizationLevel::O0; break; - case app::Options::Optimization::OPTIMIZE_O1: level = llvm::OptimizationLevel::O1; break; - case app::Options::Optimization::OPTIMIZE_O2: level = llvm::OptimizationLevel::O2; break; - case app::Options::Optimization::OPTIMIZE_O3: level = llvm::OptimizationLevel::O3; break; - case app::Options::Optimization::OPTIMIZE_Os: level = llvm::OptimizationLevel::Os; break; - case app::Options::Optimization::OPTIMIZE_Oz: level = llvm::OptimizationLevel::Oz; break; - default: assert(false && "during code optimization"); - } - std::vector> PipelineStartEPCallbacks; - std::vector> OptimizerLastEPCallbacks; - PipelineStartEPCallbacks.push_back([](llvm::ModulePassManager & MPM, llvm::OptimizationLevel Level) { - MPM.addPass(llvm::VerifierPass()); - }); - for (const auto& C : PipelineStartEPCallbacks) pass_builder.registerPipelineStartEPCallback(C); - for (const auto& C : OptimizerLastEPCallbacks) pass_builder.registerOptimizerLastEPCallback(C); - llvm::ModulePassManager mpm; - if (dbg.debug) { - mpm = pass_builder.buildThinLTODefaultPipeline(level, nullptr); - } else { -#if PERFORM_SIMPLE_OPTS - { - // simple optimizations done for each function. It does not depend on the optimization level. - std::unique_ptr functionPassManager = - std::make_unique(module.get()); - - // Promote allocas to registers. - functionPassManager->add(llvm::createPromoteMemoryToRegisterPass()); - // Do simple "peephole" optimizations - functionPassManager->add(llvm::createInstructionCombiningPass()); - // Reassociate expressions. - functionPassManager->add(llvm::createReassociatePass()); - // Eliminate Common SubExpressions. - functionPassManager->add(llvm::createGVNPass()); - // Simplify the control flow graph (deleting unreachable blocks etc). - functionPassManager->add(llvm::createCFGSimplificationPass()); - - functionPassManager->doInitialization(); - - for (auto& function : module->getFunctionList()) { functionPassManager->run(function); } - } - llvm::legacy::PassManager codegen_pm; - codegen_pm.add(llvm::createTargetTransformInfoWrapperPass(target->getTargetIRAnalysis())); - codegen_pm.run(*module); -#endif - mpm = pass_builder.buildLTOPreLinkDefaultPipeline(level); - } - mpm.run(*module, module_analysis_manager); - applyDebugTransformations(module.get(), dbg.debug); -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/initializeRuntime.cc b/src/builder/llvm/initializeRuntime.cc deleted file mode 100644 index 488910a5..00000000 --- a/src/builder/llvm/initializeRuntime.cc +++ /dev/null @@ -1,77 +0,0 @@ - -#include "../../utils/utils.h" -#include "../../../runtime/libs/runtime.h" -#include "LLVMBuilder.h" - -#include -#include -#include - -namespace snowball { -namespace codegen { - -#define CALL_INITIALIZERS \ - builder->CreateCall(f, {flagsInt}); \ - if (envArgv) \ - builder->CreateCall(envArgv, {argc, argv}); - -void LLVMBuilder::initializeRuntime() { - auto ty = llvm::FunctionType::get(builder->getVoidTy(), {builder->getInt32Ty()}, false); - auto f = llvm::cast( - module->getOrInsertFunction(getSharedLibraryName("sn.runtime.initialize"), ty).getCallee() - ); - f->addFnAttr(llvm::Attribute::AlwaysInline); - f->addFnAttr(llvm::Attribute::NoUnwind); - const int flags = (dbg.debug ? SNOWBALL_FLAG_DEBUG : 0) | 0; - auto envArgv = module->getFunction("sn.env.set_argv"); - auto mainFunction = module->getFunction(_SNOWBALL_FUNCTION_ENTRY); - bool buildReturn = false; - llvm::BasicBlock* body; - auto fnType = llvm::FunctionType::get(builder->getInt32Ty(), {builder->getInt32Ty(), builder->getInt8PtrTy()->getPointerTo()}, - false); - if (mainFunction) { - if (ctx->testMode) { - mainFunction->eraseFromParent(); - mainFunction = (llvm::Function*) module->getOrInsertFunction(_SNOWBALL_FUNCTION_ENTRY, fnType).getCallee(); - setPersonalityFunction(mainFunction); - body = llvm::BasicBlock::Create(builder->getContext(), "test_entry", mainFunction); - } else if (ctx->benchmarkMode) { - mainFunction->eraseFromParent(); - mainFunction = (llvm::Function*) module->getOrInsertFunction(_SNOWBALL_FUNCTION_ENTRY, fnType).getCallee(); - setPersonalityFunction(mainFunction); - body = llvm::BasicBlock::Create(builder->getContext(), "benchmark_entry", mainFunction); - } else { - body = &mainFunction->front(); - } - } else { - mainFunction = (llvm::Function*) module->getOrInsertFunction(_SNOWBALL_FUNCTION_ENTRY, fnType).getCallee(); - setPersonalityFunction(mainFunction); - body = llvm::BasicBlock::Create(builder->getContext(), "entry", mainFunction); - buildReturn = !ctx->testMode; - } - builder->SetInsertPoint(body); - auto flagsInt = builder->getInt32(flags); - auto argc = mainFunction->arg_begin(); - argc->setName("argc"); - auto argv = std::next(mainFunction->arg_begin()); - argv->setName("argv"); - if (buildReturn) { - CALL_INITIALIZERS - builder->CreateRet(builder->getInt32(0)); - } else if (ctx->testMode) { - CALL_INITIALIZERS - createTests(mainFunction); - } else if (ctx->benchmarkMode) { - CALL_INITIALIZERS - createBenchmark(mainFunction); - } else { - llvm::CallInst::Create(f, {flagsInt}, "", &body->front()); - if (envArgv) { - auto debugLoc = llvm::DebugLoc(llvm::DILocation::get(*context, 0, 0, mainFunction->getSubprogram())); - llvm::CallInst::Create(envArgv, {argc, argv}, "", &body->front())->setDebugLoc(debugLoc); - } - } -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/initializeVariable.cc b/src/builder/llvm/initializeVariable.cc deleted file mode 100644 index e6694636..00000000 --- a/src/builder/llvm/initializeVariable.cc +++ /dev/null @@ -1,48 +0,0 @@ -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include -#include - -namespace snowball { -namespace codegen { - -void LLVMBuilder::initializeVariable(llvm::Value* var, llvm::Type* ty, unsigned int size) { - assert(llvm::isa(ty)); - auto llvmType = llvm::cast(ty); - auto initializerName = - FMT("__const.default.%s", llvmType->getName().str().c_str()); - auto constInitializer = module->getNamedGlobal(initializerName); - if (!constInitializer) { - std::vector elements; - for (auto field : llvmType->elements()) { - if (field->isPointerTy()) { - elements.push_back(llvm::ConstantPointerNull::get(llvm::cast(field))); - } else if (field->isStructTy()) { - elements.push_back(llvm::UndefValue::get(field)); - } else { - elements.push_back(llvm::Constant::getNullValue(field)); - } - } - auto structInitializer = llvm::ConstantStruct::get(llvmType, elements); - constInitializer = new llvm::GlobalVariable( - *module, - llvmType, - true, - llvm::GlobalValue::PrivateLinkage, - structInitializer, - initializerName, - nullptr, - llvm::GlobalVariable::NotThreadLocal - ); - constInitializer->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - } - auto dataLayout = module->getDataLayout(); - auto layout = dataLayout.getTypeSizeInBits(llvmType); - //builder->CreateMemCpy(var, llvm::MaybeAlign(), constInitializer, llvm::MaybeAlign(), layout/8); - builder->CreateStore(llvm::Constant::getNullValue(llvmType), var); -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/llvmTypes.cc b/src/builder/llvm/llvmTypes.cc deleted file mode 100644 index 3dc17ee0..00000000 --- a/src/builder/llvm/llvmTypes.cc +++ /dev/null @@ -1,152 +0,0 @@ - -#include "../../ast/errors/error.h" -#include "../../utils/utils.h" -#include "../../services/ImportService.h" -#include "../../ast/types/EnumType.h" -#include "LLVMBuilder.h" - -#include -#include -#include -#include - -using namespace snowball::utils; - -namespace snowball { -namespace codegen { - -llvm::Type* LLVMBuilder::getLLVMType(types::Type* t, bool translateVoid, bool ignoreMemorySize) { - if (auto x = cast(t)) { - if (x->getBits() == 1 && !ignoreMemorySize) return builder->getInt8Ty(); - return builder->getIntNTy(x->getBits()); - } else if (auto x = cast(t)) { - switch (x->getBits()) { - case 16: return builder->getHalfTy(); - case 32: return builder->getFloatTy(); - case 64: return builder->getDoubleTy(); - default: assert(!"Unreachable type case found!"); - } - } else if (cast(t)) { - return translateVoid ? builder->getInt8Ty() : builder->getVoidTy(); - } else if (auto x = cast(t)) { - return getLLVMType(x->getPointedType())->getPointerTo(); - } else if (auto x = cast(t)) { - if (is(x->getPointedType())) return builder->getInt8PtrTy(); - return getLLVMType(x->getPointedType())->getPointerTo(); - } else if (auto f = cast(t)) { - return getLLVMFunctionType(f)->getPointerTo(); // return getLambdaContextType()->getPointerTo() if lambda - } else if (auto a = cast(t)) { - assert(!"Unreachable type case found!"); - return getLLVMType(a->getBaseType()); - } else if (auto e = cast(t)) { - if (types.find(e->getId()) != types.end()) return types.find(e->getId())->second; - auto size = e->sizeOf(); - auto type = llvm::StructType::create(*context, _SN_ENUM_PREFIX + e->getMangledName()); - type->setBody({builder->getInt8Ty(), llvm::ArrayType::get(builder->getInt8Ty(), (size / 8) - 1)}); - types.insert({e->getId(), type}); - return type; - } else if (auto c = cast(t)) { - llvm::StructType* s; - if (auto it = types.find(c->getId()); it != types.end()) { - return it->second; - } else { - auto isStruct = utils::cast(c); - s = llvm::StructType::create( - *context, - ((isStruct && isStruct->isStruct()) ? _SN_STRUCT_PREFIX : _SN_CLASS_PREFIX) + c->getMangledName() - ); - types.insert({c->getId(), s}); - assert(ctx->typeInfo.find(c->getId()) != ctx->typeInfo.end()); - c = ctx->typeInfo.find(c->getId())->second.get(); - } - std::vector generatedFields; - if (auto c = utils::cast(t)) { - auto fields = c->getFields(); - generatedFields = vector_iterate( - fields, [&](types::DefinedType::ClassField * t) { return getLLVMType(t->type); } - ); - } else if (auto c = utils::cast(t)) { - auto fields = c->getFields(); - generatedFields = - vector_iterate(fields, [&](types::InterfaceType::Member * t) { - return getLLVMType(t->type); - }); - } else { - Syntax::E(FMT("Undefined type! ('%s')", t->getName().c_str())); - } - if (c->hasVtable) { - (void)getVtableType(c); // generate vtable type - generatedFields.insert( - generatedFields.begin(), - llvm::FunctionType::get(builder->getInt32Ty(), {}, true)->getPointerTo()->getPointerTo() - ); - } else if (auto x = utils::cast(c); x && x->hasParent()) { - auto p = x; - while (p->hasParent()) { - p = p->getParent(); - p = utils::cast(ctx->typeInfo.find(p->getId())->second.get()); - if (!p) break; - (void)getVtableType(p); // generate vtable type - generatedFields.insert( - generatedFields.begin(), - llvm::FunctionType::get(builder->getInt32Ty(), {}, true)->getPointerTo()->getPointerTo() - ); - } - } - s->setBody(generatedFields); - return s; - } else { - Syntax::E(FMT("Undefined type! ('%s')", t->getName().c_str())); - } - assert(false); - return nullptr; // to avoid warnings -} - -llvm::FunctionType* LLVMBuilder::getLLVMFunctionType(types::FunctionType* fn, const ir::Func* func) { - auto argTypes = - vector_iterate(fn->getArgs(), [&](types::Type * arg) { return getLLVMType(arg); }); - auto ret = getLLVMType(fn->getRetType()); - if (func && func->isAnon()) { - argTypes.insert(argTypes.begin(), getLambdaContextType()->getPointerTo()); - } - if (utils::is(fn->getRetType()) && - !(func && func->getAttributeArgs(Attributes::LLVM_FUNC).count("sanitise_void_return"))) { - argTypes.insert(argTypes.begin(), ret->getPointerTo()); - ret = builder->getVoidTy(); - } - if (func && func->getAttributeArgs(Attributes::LLVM_FUNC).count("sanitise_void_return")) { - if (ret->isVoidTy()) { ret = builder->getInt8Ty(); } - } - return llvm::FunctionType::get(ret, argTypes, fn->isVariadic()); -} - -llvm::Type* LLVMBuilder::createEnumFieldType(types::EnumType* ty, std::string field) { - static std::unordered_map enumTypes; - auto name = _SN_ENUM_PREFIX + ty->getMangledName() + "__" + field; - if (enumTypes.find(name) != enumTypes.end()) return enumTypes.find(name)->second; - auto enumField = *std::find_if(ty->getFields().begin(), ty->getFields().end(), [&](auto f) { - return f.name == field; - }); - auto dataLayout = module->getDataLayout(); - auto enumSize = dataLayout.getStructLayout((llvm::StructType*)getLLVMType(ty))->getSizeInBits(); - // convert this to a struct and an array of bytes at the end to fix alignment issues - auto type = llvm::StructType::create(*context, name); - auto fieldTypes = enumField.types; - int fieldSize = 0; - std::vector generatedFields; - generatedFields.push_back(builder->getInt8Ty()); // enum field - for (auto t : fieldTypes) { - auto llvmType = getLLVMType(t); - fieldSize += t->sizeOf() * 8; - generatedFields.push_back(llvmType); - } - auto rem = (enumSize - (fieldSize - 8)) / 8 / 8; - if (rem > 0) - generatedFields.push_back(llvm::ArrayType::get(builder->getInt8Ty(), rem)); - type->setBody(generatedFields); - enumTypes.insert({name, type}); - return type; -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/setDebugInfoLoc.cc b/src/builder/llvm/setDebugInfoLoc.cc deleted file mode 100644 index 2f93c879..00000000 --- a/src/builder/llvm/setDebugInfoLoc.cc +++ /dev/null @@ -1,29 +0,0 @@ - -#include "../../ast/errors/error.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include -#include -#include - -using namespace snowball::utils; - -namespace snowball { -namespace codegen { - -void LLVMBuilder::setDebugInfoLoc(ir::Value* v) { - if (v) { - auto info = v->getDBGInfo(); - if (auto f = ctx->getCurrentFunction(); (info != nullptr && f != nullptr)) { - auto loc = llvm::DILocation::get(*context, info->line, info->pos.second, f->getSubprogram()); - builder->SetCurrentDebugLocation(loc); - return; - } - } - builder->SetCurrentDebugLocation(llvm::DebugLoc()); -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/setPersonalityFunction.cc b/src/builder/llvm/setPersonalityFunction.cc deleted file mode 100644 index e703ef61..00000000 --- a/src/builder/llvm/setPersonalityFunction.cc +++ /dev/null @@ -1,33 +0,0 @@ - -#include "../../ast/errors/error.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include -#include -#include - -using namespace snowball::utils; - -namespace snowball { -namespace codegen { - -void LLVMBuilder::setPersonalityFunction(llvm::Function* func) { - auto ty = llvm::FunctionType::get( - builder->getInt32Ty(), { - builder->getInt32Ty(), - builder->getInt32Ty(), - builder->getInt64Ty(), - builder->getInt8PtrTy(), - builder->getInt8PtrTy() - }, - false - ); - auto c = module->getOrInsertFunction(getSharedLibraryName("sn.eh.personality"), ty).getCallee(); - auto f = llvm::cast(c); - func->setPersonalityFn(f); -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/toBool.cc b/src/builder/llvm/toBool.cc deleted file mode 100644 index 5d5af1c1..00000000 --- a/src/builder/llvm/toBool.cc +++ /dev/null @@ -1,30 +0,0 @@ - -#include "../../ast/errors/error.h" -#include "../../utils/utils.h" -#include "LLVMBuilder.h" - -#include -#include -#include -#include - -using namespace snowball::utils; - -namespace snowball { -namespace codegen { - -llvm::Value* LLVMBuilder::toBool(llvm::Value* v, bool isSigned) { - if (v->getType()->isIntegerTy()) { - if (v->getType()->getIntegerBitWidth() == 1) return v; - return builder->CreateICmpNE(v, llvm::ConstantInt::get(v->getType(), 0, isSigned)); - } else if (v->getType()->isFloatingPointTy()) { - return builder->CreateFCmpONE(v, llvm::ConstantFP::get(v->getType(), 0)); - } else if (v->getType()->isPointerTy()) { - return builder->CreateICmpNE(v, llvm::ConstantPointerNull::get(llvm::cast(v->getType()))); - } - Syntax::E("Unknown value type! Cannot convert to bool!"); - assert(false); -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/utils/typeIdxLookup.cc b/src/builder/llvm/utils/typeIdxLookup.cc deleted file mode 100644 index a1d5c79c..00000000 --- a/src/builder/llvm/utils/typeIdxLookup.cc +++ /dev/null @@ -1,21 +0,0 @@ -#include "../LLVMBuilder.h" - -namespace snowball { -namespace codegen { -namespace llvm_utils { -int typeIdxLookup(const std::string& name) { - static std::unordered_map cache; - static int next = 1000; - if (name.empty()) return 0; - auto it = cache.find(name); - if (it != cache.end()) { - return it->second; - } else { - const int myID = next++; - cache[name] = myID; - return myID; - } -} -} // namespace llvm_utils -} // namespace codegen -} // namespace snowball diff --git a/src/builder/llvm/varFetchImpl.h b/src/builder/llvm/varFetchImpl.h deleted file mode 100644 index 205412e3..00000000 --- a/src/builder/llvm/varFetchImpl.h +++ /dev/null @@ -1,37 +0,0 @@ - -#ifndef GET_VAR_IMPL - -// note(argument): "x + 1" because ir::Argument (x - 1) gets -// created after ir::Variable (x). note(note argument): They are -// declared as usual with normal ID incrementation -#define GET_VAR_IMPL(variable, value) \ - auto x = ctx->getCurrentIRFunction();\ - if (x && variable->isUsedInLambda()) {\ - llvm::Value* arg = nullptr;\ - LLVMBuilderContext::ClosureContext closure;\ - if (x->getId() != variable->getParentFunc()->getId()) {\ - closure = ctx->closures.at(x->getParentScope()->getId());\ - int argumentIndex = 0;\ - if (utils::is(x->getRetTy()))\ - argumentIndex++;\ - arg = builder->CreateLoad(closure.closureType->getPointerTo(), builder->CreateStructGEP(getLambdaContextType(), ctx->getCurrentFunction()->getArg(argumentIndex), 1));\ - } else {\ - closure = ctx->closures.at(x->getId());\ - arg = closure.closure; \ - }\ - auto index = std::distance(\ - closure.variables.begin(),\ - std::find_if(\ - closure.variables.begin(),\ - closure.variables.end(),\ - [variable](auto v2) { return v2 == variable->getId(); }\ - )\ - );\ - assert(index != (int)closure.variables.size());\ - value = builder->CreateStructGEP(closure.closureType, arg, index);\ - } else {\ - auto id = variable->getId();\ - value = ctx->getSymbol(id);\ - } - -#endif // GET_VAR_IMPL diff --git a/src/builder/sn-ir/SnowballIREmitter.cc b/src/builder/sn-ir/SnowballIREmitter.cc deleted file mode 100644 index 3ce8f919..00000000 --- a/src/builder/sn-ir/SnowballIREmitter.cc +++ /dev/null @@ -1,237 +0,0 @@ - -#include "SnowballIREmitter.h" -#include "../../ir/module/MainModule.h" -#include "../../ir/module/Module.h" -#include "../../ir/values/all.h" -#include "../llvm/LLVMIRChunk.h" - -namespace snowball { -namespace codegen { - -SnowballIREmitter::SnowballIREmitter(std::shared_ptr p_module) : module(p_module) { } - -void SnowballIREmitter::codegen(std::string p_output) { - auto mainModule = utils::dyn_cast(module); - assert(mainModule); - for (auto m : mainModule->getModules()) visit(m); - visit(mainModule); - // write content to file - std::ofstream file(p_output); - file << output.str(); - file.close(); -} - -void SnowballIREmitter::addContent(std::string str) { output << str; } - -void SnowballIREmitter::visit(std::shared_ptr m) { - addContent("module " + m->getName() + " {\n"); - for (auto v : m->getVariables()) { - addContent(" var " + v->getIdentifier() + " : " + v->getType()->getPrettyName()); - if (v->getValue()) { - addContent(" = "); - v->getValue()->visit(this); - } - addContent(";\n"); - } - for (auto f : m->getFunctions()) { - if (f->isExternal(f->getMangle())) - addContent(" external "); - else - addContent(" "); - addContent("func " + f->getNiceName() + "("); - for (auto p : f->getArgs()) { - p.second->visit(this); - if (p != f->getArgs().back()) addContent(", "); - } - addContent(") : " + f->getRetTy()->getPrettyName()); - if (f->isExternal(f->getMangle())) - addContent(";\n"); - else if (f->hasAttribute(Attributes::LLVM_FUNC)) { - addContent(" [LLVM] {\n"); - for (const auto& chunk : f->getLLVMBody()) { - if (chunk.type == Syntax::LLVMIRChunk::TypeAccess) { - addContent(chunk.ty->getMangledName()); - } else { - assert(chunk.type == Syntax::LLVMIRChunk::LLCode); - addContent(chunk.code); - } - } - addContent(" }\n"); - } else if (!f->isDeclaration()) { - addContent(" "); - f->getBody()->visit(this); - addContent("\n\n"); - } - } - addContent("}\n"); -} - -void SnowballIREmitter::visit(ir::Variable* v) { addContent(v->getIdentifier()); } - -void SnowballIREmitter::visit(ir::Func* f) { addContent(f->getNiceName()); } - -void SnowballIREmitter::visit(ir::Block* b) { - addContent("{\n"); - for (auto s : b->getBlock()) { - addContent(" "); - s->visit(this); - addContent("\n"); - } - addContent(" }"); -} - -void SnowballIREmitter::visit(ir::Return* r) { - addContent("return "); - if (r->getExpr()) r->getExpr()->visit(this); -} - -void SnowballIREmitter::visit(ir::Call* c) { - if (c->getCallee()) - c->getCallee()->visit(this); - else - addContent(""); - addContent("("); - for (auto a : c->getArguments()) { - a->visit(this); - if (a != c->getArguments().back()) addContent(", "); - } - addContent(")"); -} - -void SnowballIREmitter::visit(ir::Switch* s) { - addContent(s->isCStyleSwitch() ? "switch (" : "case ("); - s->getExpr()->visit(this); - addContent(") {\n"); - for (auto c : s->getCases().first) { - addContent(" case " + c.name); - addContent("("); - for (auto a : c.args) { - addContent(a->getIdentifier()); - if (a != c.args.back()) addContent(", "); - } - addContent(") => "); - c.block->visit(this); - addContent("\n"); - } - for (auto c : s->getCases().second) { - addContent(" case "); - c.value->visit(this); - addContent(" => "); - c.block->visit(this); - addContent("\n"); - } - addContent(" }"); -} - -void SnowballIREmitter::visit(ir::Conditional* c) { - addContent("if ("); - c->getCondition()->visit(this); - addContent(") "); - c->getBlock()->visit(this); - if (c->getElse()) { - addContent(" else "); - c->getElse()->visit(this); - } -} - -void SnowballIREmitter::visit(ir::WhileLoop* w) { - addContent("while ("); - w->getCondition()->visit(this); - addContent(") "); - w->getBlock()->visit(this); -} - -void SnowballIREmitter::visit(ir::Cast* c) { - addContent("cast<"); - addContent(c->getCastType()->getPrettyName()); - addContent(">("); - c->getExpr()->visit(this); - addContent(")"); -} - -void SnowballIREmitter::visit(ir::TryCatch* tc) { - addContent("try "); - tc->getBlock()->visit(this); - for (auto i = 0; i < (int)tc->getCatchBlocks().size(); i++) { - addContent(" catch ("); - tc->getCatchVars()[i]->visit(this); - addContent(": "); - addContent(tc->getCatchVars()[i]->getType()->getPrettyName()); - addContent(") "); - tc->getCatchBlocks()[i]->visit(this); - } -} - -void SnowballIREmitter::visit(ir::EnumInit* ei) { - addContent(ei->getType()->getPrettyName() + "::" + ei->getName()); -} - -void SnowballIREmitter::visit(ir::Throw* t) { - addContent("throw "); - t->getExpr()->visit(this); -} - -void SnowballIREmitter::visit(ir::VariableDeclaration* vd) { - addContent("(" + vd->getIdentifier()); - if (vd->getValue()) { - addContent(" = "); - vd->getValue()->visit(this); - } - addContent(")"); -} - -void SnowballIREmitter::visit(ir::IndexExtract* ie) { - addContent("("); - ie->getValue()->visit(this); - addContent(")"); - addContent(" get element at "); - addContent(std::to_string(ie->getIndex())); - addContent(" (field: " + ie->getField()->name + ")"); -} - -void SnowballIREmitter::visit(ir::ValueExtract* ve) { - addContent("load "); - ve->getValue()->visit(this); -} - -void SnowballIREmitter::visit(ir::Argument* a) { - addContent(a->getIdentifier()); - addContent(": "); - addContent(a->getType()->getPrettyName()); -} - -void SnowballIREmitter::visit(ir::NumberValue* nv) { addContent(std::to_string(nv->getConstantValue())); } - -void SnowballIREmitter::visit(ir::BooleanValue* bv) { addContent(bv->getConstantValue() ? "true" : "false"); } - -void SnowballIREmitter::visit(ir::StringValue* sv) { addContent("\"" + sv->getConstantValue() + "\""); } - -void SnowballIREmitter::visit(ir::FloatValue* fv) { addContent(std::to_string(fv->getConstantValue())); } - -void SnowballIREmitter::visit(ir::CharValue* cv) { addContent("\'" + std::to_string(cv->getConstantValue()) + "\'"); } - -void SnowballIREmitter::visit(ir::ReferenceTo* rt) { - addContent("&("); - rt->getValue()->visit(this); - addContent(")"); -} - -void SnowballIREmitter::visit(ir::LoopFlow* lf) { - switch (lf->getFlowType()) { - case ir::LoopFlowType::Break: - addContent("break;\n"); - break; - case ir::LoopFlowType::Continue: - addContent("continue;\n"); - break; - } -} - -void SnowballIREmitter::visit(ir::DereferenceTo* d) { - addContent("*("); - d->getValue()->visit(this); - addContent(")"); -} - -} // namespace codegen -} // namespace snowball diff --git a/src/builder/sn-ir/SnowballIREmitter.h b/src/builder/sn-ir/SnowballIREmitter.h deleted file mode 100644 index 14f9e0c7..00000000 --- a/src/builder/sn-ir/SnowballIREmitter.h +++ /dev/null @@ -1,92 +0,0 @@ -#include "../../ValueVisitor/Visitor.h" -#include "../../ir/values/Value.h" -#include "../../sourceInfo/DBGSourceInfo.h" - -#include -#include -#include -#include -#include - -#ifndef __SNOWBALL_IR_EMITTER_H_ -#define __SNOWBALL_IR_EMITTER_H_ - -namespace snowball { -namespace codegen { - -/** - * @brief SnowballIREmitter class - * - * The SnowballIREmitter class is responsible for generating an Intermediate Representation (IR) - * code in the form of a string representation. This IR code represents a program's logic and structure - * and can serve as input for various subsequent stages of code generation and optimization. - * - * This class extends the ValueVisitor hierarchy, allowing it to traverse and visit different types - * of IR values to emit their corresponding string representations. It operates on a module, which - * encapsulates the entire program to be emitted. - * - * The SnowballIREmitter supports the following functionalities: - * - Generating IR code for different types of IR values by visiting them and converting them to strings. - * - Emitting the generated IR code to a specified output destination, such as a file or console. - * - Ensuring consistency and correctness by relying on the underlying IR value structure. - * - * The emitted IR code can then be utilized for various purposes, including debugging, optimization, - * and generating machine code or other target-specific representations. - */ -class SnowballIREmitter : public AcceptorExtend { - // Program represented by a module. - std::shared_ptr module; - // String representation of the emitted IR code. - std::stringstream output; - - public: - /** - * @brief Construct a SnowballIREmitter instance. - * @param mod The IR module to be emitted. - */ - SnowballIREmitter(std::shared_ptr mod); - - /** - * @brief Destructor for the SnowballIREmitter. - */ - ~SnowballIREmitter() noexcept = default; - - /** - * @brief Generate and emit the IR code to the specified output destination. - * @param output The output destination for the emitted IR code. - */ - void codegen(std::string output); - - // Deleting the default codegen() function to prevent accidental usage. - void codegen() override { assert(false); } - - private: - /** - * @brief Visit and emit IR code for a given IR value. - * @param v The IR value to be visited and emitted. - */ - void visit(ir::Value* v) { v->visit(this); } - - /** - * @brief Emit a new module. - * @param p_node The module to be emitted. - */ - void visit(std::shared_ptr p_node); - - /** - * @brief Add string content to the emitted IR code. - * @param p_node The string content to be added. - */ - void addContent(std::string str); - - // Define visit functions for various IR value types using the visits.def file. -#define VISIT(n) void visit(ir::n*) override; -#include "../../defs/visits.def" -#undef VISIT -}; - -} // namespace codegen -} // namespace snowball - -#undef VISIT -#endif // __SNOWBALL_IR_EMITTER_H_ diff --git a/src/common.h b/src/common.h deleted file mode 100644 index 941aeb1c..00000000 --- a/src/common.h +++ /dev/null @@ -1,52 +0,0 @@ - -#include - -#ifndef __SNOWBALL_COMMON_H_ -#define __SNOWBALL_COMMON_H_ - -namespace snowball { -template -class AcceptorExtend : public Parent { - public: - using Parent::Parent; -}; - -#if 0 -template -class enable_shared_from_base - : public std::enable_shared_from_this { - protected: - template - std::shared_ptr shared_from_base() { - return std::static_pointer_cast(shared_from_this()); - } -}; -#endif - -template -class InheritEnum { - public: - InheritEnum() { } - InheritEnum(EnumT e) : enum_(e) { } - - InheritEnum(BaseEnumT e) : baseEnum_(e) { } - - explicit InheritEnum(int val) : enum_(static_cast(val)) { } - - operator EnumT() const { return enum_; } - - private: - // Note - the value is declared as a union mainly for as a debugging aid. If - // the union is undesired and you have other methods of debugging, change it - // to either of EnumT and do a cast for the constructor that accepts BaseEnumT. - union { - EnumT enum_; - BaseEnumT baseEnum_; - }; -}; - -template -using UniquePtr = std::unique_ptr; -} // namespace snowball - -#endif // __SNOWBALL_COMMON_H_ diff --git a/src/compiler.cc b/src/compiler.cc deleted file mode 100644 index eec6c3c6..00000000 --- a/src/compiler.cc +++ /dev/null @@ -1,287 +0,0 @@ -#include "compiler.h" - -#include "builder/linker/Linker.h" -#include "builder/llvm/LLVMBuilder.h" -#include "builder/sn-ir/SnowballIREmitter.h" -#include "ir/module/MainModule.h" -#include "ir/module/Module.h" -#include "lexer/lexer.h" -#include "parser/Parser.h" -#include "pm/Manager.h" -#include "utils/utils.h" -#include "visitors/Analyzer.h" -#include "visitors/Transformer.h" -#include "visitors/TypeChecker.h" -#include "visitors/analyzers/DefinitveAssigment.h" -#include "visitors/documentation/DocGen.h" - -#include -#include -#include -#include -#include -#include - -namespace fs = std::filesystem; - -namespace snowball { -Compiler::Compiler(std::string p_code, std::string p_path) { - source = p_code; - cwd = fs::current_path(); - path = path / p_path; - srcInfo = nullptr; -} - -void Compiler::initialize() { - initialized = true; - createSourceInfo(); - globalContext = GlobalContext(); - globalContext.isTest = testsEnabled; - globalContext.isBench = benchmarkEnabled; - configFolder = cwd / ".sn"; - if (!fs::exists(configFolder)) fs::create_directory(configFolder); - if (!fs::exists(configFolder / "bin")) fs::create_directory(configFolder / "bin"); - if (!fs::exists(configFolder / "docs")) fs::create_directory(configFolder / "docs"); - if (!fs::exists(configFolder / "deps")) fs::create_directory(configFolder / "deps"); -} - -void Compiler::compile(bool silent) { - if (!initialized) { throw SNError(Error::COMPILER_ERROR, "Compiler has not been initialized!"); } -#if _SNOWBALL_TIMERS_DEBUG == 0 -#define SHOW_STATUS(status) \ - if (!silent) status; -#else -#define SHOW_STATUS(_) -#endif - runPackageManager(silent); - SHOW_STATUS(Logger::compiling(Logger::progress(0))); - /* ignore_goto_errors() */ { - SHOW_STATUS(Logger::compiling(Logger::progress(0.30))) - auto lexer = new Lexer(srcInfo); -#if _SNOWBALL_TIMERS_DEBUG - DEBUG_TIMER("Lexer: %fs", utils::_timer([&] { lexer->tokenize(); })); -#else - lexer->tokenize(); -#endif - auto tokens = lexer->tokens; - if (tokens.size() != 0) { - SHOW_STATUS(Logger::compiling(Logger::progress(0.40))) - parser::Parser parser(tokens, srcInfo); -#if _SNOWBALL_TIMERS_DEBUG - parser::Parser::NodeVec ast; - DEBUG_TIMER("Parser: %fs", utils::_timer([&] { ast = parser.parse(); })); -#else - auto ast = parser.parse(); -#endif - SHOW_STATUS(Logger::compiling(Logger::progress(0.50))) - auto mainModule = std::make_shared(); - mainModule->setSourceInfo(srcInfo); - auto simplifier = new Syntax::Transformer( - mainModule->downcasted_shared_from_this(), srcInfo, ((fs::path) path).parent_path(), testsEnabled, - benchmarkEnabled, silent - ); - chdir(((fs::path) path).parent_path().c_str()); -#if _SNOWBALL_TIMERS_DEBUG - DEBUG_TIMER("Simplifier: %fs", utils::_timer([&] { simplifier->visitGlobal(ast); })); -#else - simplifier->visitGlobal(ast); -#endif - SHOW_STATUS(Logger::compiling(Logger::progress(0.70))) - mainModule->setModules(simplifier->getModules()); - module = mainModule; -#if _SNOWBALL_TIMERS_DEBUG - DEBUG_TIMER("Passes: %fs", utils::_timer([&] { - SNOWBALL_PASS_EXECUTION_LIST - })); -#else - SNOWBALL_PASS_EXECUTION_LIST -#endif - SHOW_STATUS(Logger::compiling(Logger::progress(0.90))) - auto typeCheckModules = mainModule->getModules(); - typeCheckModules.push_back(mainModule); - for (auto module : typeCheckModules) { - codegen::TypeChecker typeChecker(module); -#if _SNOWBALL_TIMERS_DEBUG - DEBUG_TIMER("TypeChecker: %fs (%s)", utils::_timer([&] { typeChecker.codegen(); }), module->getName().c_str()); -#else - typeChecker.codegen(); -#endif - } - SHOW_STATUS(Logger::compiling(Logger::progress(1))) - SHOW_STATUS(Logger::reset_status()) - } - chdir(cwd.c_str()); - } -} - -using recursive_directory_iterator = std::filesystem::recursive_directory_iterator; - -void Compiler::runPackageManager(bool silent) { - if (!globalContext.packageManagerEnabled) return; - auto package = getConfiguration(); - auto manager = new pm::Manager(package, silent, cwd, configFolder); - manager->runAsMain(); -} - -int Compiler::emitDocs(std::string folder, std::string baseURL, BasicPackageInfo package, bool silent) { - auto path = cwd / folder; - auto outputFolder = configFolder / "docs"; - fs::remove_all(outputFolder); - std::vector modules; - if (utils::split(folder, "/").size() < 2) { - auto parts = utils::list2vec(utils::split(folder, "/")); - if (parts.size() < 1 && (parts[0] == "." || parts[0] == ".." || parts[0] == "")) { - if (parts.size() < 2 || (parts[1] == "." || parts[1] == ".." || parts[1] == "")) { - Syntax::E("Invalid relative path for documentation generation"); - } - } - } - for (const auto& dirEntry : recursive_directory_iterator(path)) { - if (utils::endsWith(dirEntry.path().string(), ".sn")) { - modules.push_back(fs::relative(dirEntry.path(), path).string()); - size_t lastindex = modules.back().find_last_of("."); - modules.back() = modules.back().substr(0, lastindex); - auto relative = dirEntry.path().lexically_relative(cwd).lexically_normal(); - lastindex = relative.string().find_last_of("."); - relative = relative.string().substr(0, lastindex); - fs::path relativePath = package.name; - int i = 0; - for (auto part : relative) { - if (i == 0) { - i++; - continue; - } - relativePath /= part; - } - std::string moduleName = relativePath.string(); - utils::replaceAll(moduleName, "/", "::"); - if (!silent) - Logger::message("Generating", " " + relative.string() + BCYN + " (" + relativePath.string() + ".html" + ")" + RESET); - std::ifstream ifs(dirEntry.path().string()); - std::string content((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); - srcInfo = new SourceInfo(content, dirEntry.path().string()); - auto lexer = new Lexer(srcInfo); - lexer->tokenize(); - auto tokens = lexer->tokens; - if (tokens.size() != 0) { - auto parser = new parser::Parser(tokens, srcInfo, true); - auto ast = parser->parse(); - Syntax::DocGenContext context { - .currentModule = moduleName, - .currentModulePath = relativePath.string(), - - .baseURL = baseURL, - .packageVersion = package.version, - }; - auto docGen = new Syntax::DocGen(context); - docGen->run(ast); - delete parser; - delete lexer; - auto result = docGen->getResult(); - for (auto& page : result.pages) { - auto htmlPath = outputFolder / page.path; - if (!fs::exists(htmlPath.parent_path())) fs::create_directories(htmlPath.parent_path()); - std::ofstream file(htmlPath); - file << page.html; - file.close(); - } - } - } - } - if (!silent) Logger::message("Indexing", - (std::string)"module's paths into index book" + BCYN + " (" + package.name + ".html)" + RESET); - Syntax::DocGenContext context { - .currentModule = package.name, - .currentModulePath = package.name, - - .baseURL = baseURL, - .packageVersion = package.version, - }; - auto docGen = new Syntax::DocGen(context); - auto page = docGen->createRootPage(modules); - auto htmlPath = outputFolder / page.path; - if (!fs::exists(htmlPath.parent_path())) fs::create_directories(htmlPath.parent_path()); - std::ofstream file(htmlPath); - file << page.html; - file.close(); - return EXIT_SUCCESS; -} -#undef SHOW_STATUS - -toml::parse_result Compiler::getConfiguration() { - std::string name = fs::current_path() / "sn.toml"; - std::ifstream f(name.c_str()); - if (f.good()) { return toml::parse_file(name); } - throw SNError( - Error::IO_ERROR, - FMT("Project configuration not found (%s)\n%shelp%s: try " - "runing 'snowball init --cfg'", - name.c_str(), - BGRN, - RESET) - ); -} - -void Compiler::enamblePackageManager(bool enable) { - globalContext.packageManagerEnabled = enable; -} - -void Compiler::cleanup() { } - -int Compiler::emitObject(std::string out, bool log) { - auto builder = new codegen::LLVMBuilder(module, opt_level, testsEnabled, benchmarkEnabled); - builder->codegen(); - builder->optimizeModule(); -#if _SNOWBALL_BYTECODE_DEBUG - builder->dump(); -#endif - return builder->emitObjectFile(out, log); -} - -int Compiler::emitLLVMIr(std::string p_output, bool p_pmessage) { - auto builder = new codegen::LLVMBuilder(module, opt_level, testsEnabled, benchmarkEnabled); - builder->codegen(); - builder->optimizeModule(); - std::error_code EC; - llvm::raw_fd_ostream dest(p_output, EC); - if (EC) throw SNError(Error::IO_ERROR, Logger::format("Could not open file: %s", EC.message().c_str())); - builder->print(dest); - if (p_pmessage) Logger::success("Snowball project transpiled to llvm IR code! 🎉\n"); - return EXIT_SUCCESS; -} - -int Compiler::emitASM(std::string p_output, bool p_pmessage) { - auto builder = new codegen::LLVMBuilder(module, opt_level, testsEnabled, benchmarkEnabled); - builder->codegen(); - builder->optimizeModule(); - auto res = builder->emitObjectFile(p_output, false, false); - if (p_pmessage) Logger::success("Snowball project transpiled to assembly code! 🎉\n"); - return res; -} - -int Compiler::emitBinary(std::string out, bool log) { - std::vector extraLinkerArgs = {}; - auto objfile = linker::Linker::getSharedLibraryName(out); - DEBUG_CODEGEN("Emitting object file... (%s)", objfile.c_str()); - int objstatus = emitObject(objfile, false); - if (objstatus != EXIT_SUCCESS) return objstatus; - auto linker = linker::Linker(globalContext, LD_PATH); - for (auto lib : linkedLibraries) { linker.addLibrary(lib); } - // TODO: add user-defined extra ld args - linker.link(objfile, out, extraLinkerArgs); - if (log) Logger::success(Logger::format("Snowball project successfully compiled! 🥳", BGRN, RESET, out.c_str())); - // clean up - DEBUG_CODEGEN("Cleaning up object file... (%s)", objfile.c_str()); - remove(objfile.c_str()); - return EXIT_SUCCESS; -} - -int Compiler::emitSnowballIr(std::string p_output, bool p_pmessage) { - auto builder = new codegen::SnowballIREmitter(module); - builder->codegen(p_output); - if (p_pmessage) Logger::success("Snowball project transpiled to snowball IR code! 🎉\n"); - return EXIT_SUCCESS; -} - -void Compiler::createSourceInfo() { srcInfo = new SourceInfo(source, path); } -} // namespace snowball diff --git a/src/compiler.h b/src/compiler.h deleted file mode 100644 index 52b1edc2..00000000 --- a/src/compiler.h +++ /dev/null @@ -1,119 +0,0 @@ - -#include "../app/cli.h" -#include "SourceInfo.h" -#include "common.h" -#include "ir/module/MainModule.h" -#include "ir/module/Module.h" -#include "lexer/lexer.h" -#include "vendor/toml.hpp" -#include "./visitors/documentation/DocGen.h" - -#include -#include - -namespace fs = std::filesystem; -#ifndef __SNOWBALL_COMPILER_H_ -#define __SNOWBALL_COMPILER_H_ - -// It is important that the passes are pointers initialized with "new" and not -// just objects. This is because c++ messes up virtual functions when using -// objects. This is a known bug in c++. -#define SNOWBALL_PASS_EXECUTION_LIST \ - std::vector passes = { \ - new Syntax::DefiniteAssigment(srcInfo)}; \ - for (auto pass : passes) \ - pass->run(ast); - -namespace snowball { - -/** - * @brief Global context for the compiler - * - * @details - * This struct holds all the global context for the compiler. This is used to pass - * information between different parts of the compiler. - */ -struct GlobalContext { - bool isTest = false; - bool isBench = false; - bool withStd = true; - bool withCXXStd = true; - bool isThreaded = false; - bool packageManagerEnabled = false; - - bool isDynamic = true; - app::Options::Optimization opt = app::Options::Optimization::OPTIMIZE_O0; -}; - -/** - * @brief snowball Compiler - * - * @details - * Main class that handles all the compiling process of snowball. Note that it does not - * actually compile, the llvm builder does the actual compilation. This class is more of - * a wrapper around the whole compiler functionality. - */ -class Compiler { - // variables - std::string source; - fs::path path; - - fs::path cwd; - app::Options::Optimization opt_level; - - GlobalContext globalContext; - - const SourceInfo* srcInfo = (snowball::SourceInfo*) nullptr; - bool initialized = false; - bool testsEnabled = false; - bool benchmarkEnabled = false; - - std::shared_ptr module; - - public: - Compiler(std::string p_code, std::string p_path); - - void initialize(); - void compile(bool verbose = true); - - void cleanup(); - - static toml::parse_result getConfiguration(); - void enable_tests() { testsEnabled = true; } - void enable_benchmark() { benchmarkEnabled = true; } - - // Get - ~Compiler() {}; - - std::vector linkedLibraries; - fs::path configFolder; - - struct BasicPackageInfo { - std::string name; - std::string version; - }; - - int emitBinary(std::string, bool = true); - int emitObject(std::string, bool = true); - int emitLLVMIr(std::string, bool = true); - int emitASM(std::string, bool = true); - int emitSnowballIr(std::string, bool = true); - int emitDocs(std::string, std::string, BasicPackageInfo, bool = true); - - void enamblePackageManager(bool); - - GlobalContext& getGlobalContext() { return globalContext; } - - void setOptimization(app::Options::Optimization o) { - globalContext.opt = o; - opt_level = o; - } - - private: - // methods - void createSourceInfo(); - void runPackageManager(bool silent); -}; -} // namespace snowball - -#endif // __SNOWBALL_COMPILER_H_ diff --git a/src/constants.h b/src/constants.h deleted file mode 100644 index f83f2f59..00000000 --- a/src/constants.h +++ /dev/null @@ -1,317 +0,0 @@ - -#include -#include - -#ifndef __SNOWBALL_CONSTANTS_H_ -#define __SNOWBALL_CONSTANTS_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -// breaking.feature.fix -#if !defined(_SNOWBALL_VERSION) || !defined(_SNOWBALL_VERSION_NUMBER) -#error "_SNOWBALL_VERSION and _SNOWBALL_VERSION_NUMBER must be defined!" -#endif -#define _SNOWBALL_BUILD_DATE __DATE__ -#define _SNOWBALL_BUILD_TIME __TIME__ - -// Exports -#ifdef _WIN32 -#define DLLEXPORT __declspec(dllexport) -#else -#define DLLEXPORT -#endif - -#ifndef _SNOWBALL_PACkAGE_REGISTRY -// http to avoid needing to use an SSL library -#define _SNOWBALL_PACKAGE_REGISTRY "http://snowball-lang.github.io/packages/pkgs/" -#endif - -// OS specific -#pragma region -#ifdef _WIN32 -#define OS_NAME "Windows 32-bit" -#define PATH_SEPARATOR "\\" -#define _SNOWBALL_OS "windows" -#elif _WIN64 -#define OS_NAME "Windows 64-bit" -#define PATH_SEPARATOR "\\" -#define _SNOWBALL_OS "windows" -#elif __APPLE__ || __MACH__ -#define OS_NAME "Mac OS_NAMEX" -#define PATH_SEPARATOR "/" -#define _SNOWBALL_OS "macos" -#elif __linux__ -#define OS_NAME "Linux" -#define PATH_SEPARATOR "/" -#define _SNOWBALL_OS "linux" -#elif __unix || __unix__ -#define OS_NAME "Unix" -#define PATH_SEPARATOR "/" -#define _SNOWBALL_OS "unix" -#else -#define OS_NAME "Unknown OS" -#define PATH_SEPARATOR "/" -#define _SNOWBALL_OS "unknown" -#endif -#pragma endregion - -// Values - -#define _SNOWBALL_CONST_PTR "$const-pointer" -#define _SNOWBALL_MUT_PTR "$mut-pointer" -#define _SNOWBALL_INT_IMPL "$integer-impl" -#define _SNOWBALL_FUNC_IMPL "$function-impl" - -// Make sure this is always correct! -#define _SNOWBALL_CONST_PTR_DECL "std::internal::preloads::$const-pointer" -#define _SNOWBALL_MUT_PTR_DECL "std::internal::preloads::$mut-pointer" - -#define _SNOWBALL_STR_FACTOR 16 -#define _SNOWBALL_MAX_LENGTH 2147483647 -#define _SNOWBALL_OUT_DEFAULT(x, t, s) \ - (".sn" PATH_SEPARATOR "bin" PATH_SEPARATOR + (os::Driver::getOutputFilename(x, t, s))) - -#ifndef _SNOWBALL_ENABLE_INT64 -#define _SNOWBALL_ENABLE_INT64 1 -#endif - -#if _SNOWBALL_ENABLE_INT64 -typedef uint64_t snowball_int_t; -#define _SNOWBALL_INT_MAX 9223372036854775807 -#define _SNOWBALL_INT_MIN (-_SNOWBALL_INT_MAX - 1LL) -#else -typedef uint32_t snowball_int_t; -#define _SNOWBALL_INT_MAX 2147483647 -#define _SNOWBALL_INT_MIN -2147483648 -#endif - -#define SN_INT_MAX_POWER 8388608 -#define SN_MAX_MACRO_DEPTH 2048 - -#define UNREACHABLE \ - do { std::abort(); } while (0); - -// Debug -#undef NDEBUG - -#ifndef _SN_DEBUG -#define _SN_DEBUG true -#endif - -#define LINE_SEPARATOR "------------------" -#if _SN_DEBUG -#define _SNOWBALL_BUILD_TYPE "Debug" - -#define _SNOWBALL_LEXER_DEBUG 0 -#define _SNOWBALL_PARSER_DEBUG 0 -#define _SNOWBALL_CODEGEN_DEBUG 0 -#define _SNOWBALL_BYTECODE_DEBUG 1 -#define _SNOWBALL_SYMTABLE_DEBUG 0 -#define _SNOWBALL_TIMERS_DEBUG 0 -#define _SNOWBALL_FREE_DEBUG 0 // todo - -#define PRINT_LINE(...) \ - printf(__VA_ARGS__); \ - printf("\n"); \ - fflush(stdout); - -#if _SNOWBALL_LEXER_DEBUG -#define DEBUG_LEXER(...) PRINT_LINE(__VA_ARGS__) -#else -#define DEBUG_LEXER(...) -#endif - -#if _SNOWBALL_PARSER_DEBUG -#define DEBUG_PARSER(...) PRINT_LINE(__VA_ARGS__) -#else -#define DEBUG_PARSER(...) -#endif - -#if _SNOWBALL_TIMERS_DEBUG -#define DEBUG_TIMER(...) PRINT_LINE(__VA_ARGS__) -#else -#define DEBUG_TIMER(...) -#endif - -#if _SNOWBALL_SYMTABLE_DEBUG -#define DEBUG_SYMTABLE(depth, ...) \ - printf("%*s", depth * 4, " "); \ - PRINT_LINE(__VA_ARGS__) -#else -#define DEBUG_SYMTABLE(...) -#endif - -#if _SNOWBALL_CODEGEN_DEBUG -#define DEBUG_CODEGEN(...) PRINT_LINE(__VA_ARGS__) -#else -#define DEBUG_CODEGEN(...) -#endif - -#if _SNOWBALL_FREE_DEBUG -#define DEBUG_FREE(...) PRINT_LINE(__VA_ARGS__) -#else -#define DEBUG_FREE(...) -#endif - -#define DEBUG_ALWAYS(...) PRINT_LINE(__VA_ARGS__) - -#define DUMP(varname) fprintf(stderr, "%s (%s) = %i\n", #varname, typeid(varname).name(), varname); -#define DUMP_S(varname) fprintf(stderr, "%s (%s) = %s\n", #varname, typeid(varname).name(), varname); - -#else -#define _SNOWBALL_BUILD_TYPE "Default" - -#define DEBUG_PARSER(...) -#define DEBUG_SYMTABLE(...) -#define DEBUG_CODEGEN(...) -#define DEBUG_FREE(...) - -#define DEBUG_ALWAYS(...) - -#define _SNOWBALL_LEXER_DEBUG 0 -#define _SNOWBALL_PARSER_DEBUG 0 -#define _SNOWBALL_CODEGEN_DEBUG 0 -#define _SNOWBALL_BYTECODE_DEBUG 0 -#define _SNOWBALL_SYMTABLE_DEBUG 0 -#define _SNOWBALL_FREE_DEBUG 0 -#endif - -// LD -#pragma region - -#ifndef _SNOWBALL_LIBRARY_OBJ -#error "_SNOWBALL_LIBRARY_OBJ must be defined! (e.g. \"snowball-objects\")" -#endif - -#ifndef _SNOWBALL_LIBRARY_DIR -#error "_SNOWBALL_LIBRARY_DIR must be defined! (e.g. \"snowball-libs\")" -#endif - -#ifndef _SNOWBALL_PACKAGES_DIR -#define _SNOWBALL_PACKAGES_DIR ".sn" PATH_SEPARATOR "deps" -#endif - -#ifndef _SNOWBALL_LLVM_PACKAGE_VERSION -#error "_SNOWBALL_LLVM_PACKAGE_VERSION must be defined! (e.g. \"16.0.6\")" -#endif - -// path of ld compiler used for linking -#ifndef LD_PATH -#error "LD_PATH must be defined! (e.g. \"/usr/bin/ld\")" -#endif - -#ifndef STATICLIB_DIR -#error "STATICLIB_DIR path must be defined! (e.g. \"/usr/lib/\")" -#endif - -#pragma endregion - -// Optimizations -#ifndef _SNOWBALL_CAN_OPTIMIZE -#define _SNOWBALL_CAN_OPTIMIZE 1 -#endif - -// Function names -#define _SNOWBALL_FUNCTION_ENTRY "main" - -// Keywords -#define _SNOWBALL_KEYWORD__IF "if" -#define _SNOWBALL_KEYWORD__AS "as" -#define _SNOWBALL_KEYWORD__FOR "for" -#define _SNOWBALL_KEYWORD__ENUM "enum" -#define _SNOWBALL_KEYWORD__TRUE "true" -#define _SNOWBALL_KEYWORD__ELSE "else" -#define _SNOWBALL_KEYWORD__CLASS "class" -#define _SNOWBALL_KEYWORD__INTER "interface" -#define _SNOWBALL_KEYWORD__EXTENDS "extends" -#define _SNOWBALL_KEYWORD__IMPLS "implements" -#define _SNOWBALL_KEYWORD__PRIVATE "private" -#define _SNOWBALL_KEYWORD__PUBLIC "public" -#define _SNOWBALL_KEYWORD__VIRTUAL "virtual" -#define _SNOWBALL_KEYWORD__FALSE "false" -#define _SNOWBALL_KEYWORD__OVERRIDE "override" -#define _SNOWBALL_KEYWORD__WHILE "while" -#define _SNOWBALL_KEYWORD__BREAK "break" -#define _SNOWBALL_KEYWORD__EXTERN "external" -#define _SNOWBALL_KEYWORD__SUPER "super" -#define _SNOWBALL_KEYWORD__STATIC "static" -#define _SNOWBALL_KEYWORD__IMPORT "import" -#define _SNOWBALL_KEYWORD__UNSAFE "unsafe" -#define _SNOWBALL_KEYWORD__CONSTEXPR "constexpr" -#define _SNOWBALL_KEYWORD__NAMESPACE "namespace" -#define _SNOWBALL_KEYWORD__STRUCT "struct" -#define _SNOWBALL_KEYWORD__TYPEDEF "type" -#define _SNOWBALL_KEYWORD__MUTABLE "mut" -#define _SNOWBALL_KEYWORD__DO "do" -#define _SNOWBALL_KEYWORD__RETURN "return" -#define _SNOWBALL_KEYWORD__DECLTYPE "decltype" -#define _SNOWBALL_KEYWORD__SWITCH "switch" -#define _SNOWBALL_KEYWORD__CASE "case" -#define _SNOWBALL_KEYWORD__DEFAULT "default" -#define _SNOWBALL_KEYWORD__CONTINUE "continue" -#define _SNOWBALL_KEYWORD__FUNCTION "func" -#define _SNOWBALL_KEYWORD__MACRO "macro" -#define _SNOWBALL_KEYWORD__OPERATOR "operator" -#define _SNOWBALL_KEYWORD__VARIABLE "let" -#define _SNOWBALL_KEYWORD__NEW "new" -#define _SNOWBALL_KEYWORD__THROW "throw" -#define _SNOWBALL_KEYWORD__CONSTANT "const" -#define _SNOWBALL_KEYWORD__TRY "try" -#define _SNOWBALL_KEYWORD__CATCH "catch" - -#define _SNOWBALL_LAMBDA_FUNCTIONS \ - { 'l', 'a', 'm', 'b', 'd', 'a', ' ', 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', 0 } -#define _SNOWBALL_LAMBDA_SIZE 17 - -// LLVM IR constants -#define _SN_CLASS_PREFIX "class." -#define _SN_STRUCT_PREFIX "struct." -#define _SN_VTABLE_PREFIX "vtable." -#define _SN_ENUM_PREFIX "enum." - -#define _SN_MANGLE_PREFIX "_ZN$SN" - -// Compiler lines -#if 0 -#define _SNOWBALL_COMPILER_ENTRY \ - "Snowball " _SNOWBALL_VERSION " (" _SNOWBALL_BUILD_TYPE ": " _SNOWBALL_BUILD_DATE ", " _SNOWBALL_BUILD_TIME ")" -#define _SNOWBALL_COMPILER_ENTRY_BK \ - "\ -Snowball " _SNOWBALL_VERSION " (" _SNOWBALL_BUILD_TYPE ": " _SNOWBALL_BUILD_DATE ", " _SNOWBALL_BUILD_TIME ")\n\ -Type \"help\", \"copyright\", \"credits\" or \"license\" for more information.\ -" -#endif - -// Licenses -#define _SNOWBALL_LICENSE_NAME "MIT" -#define _SNOWBALL_LICENSE_TEXT \ - "\ -The MIT License (MIT)\n\ -\n\ -Copyright (c) 2022 mauro-balades \n\ -\n\ -Permission is hereby granted, free of charge, to any person obtaining a copy\n\ -of this software and associated documentation files (the \"Software\"), to deal\n\ -in the Software without restriction, including without limitation the rights\n\ -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n\ -copies of the Software, and to permit persons to whom the Software is\n\ -furnished to do so, subject to the following conditions:\n\ -\n\ -The above copyright notice and this permission notice shall be included in\n\ -all copies or substantial portions of the Software.\n\ -\n\ -THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n\ -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n\ -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n\ -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n\ -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n\ -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n\ -THE SOFTWARE." - -#ifdef __cplusplus -} -#endif - -#endif // __SNOWBALL_CONSTANTS_H_ diff --git a/src/defs/accepts.def b/src/defs/accepts.def deleted file mode 100644 index 8eb2d829..00000000 --- a/src/defs/accepts.def +++ /dev/null @@ -1,36 +0,0 @@ - -#ifndef ACCEPT -#error ACCEPT needs to be defined! -#define ACCEPT(n) // For linting -#endif - -ACCEPT(Block) -ACCEPT(Macro) - -ACCEPT(Expression::ConstantValue) -ACCEPT(Expression::FunctionCall) -ACCEPT(Expression::Identifier) -ACCEPT(Expression::GenericIdentifier) -ACCEPT(Expression::Index) -ACCEPT(Expression::TypeRef) -ACCEPT(Expression::Cast) -ACCEPT(Expression::NewInstance) -ACCEPT(Expression::BinaryOp) -ACCEPT(Expression::LambdaFunction) -ACCEPT(Expression::PseudoVariable) - -ACCEPT(Statement::TypeAlias) -ACCEPT(Statement::Raise) -ACCEPT(Statement::WhileLoop) -ACCEPT(Statement::TryCatch) -ACCEPT(Statement::Return) -ACCEPT(Statement::VariableDecl) -ACCEPT(Statement::DefinedTypeDef) -ACCEPT(Statement::ImportStmt) -ACCEPT(Statement::FunctionDef) -ACCEPT(Statement::Namespace) -ACCEPT(Statement::ForLoop) -ACCEPT(Statement::Conditional) -ACCEPT(Statement::LoopFlow) -ACCEPT(Statement::EnumTypeDef) -ACCEPT(Statement::Switch) diff --git a/src/defs/ct.def b/src/defs/ct.def deleted file mode 100644 index aa6563de..00000000 --- a/src/defs/ct.def +++ /dev/null @@ -1,12 +0,0 @@ - -#ifndef VISIT -#define VISIT(v) v, -#endif - -VISIT(String) -VISIT(Number) -VISIT(Float) -VISIT(Bool) -VISIT(Char) - -#undef VISIT diff --git a/src/defs/operators.def b/src/defs/operators.def deleted file mode 100644 index 21bbe5cc..00000000 --- a/src/defs/operators.def +++ /dev/null @@ -1,48 +0,0 @@ - -#ifndef OPERATOR -#error OPERATOR needs to be defined! -#define OPERATOR(o, n, s, p) // For linting -#endif - -OPERATOR(EQ, 0, "Eq", "operator =" ) -OPERATOR(EQEQ, 1, "DbEq", "operator ==" ) -OPERATOR(PLUS, 2, "Pl", "operator +" ) -OPERATOR(PLUSEQ, 3, "PlEq", "operator +=" ) -OPERATOR(MINUS, 4, "Mn", "operator -" ) -OPERATOR(UPLUS, 5, "Up", "operator(unary) +" ) -OPERATOR(UMINUS, 6, "Um", "operator(unary) -" ) -OPERATOR(REFERENCE, 7, "Ref", "(reference to value)" ) -OPERATOR(MINUSEQ, 8, "MnEq", "operator -=" ) -OPERATOR(MUL, 9, "Ml", "operator *" ) -OPERATOR(MULEQ, 10, "MlEq", "operator *=" ) -OPERATOR(DIV, 11, "Di", "operator / " ) -OPERATOR(DIVEQ, 12, "DiEq", "operator /=" ) -OPERATOR(MOD, 13, "Md", "operator %" ) -OPERATOR(MOD_EQ, 14, "MdEq", "operator %=" ) -OPERATOR(LT, 15, "Lt", "operator <" ) -OPERATOR(LTEQ, 16, "LtEq", "operator <=" ) -OPERATOR(GT, 17, "Gt", "operator >" ) -OPERATOR(GTEQ, 18, "GtEq", "operator >=" ) -OPERATOR(AND, 19, "An", "operator &&" ) -OPERATOR(OR, 20, "O", "operator ||" ) -OPERATOR(NOT, 21, "Nt", "operator !" ) -OPERATOR(NOTEQ, 22, "NtE", "operator !=" ) -OPERATOR(BIT_NOT, 23, "BNt", "operator ~" ) -OPERATOR(BIT_LSHIFT, 24, "BLsShft", "operator <<" ) -OPERATOR(BIT_LSHIFT_EQ, 25, "BLsShftEq", "operator <<=" ) -OPERATOR(BIT_RSHIFT, 26, "BRshft", "operator |>>" ) -OPERATOR(BIT_RSHIFT_EQ, 27, "BRshftEq", "operator >>=" ) -OPERATOR(BIT_OR, 28, "BOr", "operator |" ) -OPERATOR(BIT_OR_EQ, 29, "BOrEq", "operator |=" ) -OPERATOR(BIT_AND, 30, "BAnd", "operator &" ) -OPERATOR(BIT_AND_EQ, 31, "BAndEq", "operator &=" ) -OPERATOR(BIT_XOR, 32, "BXor", "operator ^" ) -OPERATOR(BIT_XOR_EQ, 33, "BXorEq", "operator ^=" ) -OPERATOR(CONSTRUCTOR, 34, "NwC", "constructor" ) -OPERATOR(DESTRUCTOR, 35, "Dle", "destructor" ) -OPERATOR(CALL, 36, "Cll", "operator ()" ) -OPERATOR(BOOL, 37, "BlC", "Boolean conversion" ) -OPERATOR(INDEX, 38, "Idx", "operator []" ) -OPERATOR(DEREFERENCE, 39, "DRf", "(dereference to value)") -OPERATOR(RANGE, 40, "Rng", "operator .." ) -OPERATOR(INVALID, 41, "Inv", "" ) \ No newline at end of file diff --git a/src/defs/visits.def b/src/defs/visits.def deleted file mode 100644 index dab3883c..00000000 --- a/src/defs/visits.def +++ /dev/null @@ -1,30 +0,0 @@ - -#ifndef VISIT -#error "VISIT(n) should be defined!" -#define VISIT(v) // for linting -#endif - -VISIT(Func) -VISIT(Block) -VISIT(StringValue) -VISIT(NumberValue) -VISIT(BooleanValue) -VISIT(FloatValue) -VISIT(Variable) -VISIT(Call) -VISIT(ValueExtract) -VISIT(Return) -VISIT(Argument) -VISIT(Cast) -VISIT(Throw) -VISIT(VariableDeclaration) -VISIT(CharValue) -VISIT(WhileLoop) -VISIT(Conditional) -VISIT(TryCatch) -VISIT(ReferenceTo) -VISIT(IndexExtract) -VISIT(DereferenceTo) -VISIT(EnumInit) -VISIT(LoopFlow) -VISIT(Switch) diff --git a/src/errors.cc b/src/errors.cc deleted file mode 100644 index 00ddcd90..00000000 --- a/src/errors.cc +++ /dev/null @@ -1,164 +0,0 @@ - -#include "errors.h" -#include "utils/utils.h" - -#define RET_ERROR_IF_CODE(x, err) \ - if (code == x) return err; - -namespace snowball { -namespace errors { - -namespace { -/// @brief replace 'hello' with [white]'hello'[reset] -std::string highlight(std::string str) { - std::string ret = ""; - bool in_highlight = false; - for (size_t i = 0; i < str.size(); i++) { - bool add = false; - if (str[i] == '\'') { - if (in_highlight) { - add = true; - } else { - ret += BWHT; - in_highlight = true; - } - } - ret += str[i]; - if (add) { - ret += RESET; - in_highlight = false; - } - } - return ret; -} -} // namespace - -void NiceError::print_error(bool asTail) const { - cb_dbg_info->prepare_for_error(); - if (!asTail) { - Logger::log(""); - Logger::error(FMT("(%s%s%s) %s%s%s", BRED, get_error(error), RESET, BOLD, RESET, highlight(message).c_str())); - Logger::elog(FMT("%s╚══╤══╝", BLK)); - Logger::elog(FMT(" ╰───╮%s", RESET)); - Logger::elog( - FMT("%s ├─[%s%s%s%s:%i:%i%s%s]%s", - BLK, - RESET, - BBLU, - cb_dbg_info->getSourceInfo()->getPath().c_str(), - BBLK, - cb_dbg_info->line, - cb_dbg_info->pos.second, - RESET, - BLK, - RESET) - ); - } else { - Logger::elog( - FMT("%s ├─[%s%s%s%s:%i:%i%s%s]%s", - BLK, - RESET, - BBLU, - cb_dbg_info->getSourceInfo()->getPath().c_str(), - BBLK, - cb_dbg_info->line, - cb_dbg_info->pos.second, - RESET, - BLK, - RESET) - ); - } - // Logger::elog(FMT("%s │%s", BLK, RESET)); - Logger::elog(FMT("%s │%s", BLK, RESET)); - if ((((int) cb_dbg_info->line) - 2) >= 1) // first line may not be available to log - Logger::elog(FMT(" %s%4i%s │ %s", BBLK, cb_dbg_info->line - 2, BLK, cb_dbg_info->line_before_before.c_str())); - if ((((int) cb_dbg_info->line) - 1) >= 1) // first line may not be available to log - Logger::elog(FMT(" %s%4i%s │ %s", BBLK, cb_dbg_info->line - 1, BLK, cb_dbg_info->line_before.c_str())); - // highlight line where the error is - // e.g. hello(1, 2, 3) - // ~~~~~ - // converted to - // [white]hello[gray](1, 2, 3) - std::string line_str = ""; - for (size_t i = 0; i < cb_dbg_info->line_str.size(); i++) { - if (i >= (size_t)cb_dbg_info->pos.second - 1 && i < cb_dbg_info->pos.second + cb_dbg_info->width - 1) { - line_str += BWHT; - } else if (i >= cb_dbg_info->pos.second + cb_dbg_info->width - 1) { - line_str += BLK; - } - line_str += cb_dbg_info->line_str[i]; - } - Logger::elog( - FMT(" %s %4i%s >%s %s\n %s│%s %s%s %s%s", - BWHT, - cb_dbg_info->line, - BLK, - BLK, - line_str.c_str(), - BLK, - RESET, - BRED, - cb_dbg_info->get_pos_str().c_str(), - info.info.c_str(), - RESET) - ); - if (!cb_dbg_info->line_after_after.empty() || !cb_dbg_info->line_after.empty()) - Logger::elog(FMT(" %s%4i%s │ %s", BBLK, cb_dbg_info->line + 1, BLK, cb_dbg_info->line_after.c_str())); - if (!cb_dbg_info->line_after_after.empty()) - Logger::elog(FMT(" %s%4i%s │ %s", BBLK, cb_dbg_info->line + 2, BLK, cb_dbg_info->line_after_after.c_str())); - if (!info.note.empty()) { - Logger::elog(FMT("%s │", BLK)); - Logger::elog(FMT("%s │", BLK)); - auto lines = utils::split(highlight(info.note), "\n"); - Logger::elog(FMT("%s note%s:%s %s", BCYN, BBLK, RESET, (*lines.begin()).c_str())); - lines.pop_front(); - for (auto line : lines) { Logger::elog(FMT("%s │ %s%s", BLK, RESET, line.c_str())); } - } - if (auto x = info.tail) { - if (info.note.empty()) Logger::elog(FMT("%s │", BLK)); - Logger::elog(FMT("%s │", BLK)); - Logger::elog(FMT("%s :", BLK)); - Logger::elog(FMT("%s │", BLK)); - x->print_error(true); - } - if (!info.help.empty()) { - // if (!info.note.empty()) - Logger::elog(FMT("%s │", BLK)); - auto lines = utils::split(highlight(info.help), "\n"); - Logger::elog(FMT("%s help%s:%s %s", BGRN, BBLK, RESET, (*lines.begin()).c_str())); - lines.pop_front(); - for (auto line : lines) { Logger::elog(FMT("%s │ %s%s", BLK, RESET, line.c_str())); } - } - Logger::elog(FMT("%s │", BLK)); - if (!asTail) { - Logger::elog(FMT(" ────╯%s", RESET)); - Logger::log("\n"); - } -}; - -const char* get_error(Error code) { - RET_ERROR_IF_CODE(Error::BUG, "BUG") - RET_ERROR_IF_CODE(Error::TODO, "TODO") - RET_ERROR_IF_CODE(Error::WARNING, "Warning") - RET_ERROR_IF_CODE(Error::IO_ERROR, "IO Error") - RET_ERROR_IF_CODE(Error::TYPE_ERROR, "Type Error") - RET_ERROR_IF_CODE(Error::UNEXPECTED_EOF, "Unexpected EOF") - RET_ERROR_IF_CODE(Error::SYNTAX_ERROR, "Syntax error") - RET_ERROR_IF_CODE(Error::LLVM_INTERNAL, "LLVM internal error") - RET_ERROR_IF_CODE(Error::UNDEFINED_VARIABLE, "Undefined Variable") - RET_ERROR_IF_CODE(Error::VARIABLE_ERROR, "Variable Error") - RET_ERROR_IF_CODE(Error::COMPILER_ERROR, "Compiler Error") - RET_ERROR_IF_CODE(Error::ARGUMENT_ERROR, "Argument Error") - RET_ERROR_IF_CODE(Error::FUNCTION_RET_ERR, "Function Return Error") - RET_ERROR_IF_CODE(Error::CONFIGURATION_ERROR, "Configuration Error") - RET_ERROR_IF_CODE(Error::LINKER_ERR, "Linker Error") - RET_ERROR_IF_CODE(Error::REFERENCE_ERROR, "Reference Error") - RET_ERROR_IF_CODE(Error::ATTRIBUTE_ERROR, "Attribute Error") - RET_ERROR_IF_CODE(Error::PSEUDO_ERROR, "Pseudo-code Error") - RET_ERROR_IF_CODE(Error::IMPORT_ERROR, "Import Error") - RET_ERROR_IF_CODE(Error::DEREFERENCE_ERROR, "Dereference Error") - RET_ERROR_IF_CODE(Error::PM_ERROR, "Package Manager") - return "Error"; -} -} // namespace errors -} // namespace snowball diff --git a/src/errors.h b/src/errors.h deleted file mode 100644 index 4b7e99d8..00000000 --- a/src/errors.h +++ /dev/null @@ -1,129 +0,0 @@ - -#include "sourceInfo/DBGSourceInfo.h" -#include "utils/colors.h" -#include "utils/logger.h" - -#include -#include -#include -#include - -#ifndef __SNOWBALL_ERRORS_H_ -#define __SNOWBALL_ERRORS_H_ - -namespace snowball { -enum Error { - IO_ERROR, - TYPE_ERROR, - SYNTAX_ERROR, - UNDEFINED_VARIABLE, - UNEXPECTED_EOF, - REFERENCE_ERROR, - WARNING, - VARIABLE_ERROR, - CONFIGURATION_ERROR, - ATTRIBUTE_ERROR, - ARGUMENT_ERROR, - IMPORT_ERROR, - PSEUDO_ERROR, - DEREFERENCE_ERROR, - FUNCTION_RET_ERR, - PM_ERROR, - COMPILER_ERROR, // note: not the same as "compile time error" - - LLVM_INTERNAL, - LINKER_ERR, - - BUG, - TODO -}; - -namespace errors { -const char* get_error(Error code); - -class SNError { - public: - SNError(Error code, std::string err) { - error = code; - message = err; - }; - - virtual void print_error(bool _ = false) const { - Logger::error(FMT("(%s%s%s) %s%s%s", BRED, get_error(error), RESET, BOLD, message.c_str(), RESET)); - }; - - virtual ~SNError() {}; - - Error error; - std::string message; -}; - -struct ErrorInfo { - const std::string info = ""; - const std::string note = ""; - - const std::string help = ""; - const std::string consider = ""; - - SNError* tail = nullptr; -}; - -/** - * @brief A nice error is an error that is printed in a nice way. - */ -class NiceError : public SNError { - protected: - DBGSourceInfo* cb_dbg_info; - - public: - ErrorInfo info; - NiceError(Error code, std::string err, DBGSourceInfo* p_cb_dbg_info, ErrorInfo info = {}) - : SNError(code, err), cb_dbg_info(p_cb_dbg_info), info(info) {}; - virtual void print_error(bool asTail = false) const override; -}; - -/** - * @brief A lexer error is an error that occurs during lexing. - */ -class LexerError : public NiceError { - public: - LexerError(Error code, std::string err, DBGSourceInfo* p_cb_dbg_info, ErrorInfo info = {}) - : NiceError(code, err, p_cb_dbg_info, info) {}; - - virtual ~LexerError() {}; -}; - -/** - * @brief A parser error is an error that occurs during parsing. - */ -class ParserError : public NiceError { - public: - ParserError(Error code, std::string err, DBGSourceInfo* p_cb_dbg_info, ErrorInfo info = {}) - : NiceError(code, err, p_cb_dbg_info, info) {}; - - virtual ~ParserError() {}; -}; - -/** - * @brief A compiler error is an error that occurs during compilation. - */ -class CompilerError : public NiceError { - public: - CompilerError(Error code, std::string err, DBGSourceInfo* p_cb_dbg_info, ErrorInfo info = {}) - : NiceError(code, err, p_cb_dbg_info, info) {}; - - virtual ~CompilerError() {}; -}; - -} // namespace errors - -using LexerError = errors::LexerError; -using ParserError = errors::ParserError; -using CompilerError = errors::CompilerError; - -using SNError = errors::SNError; -using ErrorInfo = errors::ErrorInfo; - -} // namespace snowball - -#endif // __SNOWBALL_ERRORS_H_ diff --git a/src/export.hpp b/src/export.hpp deleted file mode 100644 index 625f6d80..00000000 --- a/src/export.hpp +++ /dev/null @@ -1,42 +0,0 @@ - -#ifndef SNOWBALL_EXPORT_H -#define SNOWBALL_EXPORT_H - -#ifdef SNOWBALL_STATIC -# define SNOWBALL_EXPORT -# define SNOWBALL_NO_EXPORT -#else -# ifndef SNOWBALL_EXPORT -# ifdef snowball_EXPORTS - /* We are building this library */ -# define SNOWBALL_EXPORT __attribute__((visibility("default"))) -# else - /* We are using this library */ -# define SNOWBALL_EXPORT __attribute__((visibility("default"))) -# endif -# endif - -# ifndef SNOWBALL_NO_EXPORT -# define SNOWBALL_NO_EXPORT __attribute__((visibility("hidden"))) -# endif -#endif - -#ifndef SNOWBALL_DEPRECATED -# define SNOWBALL_DEPRECATED __attribute__ ((__deprecated__)) -#endif - -#ifndef SNOWBALL_DEPRECATED_EXPORT -# define SNOWBALL_DEPRECATED_EXPORT SNOWBALL_EXPORT SNOWBALL_DEPRECATED -#endif - -#ifndef SNOWBALL_DEPRECATED_NO_EXPORT -# define SNOWBALL_DEPRECATED_NO_EXPORT SNOWBALL_NO_EXPORT SNOWBALL_DEPRECATED -#endif - -#if 0 /* DEFINE_NO_DEPRECATED */ -# ifndef SNOWBALL_NO_DEPRECATED -# define SNOWBALL_NO_DEPRECATED -# endif -#endif - -#endif /* SNOWBALL_EXPORT_H */ diff --git a/src/ir/IdMixin.cc b/src/ir/IdMixin.cc deleted file mode 100644 index c2b04547..00000000 --- a/src/ir/IdMixin.cc +++ /dev/null @@ -1,13 +0,0 @@ - -#include "id.h" - -#include - -namespace snowball { -namespace ir { - -id_t IdMixin::currentId = 0; -void IdMixin::resetId() { currentId = 0; } - -} // namespace ir -} // namespace snowball diff --git a/src/ir/ModuleHolder.h b/src/ir/ModuleHolder.h deleted file mode 100644 index 64920070..00000000 --- a/src/ir/ModuleHolder.h +++ /dev/null @@ -1,27 +0,0 @@ - -#include "module/Module.h" - -#ifndef __SNOWBALL_MODULE_HOLDER_H_ -#define __SNOWBALL_MODULE_HOLDER_H_ - -namespace snowball { -namespace ir { - -/// Container class that holds a module pointer -class ModuleHolder { - protected: - std::shared_ptr module = nullptr; - - public: - ModuleHolder() = default; - - /// @brief Setter for a module pointer - void setModule(std::shared_ptr p_mod) { module = p_mod; } - /// @return A module pointer - std::shared_ptr getModule() { return module; } -}; - -} // namespace ir -} // namespace snowball - -#endif // __SNOWBALL_MODULE_HOLDER_H_ diff --git a/src/ir/builder/IRBuilder.cc b/src/ir/builder/IRBuilder.cc deleted file mode 100644 index e6d858d6..00000000 --- a/src/ir/builder/IRBuilder.cc +++ /dev/null @@ -1,209 +0,0 @@ - -#include "IRBuilder.h" -#include "../../ast/syntax/nodes.h" -#include "../../common.h" -#include "../../sourceInfo/DBGSourceInfo.h" - -namespace snowball { -namespace ir { - -IRBuilder::IRBuilder(std::shared_ptr module) { setModule(module); } -SharedValue IRBuilder::createFunction(DBGSourceInfo* dbgInfo, std::string name, bool isExtern, bool isVarArg, - bool isAnon) { - return N(dbgInfo, name, isExtern, isVarArg, isAnon); -} -SharedValue IRBuilder::createFunction( - DBGSourceInfo* dbgInfo, std::string name, Func::FunctionArgs args, bool isExtern, bool isVarArg, bool isAnon -) { - return N(dbgInfo, name, args, isExtern, isVarArg, isAnon); -} -SharedValue IRBuilder::createFunction( - DBGSourceInfo* dbgInfo, - std::string name, - SharedValue block, - Func::FunctionArgs args, - bool isExtern, - bool isVarArg, - bool isAnon -) { - return N(dbgInfo, name, block, args, isExtern, isVarArg, isAnon); -} -SharedValue IRBuilder::createFunction( - DBGSourceInfo* dbgInfo, std::string name, SharedValue block, bool isExtern, bool isVarArg, bool isAnon -) { - return createFunction(dbgInfo, name, block, {}, isExtern, isVarArg, isAnon); -} -SharedValue IRBuilder::createThrow(DBGSourceInfo* dbgInfo, SharedValue<> value) { - return N(dbgInfo, value); -} -SharedValue IRBuilder::createCast(DBGSourceInfo* dbgInfo, SharedValue<> value, Type<> type) { - auto cast = N(dbgInfo, value, type); - setType(cast, type); - return cast; -} -SharedValue IRBuilder::createIndexExtract( - DBGSourceInfo* dbgInfo, SharedValue<> value, types::DefinedType::ClassField* field, unsigned int index -) { - auto indexExtract = N(dbgInfo, value, field, index); - setType(indexExtract, field->type); - return indexExtract; -} -SharedValue IRBuilder::createArgument(DBGSourceInfo* dbgInfo, const std::string& name, Type<> type, - int scopeIndex) { - auto arg = createArgument(dbgInfo, name, 0, (Syntax::Expression::Base*) nullptr, scopeIndex); - if (type) setType(arg, type); - return arg; -} -SharedValue IRBuilder::createArgument( - DBGSourceInfo* dbgInfo, const std::string& name, int index, Syntax::Expression::Base* defaultValue, int scopeIndex -) { - return N(dbgInfo, name, index, defaultValue, scopeIndex); -} -SharedValue IRBuilder::createEnumInit(DBGSourceInfo* dbgInfo, types::EnumType* type, std::string name) { - auto init = N(dbgInfo, name); - setType(init, type); - return init; -} -SharedValue IRBuilder::createLoopFlow( - DBGSourceInfo* dbgInfo, LoopFlowType type) { - return N(dbgInfo, type); -} -SharedValue IRBuilder::createZeroInitialized(DBGSourceInfo* dbg, Type<> type) { - auto zero = N(dbg); - zero->setType(type); // already copied - return zero; -} -SharedValue IRBuilder::createArgument( - DBGSourceInfo* dbgInfo, const std::string& name, int index, Type<> type, Syntax::Expression::Base* defaultValue, - int scopeIndex -) { - auto arg = createArgument(dbgInfo, name, index, defaultValue, scopeIndex); - setType(arg, type); - return arg; -} -SharedValue -IRBuilder::createVariable(DBGSourceInfo* dbgInfo, const std::string& identifier, bool isArgument, bool isMutable, - int scopeIndex) { - return N(dbgInfo, identifier, isArgument, isMutable, scopeIndex); -} -SharedValue IRBuilder::createVariable( - DBGSourceInfo* dbgInfo, const std::string& identifier, Type<> type, bool isArgument, bool isMutable, int scopeIndex -) { - auto var = createVariable(dbgInfo, identifier, isArgument, isMutable, scopeIndex); - setType(var, type); - return var; -} -SharedValue IRBuilder::createBlock(DBGSourceInfo* dbgInfo) { return createBlock(dbgInfo, {}); } -SharedValue IRBuilder::createBlock(DBGSourceInfo* dbgInfo, std::vector> values) { - return N(dbgInfo, values); -} -SharedValue IRBuilder::createDereferenceTo(DBGSourceInfo* dbgInfo, SharedValue<> value, Type<> type) { - auto ref = N(dbgInfo, value); - setType(ref, type); - return ref; -} -SharedValue IRBuilder::createReferenceTo(DBGSourceInfo* dbgInfo, SharedValue<> value) { - auto ref = N(dbgInfo, value); - ref->setType(value->getType()->getReferenceTo()); - ref->getType()->setMutable(value->getType()->isMutable()); - return ref; -} -SharedValue IRBuilder::createStringValue(DBGSourceInfo* dbgInfo, const std::string value) { - return N(dbgInfo, value); -} -SharedValue IRBuilder::createNumberValue(DBGSourceInfo* dbgInfo, snowball_int_t value) { - return N(dbgInfo, value); -} -SharedValue IRBuilder::createFloatValue(DBGSourceInfo* dbgInfo, double value) { - return N(dbgInfo, value); -} -SharedValue IRBuilder::createBooleanValue(DBGSourceInfo* dbgInfo, bool value) { - return N(dbgInfo, value); -} -SharedValue IRBuilder::createCharValue(DBGSourceInfo* dbgInfo, char value) { - return N(dbgInfo, value); -} -SharedValue IRBuilder::createReturn(DBGSourceInfo* dbgInfo, SharedValue<> value) { - auto ret = N(dbgInfo, value); - if (value) setType(ret, value->getType()); - return ret; -} -SharedValue IRBuilder::createVoidReturn(DBGSourceInfo* dbgInfo) { return N(dbgInfo, nullptr); } -SharedValue IRBuilder::createCall(DBGSourceInfo* dbgInfo, SharedValue<> callee, ValueVec<> args) { - return N(dbgInfo, callee, args); -} -SharedValue IRBuilder::createVariableDeclaration( - DBGSourceInfo* dbgInfo, std::shared_ptr variable, SharedValue<> value, bool isExtern -) { - auto decl = N(dbgInfo, variable, value, isExtern); - if (value != nullptr) setType(decl, value->getType()); - else setType(decl, variable->getType()); - return decl; -} -SharedValue IRBuilder::createValueExtract(DBGSourceInfo* dbgInfo, SharedValue<> value) { - auto extract = N(dbgInfo, value); - setType(extract, value->getType()); - return extract; -} -SharedValue IRBuilder::createTryCatch( - DBGSourceInfo* dbgInfo, - SharedValue tryBlock, - std::vector> catchBlocks, - std::vector> catchVars -) { - return N(dbgInfo, tryBlock, catchBlocks, catchVars); -} -SharedValue -IRBuilder::createObjectInitialization(DBGSourceInfo* dbgInfo, types::Type* type, SharedValue<> value, ValueVec<> args, - bool isStruct) { - std::shared_ptr init = N(dbgInfo, value, args, isStruct); - setType(init, type); - return init; -} -SharedValue IRBuilder::createConditional( - DBGSourceInfo* dbgInfo, SharedValue<> condition, SharedValue thenBlock, SharedValue elseBlock -) { - return N(dbgInfo, condition, thenBlock, elseBlock); -} -SharedValue -IRBuilder::createWhileLoop(DBGSourceInfo* dbgInfo, SharedValue<> condition, SharedValue body, bool isDoWhile) { - return N(dbgInfo, condition, body, isDoWhile); -} -SharedValue IRBuilder::createFromForLoop( - DBGSourceInfo* dbgInfo, - SharedValue<> condition, - SharedValue body, - SharedValue<> forCond -) { - return N(dbgInfo, condition, body, forCond); -} -Type -IRBuilder::createFunctionType(std::vector> args, Type<> retType, bool isVarArg, bool isMutable) { - return new types::FunctionType(args, retType, isVarArg, isMutable); -} -SharedValue IRBuilder::createSwitch( - DBGSourceInfo* dbgInfo, SharedValue<> expr, std::vector cases, SharedValue defaultBlock -) { - return N(dbgInfo, expr, cases, defaultBlock); -} -SharedValue IRBuilder::createSwitch(DBGSourceInfo* dbgInfo, SharedValue<> expr, - std::vector cases, SharedValue defaultBlock) { - return N(dbgInfo, expr, cases, defaultBlock); -} -Type IRBuilder::createTypeAlias(DBGSourceInfo* dbg, std::string name, Type<> base) { - auto ty = new types::TypeAlias(name, base); - ty->unsafeSetModule(module); - ty->setSourceInfo(module->getSourceInfo()); - ty->setDBGInfo(dbg); - ty->setMutable(base->isMutable()); - return ty; -} -SharedValue IRBuilder::createBinaryOp(SharedValue call) { - auto op = N(call->getDBGInfo(), call->getCallee(), call->getArguments()); - op->isInitialization = call->isInitialization; - setType(op, call->getType()); - return op; -} -void IRBuilder::setType(SharedValue<> value, Type<> type) { value->setType(type); } -} // namespace ir -} // namespace snowball \ No newline at end of file diff --git a/src/ir/builder/IRBuilder.h b/src/ir/builder/IRBuilder.h deleted file mode 100644 index 10414ebf..00000000 --- a/src/ir/builder/IRBuilder.h +++ /dev/null @@ -1,223 +0,0 @@ - -#include "../../ast/types/DefinedType.h" -#include "../../ast/types/FunctionType.h" -#include "../../ast/types/Interface.h" -#include "../../ast/types/EnumType.h" -#include "../../ast/types/PrimitiveTypes.h" -#include "../../ast/types/TypeAlias.h" -#include "../../common.h" -#include "../../sourceInfo/DBGSourceInfo.h" - -#include "../ModuleHolder.h" -#include "../values/all.h" -#include "../values/Switch.h" -#include "../values/Argument.h" -#include "../values/Call.h" -#include "../values/EnumInit.h" -#include "../values/Cast.h" -#include "../values/Conditional.h" -#include "../values/Constants.h" -#include "../values/Dereference.h" -#include "../values/Func.h" -#include "../values/IndexExtract.h" -#include "../values/ReferenceTo.h" -#include "../values/Return.h" -#include "../values/Throw.h" -#include "../values/TryCatch.h" -#include "../values/Value.h" -#include "../values/ValueExtract.h" -#include "../values/WhileLoop.h" -#include "../values/LoopFlow.h" - -#include -#include - -#ifndef __SNOWBALL_IR_BUILDER_H_ -#define __SNOWBALL_IR_BUILDER_H_ -#define AST(x) Syntax::x* - -namespace snowball { -namespace ir { - -template -using SharedValue = std::shared_ptr; - -template -using Type = TypeName*; - -template -using ValueVec = std::vector>; - -/// @brief IRBuilder is a utility class to create new instructions -class IRBuilder : public AcceptorExtend { - friend ModuleHolder; - - public: - IRBuilder() = default; - IRBuilder(std::shared_ptr module); - - /// @brief Create a new function - SharedValue - createFunction(DBGSourceInfo* dbgInfo, std::string name, bool isExtern = false, bool isVarArg = false, - bool isAnon = false); - SharedValue createFunction( - DBGSourceInfo* dbgInfo, - std::string name, - Func::FunctionArgs args, - bool isExtern = false, - bool isVarArg = false, - bool isAnon = false - ); - SharedValue createFunction( - DBGSourceInfo* dbgInfo, - std::string name, - SharedValue block, - Func::FunctionArgs args, - bool isExtern = false, - bool isVarArg = false, - bool isAnon = false - ); - SharedValue createFunction( - DBGSourceInfo* dbgInfo, - std::string name, - SharedValue block, - bool isExtern = false, - bool isVarArg = false, - bool isAnon = false - ); - /// @brief Create a new cast - SharedValue createCast(DBGSourceInfo* dbgInfo, SharedValue<> value, Type<> type); - /// @brief Create a new index extract - SharedValue createIndexExtract( - DBGSourceInfo* dbgInfo, SharedValue<> value, types::DefinedType::ClassField* field, unsigned int index - ); - /// @brief Create a new argument value with the default parameters - SharedValue createArgument(DBGSourceInfo* dbgInfo, const std::string& name, Type<> type = nullptr, - int scopeIndex = -1); - /// @brief Create a new argument value - SharedValue createArgument( - DBGSourceInfo* dbgInfo, const std::string& name, int index, AST(Expression::Base) defaultValue = nullptr, - int scopeIndex = -1 - ); - /// @brief Create a new argument value and set a type to it - SharedValue createArgument( - DBGSourceInfo* dbgInfo, - const std::string& name, - int index, - Type<> type, - AST(Expression::Base) defaultValue = nullptr, - int scopeIndex = -1 - ); - /// @brief Create a new variable - SharedValue createVariable( - DBGSourceInfo* dbgInfo, const std::string& identifier, bool isArgument = false, bool isMutable = false, - int scopeIndex = -1 - ); - /// @brief Create a new variable and set a type to it - SharedValue createVariable( - DBGSourceInfo* dbgInfo, - const std::string& identifier, - Type<> type, - bool isArgument = false, - bool isMutable = false, - int scopeIndex = -1 - ); - /// @brief Create a new block - SharedValue createBlock(DBGSourceInfo* dbgInfo, std::vector> values); - /// @brief Create a new empty block - SharedValue createBlock(DBGSourceInfo* dbgInfo); - /// @brief Create a new throw instruction - SharedValue createThrow(DBGSourceInfo* dbgInfo, SharedValue<> value); - /// @brief Create a new reference to a value (pointer) - SharedValue createReferenceTo(DBGSourceInfo* dbgInfo, SharedValue<> value); - /// @brief Create a new dereference to a value (pointer) - SharedValue createDereferenceTo(DBGSourceInfo* dbgInfo, SharedValue<> value, Type<> type); - /// @brief Create a new string value - SharedValue createStringValue(DBGSourceInfo* dbgInfo, const std::string value); - /// @brief Create a new number value - SharedValue createNumberValue(DBGSourceInfo* dbgInfo, snowball_int_t value); - /// @brief Create a new float value - SharedValue createFloatValue(DBGSourceInfo* dbgInfo, double value); - /// @brief Create a new boolean value - SharedValue createBooleanValue(DBGSourceInfo* dbgInfo, bool value); - /// @brief Create a new char value - SharedValue createCharValue(DBGSourceInfo* dbgInfo, char value); - /// @brief Create a new return instruction - SharedValue createReturn(DBGSourceInfo* dbgInfo, SharedValue<> value); - /// @brief Create a new void return instruction - SharedValue createVoidReturn(DBGSourceInfo* dbgInfo); - /// @brief Create a new loop flow instruction - SharedValue createLoopFlow(DBGSourceInfo* dbgInfo, LoopFlowType type); - /// @brief Create a new call instruction - SharedValue createCall(DBGSourceInfo* dbgInfo, SharedValue<> callee, ValueVec<> args); - /// @brief Create a new enum type expression - SharedValue createEnumInit(DBGSourceInfo* dbgInfo, types::EnumType* type, std::string name); - /// @brief Create a new try/catch instruction - SharedValue createTryCatch( - DBGSourceInfo* dbgInfo, - SharedValue tryBlock, - std::vector> catchBlocks, - std::vector> catchVars - ); - /// @brief Create a new type - SharedValue createVariableDeclaration( - DBGSourceInfo* dbgInfo, std::shared_ptr variable, SharedValue<> value, bool isExtern = false - ); - /// @brief Create a extraction node from a value - SharedValue createValueExtract(DBGSourceInfo* dbgInfo, SharedValue<> value); - /// @brief Create a object initialization node - SharedValue - createObjectInitialization(DBGSourceInfo* dbgInfo, types::Type* type, SharedValue<> value, ValueVec<> args, - bool isStruct = false); - /// @brief Create a new conditional instruction (if/else) - SharedValue createConditional( - DBGSourceInfo* dbgInfo, SharedValue<> condition, SharedValue thenBlock, SharedValue elseBlock - ); - /// @brief Create a new switch instruction - SharedValue createSwitch( - DBGSourceInfo* dbgInfo, SharedValue<> expr, std::vector cases, SharedValue defaultBlock - ); - /// @brief Create a new c-style switch instruction - SharedValue createSwitch( - DBGSourceInfo* dbgInfo, SharedValue<> expr, std::vector cases, SharedValue defaultBlock - ); - /// @brief Create a new while loop - SharedValue - createWhileLoop(DBGSourceInfo* dbgInfo, SharedValue<> condition, SharedValue body, bool isDoWhile = false); - /// @brief Creates a while loop from a for loop - SharedValue createFromForLoop( - DBGSourceInfo* dbgInfo, - SharedValue<> condition, - SharedValue body, - SharedValue<> forCond - ); - /// @brief Create a new binary operation - /// @todo add more overloads for the binary operation - SharedValue createBinaryOp(SharedValue call); - /// @brief Create a new function type - Type - createFunctionType(std::vector> args, Type<> retType, bool isVarArg = false, bool isMutable = false); - /// @brief Create a new type alias - Type createTypeAlias(DBGSourceInfo* dbg, std::string name, Type<> base); - /// @brief Create a zero-initialized value - SharedValue createZeroInitialized(DBGSourceInfo* dbg, Type<> type); - /// @brief It sets a type to a value - /// @important When to use this function? - /// 1. val1->setType(val2->getType()) - /// When NOT to use this function? - /// 1. val1->setType(val2->getType()->getReferenceTo()) // copies base type - /// 2. val1->setType(builder.createNew[type](...)) // No need to copy - /// 3. val1->setType(transformType(...)) // already copies - void setType(SharedValue<> value, Type<> type); - /// @brief Utility function to create a new instruction - template - std::shared_ptr N(DBGSourceInfo* dbg, Args&&... args) { - return module->N(dbg, std::forward(args)...); - } -}; -} // namespace ir -} // namespace snowball - -#undef TYPE -#undef AST -#endif // __SNOWBALL_IR_BUILDER_H_ diff --git a/src/ir/id.h b/src/ir/id.h deleted file mode 100644 index cdb6b620..00000000 --- a/src/ir/id.h +++ /dev/null @@ -1,43 +0,0 @@ - -#include -#include - -#ifndef __SNOWBALL_ID_MIXIN_H_ -#define __SNOWBALL_ID_MIXIN_H_ - -namespace snowball { -namespace ir { - -using id_t = std::uint64_t; - -/// Mixin class for IR nodes that need ids. -class IdMixin { - private: - /// the global id counter - static id_t currentId; - - IdMixin& operator=(const IdMixin&) = delete; - - protected: - /// the instance's id - id_t id; - - public: - /// Resets the global id counter. - static void resetId(); - - IdMixin(const IdMixin&) = default; - IdMixin() : id(currentId++) { } - - /// @return the node's id. - virtual id_t getId() const { return id; } - /// @brief Set a "constant" ID to the IDMixin object it inherits - /// from. - /// @note This must be used wisely and not very often! - virtual void setId(id_t i) { id = i; } -}; - -} // namespace ir -} // namespace snowball - -#endif // __SNOWBALL_ID_MIXIN_H_ diff --git a/src/ir/module/MainModule.h b/src/ir/module/MainModule.h deleted file mode 100644 index 3d9887fd..00000000 --- a/src/ir/module/MainModule.h +++ /dev/null @@ -1,55 +0,0 @@ - -#include "../../common.h" -#include "../../sourceInfo/DBGSourceInfo.h" -#include "../values/Func.h" -#include "Module.h" - -#ifndef __SNOWBALL_MAIN_MODULE_H_ -#define __SNOWBALL_MAIN_MODULE_H_ - -/** - * @brief Main module - * - * The main module is considered as the "top level" - * version of the program. - * - * This module contains extra information such as; - * a pointer to the main function and untit tests. - */ -namespace snowball { -namespace ir { - -/// @brief The main module compiled from a snowball project -class MainModule : public Module { - /// @brief a list of generated modules through the whole project - std::vector> modules; - - public: - /** - * @brief Utility method to easily downcast. - * Useful when a child doesn't inherit directly from - * enable_shared_from_this but wants to use the feature. - * - * @todo move this to a generic class parent - */ - template - std::shared_ptr downcasted_shared_from_this() { - return std::dynamic_pointer_cast(Module::shared_from_this()); - } - - public: - MainModule() : Module("$main") {}; - - /// @return true because it's the entry point - bool isMain() override { return true; } - /// @return a list of generated modules through the whole project - std::vector> getModules() const { return modules; } - /// @brief add all the modules to the global generated modules list - void setModules(std::vector> m) { modules = m; } - - virtual ~MainModule() = default; -}; -} // namespace ir -} // namespace snowball - -#endif // __SNOWBALL_MAIN_MODULE_H_ diff --git a/src/ir/module/Module.h b/src/ir/module/Module.h deleted file mode 100644 index ae3e98ab..00000000 --- a/src/ir/module/Module.h +++ /dev/null @@ -1,83 +0,0 @@ - -#include "../../ast/syntax/nodes.h" -#include "../../ast/types/PrimitiveTypes.h" -#include "../../common.h" -#include "../../sourceInfo/DBGSourceInfo.h" - -#include -#include - -#ifndef __SNOWBALL_MODULE_H_ -#define __SNOWBALL_MODULE_H_ - -namespace snowball { -namespace Syntax::transform { -struct MacroInstance; -} // namespace Syntax::transform -namespace types { -class BaseType; -} -namespace ir { - -class Func; -class VariableDeclaration; - -/// @brief The representation of a programm -class Module : public SrcObject, public std::enable_shared_from_this { - // Module's name. The main modules has - // a default name. - std::string name; - // Unique identifier given to the module - // as string. - std::string uniqueName; - // A list containing all the functions that need to - // be generated. - std::vector> functions; - // A list of declared variables used for this module - std::vector> variables; - // A list of exported macros - std::unordered_map exportedMacros = {}; - - public: - Module(std::string name, std::string uuid = ""); - - /// @return module's name - std::string getName() const; - /// @return module's unique identifier (UUID) - std::string getUniqueName() const; - - // Boolean representing whether the module is global or not - virtual bool isMain() { return false; } - - // Return a list of defined functions used for our program - virtual std::vector> getFunctions() const { return functions; } - // Push a new function to the module - virtual void addFunction(std::shared_ptr fn) { functions.push_back(fn); } - // Append a new variable to the variable list - virtual void addVariable(std::shared_ptr v) { variables.push_back(v); } - // Get a list of user-declared variables for this module - const auto& getVariables() const { return variables; } - // Get a list of exported macros - const auto getExportedMacros() const { return exportedMacros; } - // Add a new exported macro - void addExportedMacro(std::string name, Syntax::transform::MacroInstance* macro) { exportedMacros[name] = macro; } - - /// @brief Utility function to create a new instruction - template - std::shared_ptr N(DBGSourceInfo* dbg, Args&&... args) { - auto ret = std::shared_ptr(new DesiredType(std::forward(args)...)); - ret->setModule(shared_from_this()); - ret->setSourceInfo(getSourceInfo()); - ret->setDBGInfo(dbg); - return ret; - } - - /// @brief A list containing the definitive type information - std::map> typeInformation; - - virtual ~Module() = default; -}; -} // namespace ir -} // namespace snowball - -#endif // __SNOWBALL_MODULE_H_ diff --git a/src/ir/module/Modules.cc b/src/ir/module/Modules.cc deleted file mode 100644 index 14757ae1..00000000 --- a/src/ir/module/Modules.cc +++ /dev/null @@ -1,26 +0,0 @@ - -#include "../../common.h" -#include "../../sourceInfo/DBGSourceInfo.h" -#include "Module.h" - -/** - * @brief Snowball module - * - * Snowball modules are used as containers - * that are represented as programs for our - * generator to use. - * - * Modules may contain things such as type - * declarations, enviroments and functions. - */ -namespace snowball { -namespace ir { - -Module::Module(const std::string name, const std::string uuid) : name(name), uniqueName(uuid.empty() ? name : uuid), - typeInformation({}) { } - -std::string Module::getName() const { return name; } -std::string Module::getUniqueName() const { return uniqueName; } - -} // namespace ir -} // namespace snowball \ No newline at end of file diff --git a/src/ir/values/Argument.h b/src/ir/values/Argument.h deleted file mode 100644 index 9907c1a1..00000000 --- a/src/ir/values/Argument.h +++ /dev/null @@ -1,51 +0,0 @@ - -#include "../../ValueVisitor/Visitor.h" -#include "../../ast/syntax/nodes.h" -#include "../../ast/types/Type.h" -#include "../../common.h" -#include "Value.h" -#include "VariableDeclaration.h" - -#include -#include -#include - -#ifndef __SNOWBALL_ARGUMENT_VALUE_H_ -#define __SNOWBALL_ARGUMENT_VALUE_H_ - -namespace snowball { -namespace ir { - -/// @brief This is just an utility class that we use in order to access -/// an argument. -class Argument : public AcceptorExtend { - /// @brief Argument index respective to the parent function arg list - int index = 0; - /// @brief default value used for the function - Syntax::Expression::Base* defaultValue = nullptr; - - public: - auto operator=(Argument*&) = delete; - Argument(const Argument&) = delete; - explicit Argument(const std::string& name, int index = 0, Syntax::Expression::Base* defaultValue = nullptr, - int scopeIndex = -1) - : AcceptorExtend(name, true, false, scopeIndex), index(index), defaultValue(defaultValue) {}; - - /// @return Argument index on the list - auto getIndex() { return index; } - /// @brief check if the function contains a default value - bool hasDefaultValue() { return defaultValue != nullptr; } - /// @return default value if it exists - auto getDefaultValue() { - assert(hasDefaultValue()); - return defaultValue; - } - - // Set a visit handler for the generators - SN_GENERATOR_VISITS -}; - -} // namespace ir -} // namespace snowball - -#endif // __SNOWBALL_ARGUMENT_VALUE_H_ diff --git a/src/ir/values/Body.h b/src/ir/values/Body.h deleted file mode 100644 index 076b9c1e..00000000 --- a/src/ir/values/Body.h +++ /dev/null @@ -1,44 +0,0 @@ - -#include "../../ValueVisitor/Visitor.h" -#include "../../ast/syntax/nodes.h" -#include "../../ast/types/Type.h" -#include "../../common.h" -#include "Value.h" - -#include -#include - -#ifndef __SNOWBALL_BLOCK_VALUE_H_ -#define __SNOWBALL_BLOCK_VALUE_H_ - -namespace snowball { -namespace ir { - -/** - * @brief Representation of block in the IR. This contains - * instructions that are executed inside of it. - */ -class Block : public AcceptorExtend, public AcceptorExtend { - // Instructions stored inside a block - std::vector> insts; - - public: - explicit Block(std::vector> insts) : insts(insts) {}; - - /// @return body block instructions - auto getBlock() { return insts; } - /// @brief It prepends a new instruction to the block - void prepend(std::shared_ptr inst) { insts.insert(insts.begin(), inst); } - /// @brief It prepends a new set of instructions to the block - void prepend(std::vector> inst) { - for (auto i = inst.rbegin(); i != inst.rend(); ++i) { prepend(*i); } - } - - // Set a visit handler for the generators - SN_GENERATOR_VISITS -}; - -} // namespace ir -} // namespace snowball - -#endif // __SNOWBALL_BLOCK_VALUE_H_ diff --git a/src/ir/values/Call.h b/src/ir/values/Call.h deleted file mode 100644 index 7dce935e..00000000 --- a/src/ir/values/Call.h +++ /dev/null @@ -1,108 +0,0 @@ - -#include "../../ValueVisitor/Visitor.h" -#include "../../ast/syntax/nodes.h" -#include "../../ast/types/Type.h" -#include "../../common.h" -#include "Value.h" - -#include -#include - -#ifndef __SNOWBALL_CALL_VALUE_H_ -#define __SNOWBALL_CALL_VALUE_H_ - -namespace snowball { -namespace ir { - -/** - * @brief Representation of a function call in the IR - */ -class Call : public AcceptorExtend { - // Function value that's being called - std::shared_ptr callee; - // Arguments passed to the function - std::vector> arguments; - - public: - explicit Call(std::shared_ptr callee, std::vector> args = {}) - : callee(callee), arguments(args) {}; - - /// @return function call arguments - auto& getArguments() { return arguments; } - /// @return function call arguments - auto getCallee() const { return callee; } - /// @brief Set a new list of arguments to the current call - void setArguments(std::vector> v) { arguments = v; } - - virtual bool isOperator() const { return false; }; - - // Set a visit handler for the generators - SN_GENERATOR_VISITS - - public: - /** - * @brief A variable used to fix a special occation for - * variable mutability. Uninitialized variables should - * allow an initial assigment (but just once). - * @example - * let a: i32; - * a = 10 // ok - * a = 20 // error - * @note It's a special variable for the OpType::EQ operator. - */ - bool isInitialization = false; -}; - -/** - * @brief Representation of the `new` operator. - * It's used to allocate a new object in the heap. - * @example - * let a = new A(); - */ -class ObjectInitialization : public AcceptorExtend { - friend Call; - - /// @brief If the created object is a constant struct - bool isStruct = false; - - public: - explicit ObjectInitialization(std::shared_ptr callee, std::vector> args = {}, bool - isStruct = false) - : AcceptorExtend(callee, args), isStruct(isStruct) { } - - /// @brief Wether or not the created object is a constant struct - bool isConstantStruct() const { return isStruct; } - - /// @brief The created object value. - /// @note It can be nullptr if the object requires a new allocation. - std::shared_ptr createdObject = nullptr; -}; - -/// @brief Representation of a binary operator -class BinaryOp : public AcceptorExtend { - friend Call; - - public: - explicit BinaryOp(std::shared_ptr callee, std::vector> args = {}) - : AcceptorExtend(callee, args) { } - - virtual bool isOperator() const { return true; }; - - /// @brief Wether or not ignore mutability checks - bool ignoreMutability = false; -}; - -/// @brief Representation of a zeroinitialized value -class ZeroInitialized : public AcceptorExtend { - friend Call; - - public: - explicit ZeroInitialized() : AcceptorExtend(nullptr, {}) { } - - virtual bool isOperator() const { return false; }; -}; - -} // namespace ir -} // namespace snowball - -#endif // __SNOWBALL_BLOCK_VALUE_H_ diff --git a/src/ir/values/Cast.h b/src/ir/values/Cast.h deleted file mode 100644 index 90e93923..00000000 --- a/src/ir/values/Cast.h +++ /dev/null @@ -1,42 +0,0 @@ - -#include "../../ValueVisitor/Visitor.h" -#include "../../ast/syntax/nodes.h" -#include "../../ast/types/Type.h" -#include "../../common.h" -#include "Value.h" - -#include -#include - -#ifndef __SNOWBALL_CAST_VALUE_H_ -#define __SNOWBALL_CAST_VALUE_H_ - -namespace snowball { -namespace ir { - -/** - * @brief Representation of a cast statement - * in the IR. - */ -class Cast : public AcceptorExtend { - /// @brief Expression used as value for the casting - std::shared_ptr expr = nullptr; - /// @brief Type to cast to - types::Type* castType; - - public: - explicit Cast(std::shared_ptr expr, types::Type* castType) : expr(expr), castType(castType) {}; - - /// @return value to cast - auto getExpr() { return expr; } - /// @return the result type to cast to - auto getCastType() { return castType; } - - // Set a visit handler for the generators - SN_GENERATOR_VISITS -}; - -} // namespace ir -} // namespace snowball - -#endif // __SNOWBALL_CAST_VALUE_H_ diff --git a/src/ir/values/Conditional.h b/src/ir/values/Conditional.h deleted file mode 100644 index 6e29b25c..00000000 --- a/src/ir/values/Conditional.h +++ /dev/null @@ -1,53 +0,0 @@ - -#include "../../ValueVisitor/Visitor.h" -#include "../../ast/syntax/nodes.h" -#include "../../ast/types/Type.h" -#include "../../common.h" -#include "Value.h" - -#include -#include - -#ifndef __SNOWBALL_CONDITIONAL_VALUE_H_ -#define __SNOWBALL_CONDITIONAL_VALUE_H_ - -namespace snowball { -namespace ir { - -/** - * @brief Representation of a conditional block or "if statement" in the - * IR. This contains instructions that are executed inside of it if a - * condition is met, if not, the "else" statement is executed if it - * exists. - */ -class Conditional : public AcceptorExtend { - // Instructions stored inside a block - std::shared_ptr insts; - // the expression to be evaluated - std::shared_ptr cond; - // The "else" statement block if the condition is false - std::shared_ptr elseBlock; - - public: - explicit Conditional( - std::shared_ptr cond, std::shared_ptr insts, std::shared_ptr elseBlock = nullptr - ) - : cond(cond), insts(insts), elseBlock(elseBlock) {}; - - /// @return body block instructions to execute - // if the condition is met - auto getBlock() { return insts; } - /// @return the expression to be evaluated - auto getCondition() { return cond; } - - /// @return Get "else" statement - auto getElse() { return elseBlock; } - - // Set a visit handler for the generators - SN_GENERATOR_VISITS -}; - -} // namespace ir -} // namespace snowball - -#endif // __SNOWBALL_CONDITIONAL_VALUE_H_ \ No newline at end of file diff --git a/src/ir/values/Constants.h b/src/ir/values/Constants.h deleted file mode 100644 index 69953ee3..00000000 --- a/src/ir/values/Constants.h +++ /dev/null @@ -1,112 +0,0 @@ - -#include "../../ValueVisitor/Visitor.h" -#include "../../ast/syntax/nodes.h" -#include "../../ast/types/Type.h" -#include "../../common.h" -#include "Body.h" -#include "Value.h" - -#include -#include - -#ifndef __SNOWBALL_CONSTANT_VALUES_H_ -#define __SNOWBALL_CONSTANT_VALUES_H_ - -namespace snowball { -namespace ir { - -/// @brief Representation of a constant value in the IR -class ConstantValue : public AcceptorExtend { - public: - enum ConstantType { -#include "../../defs/ct.def" - }; - - ConstantValue(ConstantType ty) : type(ty) { } - // Get constant value's type - auto getConstantType() { return type; } - - private: - // Type value to differentiate between constantss - ConstantType type; -}; - -/// @brief Constant representation of a string -class StringValue : public AcceptorExtend { - // Value stored from the AST - std::string value; - - public: - // Create a new string value for the IR - StringValue(std::string value) : AcceptorExtend(String), value(value) { } - - // Get the string value. - auto getConstantValue() const { return value; } - // Set a visit handler for the generators - SN_GENERATOR_VISITS -}; - -/// @brief Constant representation of an integer (32-bits) -class NumberValue : public AcceptorExtend { - // Value stored from the AST - snowball_int_t value; - - public: - // Create a new number constant for the IR - NumberValue(snowball_int_t value) : AcceptorExtend(Number), value(value) { } - - // Get the number value. - auto getConstantValue() const { return value; } - // Set a visit handler for the generators - SN_GENERATOR_VISITS -}; - -/// @brief Constant representation of a float (32-bits) -class FloatValue : public AcceptorExtend { - // Value stored from the AST - double value; - - public: - // Create a new floating number for the IR - FloatValue(double value) : AcceptorExtend(Float), value(value) { } - - // Get the number value. - auto getConstantValue() const { return value; } - // Set a visit handler for the generators - SN_GENERATOR_VISITS -}; - -/// @brief Constant representation of a boolean -class BooleanValue : public AcceptorExtend { - // Value stored from the AST - bool value; - - public: - // Create a new boolean value for the IR - BooleanValue(bool value) : AcceptorExtend(String), value(value) { } - - // Get the boolean value. - auto getConstantValue() const { return value; } - // Set a visit handler for the generators - SN_GENERATOR_VISITS -}; - -/// @brief Constant representation of a character (8-bit ints) -class CharValue : public AcceptorExtend { - // Value stored from the AST - char value; - - public: - // Create a new boolean value for the IR - CharValue(char value) : AcceptorExtend(Char), value(value) { } - - // Get the boolean value. - auto getConstantValue() const { return value; } - // Set a visit handler for the generators - SN_GENERATOR_VISITS -}; - -} // namespace ir -} // namespace snowball - -#endif // __SNOWBALL_CONSTANT_VALUES_H_ diff --git a/src/ir/values/Dereference.h b/src/ir/values/Dereference.h deleted file mode 100644 index ea8fa385..00000000 --- a/src/ir/values/Dereference.h +++ /dev/null @@ -1,41 +0,0 @@ - -#include "../../ValueVisitor/Visitor.h" -#include "../../ast/syntax/nodes.h" -#include "../../ast/types/DefinedType.h" -#include "../../ast/types/Type.h" -#include "../../ast/types/TypeAlias.h" -#include "../../common.h" -#include "Value.h" - -#include -#include - -#ifndef __SNOWBALL_DEREFERENCE_TO_VALUE_H_ -#define __SNOWBALL_DEREFERENCE_TO_VALUE_H_ - -namespace snowball { -namespace ir { - -/** - * @brief Representation of a dereference to a value in the IR. - */ -class DereferenceTo : public AcceptorExtend { - // Expression used as value for the dereference statement - std::shared_ptr value; - - public: - explicit DereferenceTo(std::shared_ptr value) : value(value) {}; - - /** - * @return The value it's being dereferenced to from. - */ - auto getValue() const { return value; } - - // Set a visit handler for the generators - SN_GENERATOR_VISITS -}; - -} // namespace ir -} // namespace snowball - -#endif // __SNOWBALL_REFERENCE_TO_VALUE_H_ diff --git a/src/ir/values/EnumInit.h b/src/ir/values/EnumInit.h deleted file mode 100644 index d0978641..00000000 --- a/src/ir/values/EnumInit.h +++ /dev/null @@ -1,42 +0,0 @@ - -#include "../../ValueVisitor/Visitor.h" -#include "../../ast/syntax/nodes.h" -#include "../../ast/types/DefinedType.h" -#include "../../ast/types/Type.h" -#include "../../ast/types/TypeAlias.h" -#include "../../common.h" -#include "Value.h" - -#include -#include - -#ifndef __SNOWBALL_ENUM_INIT_H_ -#define __SNOWBALL_ENUM_INIT_H_ - -namespace snowball { -namespace ir { - -/** - * @brief Enum initialization in the IR. - */ -class EnumInit : public AcceptorExtend { - // Enum field name - std::string name; - - public: - explicit EnumInit(std::string name) : name(name) {}; - - /** - * @return The name of the enum field. - */ - auto getName() const { return name; } - - // Set a visit handler for the generators - SN_GENERATOR_VISITS -}; - - -} // namespace ir -} // namespace snowball - -#endif // __SNOWBALL_ENUM_INIT_H_ diff --git a/src/ir/values/Func.cc b/src/ir/values/Func.cc deleted file mode 100644 index efdf3bce..00000000 --- a/src/ir/values/Func.cc +++ /dev/null @@ -1,118 +0,0 @@ - -#include "Func.h" - -#include "../../services/OperatorService.h" -#include "../../utils/utils.h" -#include "Argument.h" - -#include - -namespace snowball { -namespace ir { - -Func::Func(std::string identifier, bool declaration, bool variadic, bool isAnon, types::DefinedType* parent) - : declaration(declaration), variadic(variadic), identifier(identifier), parent(parent), anon(isAnon) { } - -Func::Func( - std::string identifier, - Func::FunctionArgs arguments, - bool declaration, - bool variadic, - bool isAnon, - types::DefinedType* parent -) - : declaration(declaration), variadic(variadic), anon(isAnon), identifier(identifier), parent(parent) { - setArgs(arguments); -} - -Func::Func( - std::string identifier, std::shared_ptr body, bool declaration, bool variadic, bool isAnon, - types::DefinedType* parent -) - : declaration(declaration), variadic(variadic), identifier(identifier), parent(parent), anon(isAnon) { - setBody(body); -} - -Func::Func( - std::string identifier, - std::shared_ptr body, - Func::FunctionArgs arguments, - bool declaration, - bool variadic, - bool isAnon, - types::DefinedType* parent -) - : declaration(declaration), variadic(variadic), identifier(identifier), parent(parent), anon(isAnon) { - setBody(body); - setArgs(arguments); -} - -bool Func::isConstructor() const { - return (services::OperatorService::opEquals(identifier)) && hasParent(); -} - -std::string Func::getIdentifier() { return identifier; } -std::string Func::getName(bool ignoreOperators) { - if (services::OperatorService::isOperator(identifier) && (!ignoreOperators)) { - auto op = services::OperatorService::operatorID(identifier); - return services::OperatorService::operatorName(op); - } - return getIdentifier(); -} - -Func::FunctionArgs Func::getArgs(bool ignoreSelf) const { - auto argv = arguments; - if (ignoreSelf && argv.size() > 0 && ((hasParent() && (!_static)) || isConstructor())) { argv.erase(argv.begin()); } - return argv; -} - -bool Func::isExternal(std::string name) { return !utils::startsWith(name, _SN_MANGLE_PREFIX); } - -std::string Func::getNiceName() { - auto base = hasParent() ? (parent->getPrettyName() + "::") : module->isMain() ? "" : module->getName() + "::"; - std::string generics = ""; - if (isGeneric()) { - generics = "<"; - for (auto g : getGenerics()) { - generics += g.second->getPrettyName(); - if (g != getGenerics().back()) generics += ", "; - } - generics += ">"; - } - auto name = getName(); - auto n = base + getName() + generics; - if (utils::startsWith(base, _SNOWBALL_CONST_PTR_DECL) || utils::startsWith(base, _SNOWBALL_MUT_PTR_DECL)) { - n = base + getName(); - } - return n; -} - -std::string Func::getMangle() { - if (!externalName.empty()) return externalName; - if (hasAttribute(Attributes::EXPORT)) { - auto args = getAttributeArgs(Attributes::EXPORT); - auto name = args.find("name"); - if (name != args.end()) { return name->second; } - } - if (hasAttribute(Attributes::NO_MANGLE)) return getIdentifier(); - // TODO: add class to here - auto base = hasParent() ? parent->getMangledName() : module->getUniqueName(); - auto name = getIdentifier(); - if (utils::endsWith(name, _SNOWBALL_LAMBDA_FUNCTIONS)) { - name = name.substr(0, name.size() - (_SNOWBALL_LAMBDA_SIZE + 1)) + ".$LmbdF"; - } - std::string prefix = (utils::startsWith(base, _SN_MANGLE_PREFIX) ? base : (_SN_MANGLE_PREFIX + base)) + +"&" + - std::to_string(name.size()) + name // Function name with modules - + "Cv" + std::to_string(getId()); // disambiguator - std::string mangledArgs = "Sa"; // Start args tag - int argCounter = 1; - for (auto a : arguments) { - mangledArgs += "A" + std::to_string(argCounter) + a.second->getType()->getMangledName(); - argCounter++; - } - std::string mangled = prefix + mangledArgs + "FnE"; // FnE = end of function - return mangled; -} - -} // namespace ir -} // namespace snowball diff --git a/src/ir/values/Func.h b/src/ir/values/Func.h deleted file mode 100644 index e656d1b6..00000000 --- a/src/ir/values/Func.h +++ /dev/null @@ -1,266 +0,0 @@ - -#include "../../ValueVisitor/Visitor.h" -#include "../../ast/syntax/nodes.h" -#include "../../ast/types/DefinedType.h" -#include "../../ast/types/Type.h" -#include "../../ast/types/TypeAlias.h" -#include "../../builder/llvm/LLVMIRChunk.h" -#include "../../common.h" -#include "../../constants.h" -#include "Body.h" -#include "Value.h" -#include "Variable.h" -#include "VariableDeclaration.h" - -#include -#include -#include - -#ifndef __SNOWBALL_FUNC_VAL_H_ -#define __SNOWBALL_FUNC_VAL_H_ -namespace snowball { - -namespace ir { - -/// @brief Representation of a function in the IR -class Func : public AcceptorExtend, - public IdMixin, - public AcceptorExtend, - public AcceptorExtend>>, - public AcceptorExtend { - public: - // Utility types - using FunctionArgs = std::list>>; - - private: - /// When a function is variadic, it means that - /// it can take a variable number of arguments. - bool variadic = false; - /// A virtual function is a member function of a - /// class that can be overridden in a derived class. - /// When a virtual function is called through a pointer - /// or reference to the base class, the implementation - /// of the derived class is invoked instead of the - /// implementation of the base class. - /// @note If it's equal to "-1" that means that it does - /// not form part of a virtual table. - int virtualIndex = -1; - - /// These are used to use the function without - /// actually setting the body inside it, it's - /// just a forward declaration. - bool declaration = false; - /// Function's identifier - std::string identifier; - /// Function's return type - types::Type* retTy; - /// @brief Parent class that this function is defined - /// in. - types::Type* parent = nullptr; - - /// Function parameters are the names listed in - /// the function definition. Function arguments - /// are the real values passed to (and received by) - /// the function. - FunctionArgs arguments; - - /// There are the instructions executed inside - /// the function. note: if there is non, this means - /// that the function could be potentially a declaration - std::shared_ptr body; - - /// There are the LLVM Ir instructions executed inside - /// the function - std::vector llvmBody; - - /// A list of variables used *anywhere* around the function. - /// This is so that we allocate a new variable at the start - /// of the function. We do this to avoid any kind of errors - /// such as; allocating new memory each time we iterate in a loop. - std::vector> symbols; - - /// This is how the function will be exported. If the name is empty, - /// snowball will mangle the name accordingly but if it's not, this - /// string will be used as an external identifier. This is used for - /// things such as; declaring the function entry point and declaring - /// external functions - std::string externalName; - - /// Functions can be declared static too! We have this utility - /// variable to determine if the function is declared as one. Being - /// declared as static may bring different meanings. - /// @example Static function for a class - bool _static = false; - - /// @brief This is used to determine if the function is an anonymous - /// function or not. - bool anon = false; - - /// @brief The scope index where the function is declared in. - /// This is used for things such as; determining if a function - /// is declared inside a class or not, etc... - int scopeIndex = -1; - - /// @brief Parent scope where the anon. function is declared in. - /// This is used for things such as; determining if a function - /// is declared inside a class or not, etc... - std::shared_ptr parentScope = nullptr; - - /// @brief If the anon. function uses variables from the parent - /// scope. - bool _usesParentScope = false; - - Func(const Func&) = delete; - Func& operator=(Func const&); - - public: -#define DEFAULT bool declaration = false, bool variadic = false, bool isAnon = false, types::DefinedType *ty = nullptr - - explicit Func(std::string identifier, DEFAULT); - explicit Func(std::string identifier, FunctionArgs arguments, DEFAULT); - explicit Func(std::string identifier, std::shared_ptr body, DEFAULT); - explicit Func(std::string identifier, std::shared_ptr body, FunctionArgs arguments, DEFAULT); - -#undef DEFAULT - - /// @return Whether the function is variadic - bool isVariadic() const { return variadic; } - /// @return Whether the function is a declaration - bool isDeclaration() const { return declaration; } - - /// @return function's raw identifier - virtual std::string getIdentifier(); - /// @return The same as @fn getIdentifier but it also handles - /// operator names. - virtual std::string getName(bool ignoreOperators = false); - /// @return mangled name for the function. - virtual std::string getMangle(); - /// @return Function's pretty name for debbuging - virtual std::string getNiceName(); - - /// @brief Set a body to a function - void setBody(std::shared_ptr p_body) { body = p_body; } - /// @return Get body from function - auto getBody() const { return body; } - - /// @brief Declare a new LLVM IR body - /// @param llvmBody the LLVM IR instructions - void setLLVMBody(std::vector llvmBody) { this->llvmBody = llvmBody; } - /// @return the LLVM ir body for this function - auto getLLVMBody() { - assert(!isDeclaration() && hasAttribute(Attributes::LLVM_FUNC)); - return llvmBody; - } - /// @brief Set arguments to a function - void setArgs(FunctionArgs p_args) { arguments = p_args; } - /// @return Get arguments from function - /// @param ignoreSelf removes the `self` paramter (aka. the first / - /// class parameter) - /// if it's set to `true`. - FunctionArgs getArgs(bool ignoreSelf = false) const; - - /// @brief Set a return type to a function - void setRetTy(types::Type* p_ret) { retTy = p_ret; } - /// @return Get function's return type. - auto& getRetTy() const { return retTy; } - - /// @brief Set a return type to a function - void addSymbol(std::shared_ptr v) { symbols.emplace_back(v); } - /// @return Get function's return type. - std::vector>& getSymbols() { - assert(!isDeclaration()); - return symbols; - } - /// @brief set from what parent this function is declared inside - void setParent(types::Type* x) { parent = x; } - /// @brief get from what parent this function is declared inside - auto getParent() const { return parent; } - /// @return whether or not the function is defiend within a - /// parent scope. - bool hasParent() const { return getParent() != nullptr; } - - /// @brief Get the index were the function is located at inside the - /// virtual table. - auto getVirtualIndex() const { - assert(inVirtualTable()); - return virtualIndex; - } - /// @return Check if the function is part of a virtual table. - bool inVirtualTable() const { return virtualIndex != -1; } - /// @brief Set a new virtual table index. - void setVirtualIndex(int x = -1) { virtualIndex = x; } - - /// @brief Set an external name to the function - /// @c externalName - void setExternalName(std::string n) { externalName = n; } - /// @brief Declare the function as static or not - void setStatic(bool s = false) { _static = s; } - /// @return whether or not the function is static - auto isStatic() { return _static; } - /// @return true if the function is a class contructor - bool isConstructor() const; - /// @return true if the function is an anonymous function - bool isAnon() const { return anon; } - - /// @brief Set the scope index where the function is declared in. - void setScopeIndex(int x) { scopeIndex = x; } - /// @return the scope index where the function is declared in. - auto getScopeIndex() const { return scopeIndex; } - - /// @brief Set the parent scope where the function is declared in. - void setParentScope(std::shared_ptr x) { parentScope = x; } - /// @return the parent scope where the function is declared in. - auto getParentScope() const { return parentScope; } - - /// @brief Set that the function uses variables from the parent scope. - void setUsesParentScope(bool x = true) { assert(isAnon()); _usesParentScope = x; } - /// @return true if the function uses variables from the parent scope. - auto usesParentScope() const { assert(isAnon()); return _usesParentScope; } - - // Set a visit handler for the generators - SN_GENERATOR_VISITS - public: - /** - * @brief Static function to detect if it's external or not - * @c setExternalName @c externalName - */ - static bool isExternal(std::string name); - /** - * @brief Static helper to check if argument size are valid. - * @note this is used for checking between 2 arguments. - * - * @param isVariadic if the function is variadic, first list of - * arguments can be greater that the function arguments. - */ - template - static bool - argumentSizesEqual(std::vector functionArgs, const std::vector arguments, bool isVariadic = false) { - auto numFunctionArgs = functionArgs.size(); - auto numProvidedArgs = arguments.size(); - int numDefaultArgs = 0; - // DUMP((std::is_same_v::value)) - // Calculate the number of default arguments - if (numFunctionArgs > numProvidedArgs) { - if constexpr(std::is_same_v) { - for (size_t i = numProvidedArgs; i < numFunctionArgs; i++) { - if (functionArgs.at(i)->hasDefaultValue()) { - numDefaultArgs++; - } else { - // If we encounter a non-default argument, stop - // counting - break; - } - } - } - } - return (numFunctionArgs - numDefaultArgs == numProvidedArgs) || (numFunctionArgs <= arguments.size() && isVariadic); - } - - /// @brief `super()` call value if it's present and if the function is a constructor. - std::shared_ptr superCall = nullptr; -}; - -} // namespace ir -} // namespace snowball - -#endif // __SNOWBALL_FUNC_VAL_H_ diff --git a/src/ir/values/IndexExtract.h b/src/ir/values/IndexExtract.h deleted file mode 100644 index c2a10a0a..00000000 --- a/src/ir/values/IndexExtract.h +++ /dev/null @@ -1,58 +0,0 @@ - -#include "../../ValueVisitor/Visitor.h" -#include "../../ast/syntax/nodes.h" -#include "../../ast/types/DefinedType.h" -#include "../../ast/types/Type.h" -#include "../../ast/types/TypeAlias.h" -#include "../../common.h" -#include "Value.h" - -#include -#include - -#ifndef __SNOWBALL_INDEX_EXTRACT_VALUE_H_ -#define __SNOWBALL_INDEX_EXTRACT_VALUE_H_ - -namespace snowball { -namespace ir { - -/** - * @brief Representation of an index extraction statement - * in the IR. - */ -class IndexExtract : public AcceptorExtend { - // Expression used as value for the index statement - std::shared_ptr value; - // Index were the extraction is taken place. - unsigned int index; - // Field being extracted from - types::DefinedType::ClassField* field; - - public: - explicit IndexExtract(std::shared_ptr value, types::DefinedType::ClassField* field, unsigned int i) - : value(value), index(i), field(field) {}; - - /** - * @return The value it's being extracted - * from. - */ - auto getValue() const { return value; } - /** - * @brief Get the index used for the index - * extraction - */ - virtual unsigned int getIndex() const { return index; } - /** - * @brief Get the field object from the value we are - * trying to extract - */ - virtual types::DefinedType::ClassField* getField() const { return field; } - - // Set a visit handler for the generators - SN_GENERATOR_VISITS -}; - -} // namespace ir -} // namespace snowball - -#endif // __SNOWBALL_INDEX_EXTRACT_VALUE_H_ diff --git a/src/ir/values/LoopFlow.h b/src/ir/values/LoopFlow.h deleted file mode 100644 index 3b2231dd..00000000 --- a/src/ir/values/LoopFlow.h +++ /dev/null @@ -1,41 +0,0 @@ - -#include "../../ValueVisitor/Visitor.h" -#include "../../ast/syntax/nodes.h" -#include "../../ast/types/Type.h" -#include "Value.h" - -#include -#include - -#ifndef __SNOWBALL_LOOP_FLOW_H_ -#define __SNOWBALL_LOOP_FLOW_H_ - -namespace snowball { -namespace ir { - -/** - * @brief Representation of a loop flow statement in the IR. - */ -class LoopFlow : public AcceptorExtend { - public: - using Type = Syntax::Statement::LoopFlow::FlowType; - private: - Type flowType; - public: - explicit LoopFlow(Type type) : flowType(type) {}; - - /** - * @return The type of the loop flow statement. - */ - auto getFlowType() const { return flowType; } - - // Set a visit handler for the generators - SN_GENERATOR_VISITS -}; - -using LoopFlowType = LoopFlow::Type; - -} // namespace ir -} // namespace snowball - -#endif // __SNOWBALL_LOOP_FLOW_H_ diff --git a/src/ir/values/ReferenceTo.h b/src/ir/values/ReferenceTo.h deleted file mode 100644 index 664c1ed1..00000000 --- a/src/ir/values/ReferenceTo.h +++ /dev/null @@ -1,41 +0,0 @@ - -#include "../../ValueVisitor/Visitor.h" -#include "../../ast/syntax/nodes.h" -#include "../../ast/types/DefinedType.h" -#include "../../ast/types/Type.h" -#include "../../ast/types/TypeAlias.h" -#include "../../common.h" -#include "Value.h" - -#include -#include - -#ifndef __SNOWBALL_REFERENCE_TO_VALUE_H_ -#define __SNOWBALL_REFERENCE_TO_VALUE_H_ - -namespace snowball { -namespace ir { - -/** - * @brief Representation of a reference to a value in the IR. - */ -class ReferenceTo : public AcceptorExtend { - // Expression used as value for the reference statement - std::shared_ptr value; - - public: - explicit ReferenceTo(std::shared_ptr value) : value(value) {}; - - /** - * @return The value it's being referenced to from. - */ - auto getValue() const { return value; } - - // Set a visit handler for the generators - SN_GENERATOR_VISITS -}; - -} // namespace ir -} // namespace snowball - -#endif // __SNOWBALL_REFERENCE_TO_VALUE_H_ diff --git a/src/ir/values/Return.h b/src/ir/values/Return.h deleted file mode 100644 index c7c0a803..00000000 --- a/src/ir/values/Return.h +++ /dev/null @@ -1,42 +0,0 @@ - -#include "../../ValueVisitor/Visitor.h" -#include "../../ast/syntax/nodes.h" -#include "../../ast/types/Type.h" -#include "../../common.h" -#include "Value.h" - -#include -#include - -#ifndef __SNOWBALL_RETURN_VALUE_H_ -#define __SNOWBALL_RETURN_VALUE_H_ - -namespace snowball { -namespace ir { - -/** - * @brief Representation of a return statement - * in the IR. - */ -class Return : public AcceptorExtend { - // Expression used as value for the return statement - std::shared_ptr expr = nullptr; - - public: - explicit Return(std::shared_ptr expr) : expr(expr) {}; - - /** - * @return value to return - * @note The value may be std::nullptr because - * the user might do `return;` for void functions - */ - auto getExpr() { return expr; } - - // Set a visit handler for the generators - SN_GENERATOR_VISITS -}; - -} // namespace ir -} // namespace snowball - -#endif // __SNOWBALL_RETURN_VALUE_H_ diff --git a/src/ir/values/Switch.h b/src/ir/values/Switch.h deleted file mode 100644 index 8e8ea3c1..00000000 --- a/src/ir/values/Switch.h +++ /dev/null @@ -1,72 +0,0 @@ - -#include "../../ValueVisitor/Visitor.h" -#include "../../ast/syntax/nodes.h" -#include "../../ast/types/Type.h" -#include "../../common.h" -#include "Value.h" - -#include -#include - -#ifndef __SNOWBALL_SWITCH_VALUE_H_ -#define __SNOWBALL_SWITCH_VALUE_H_ - -namespace snowball { -namespace ir { - -/** - * @brief Representation of a switch statement - * in the IR. - */ -class Switch : public AcceptorExtend { - public: - /// @brief Case for the switch - struct Case { - /// @brief Value to compare - std::vector> args; - /// @brief Block to jump to - std::shared_ptr block; - /// @brief Name of the case - std::string name; - }; - /// @brief C-style switch case - struct CStyleCase { - /// @brief Value to compare - std::shared_ptr value; - /// @brief Block to jump to - std::shared_ptr block; - }; - private: - /// @brief Expression used as value for the switch - std::shared_ptr expr = nullptr; - /// @brief Cases for the switch - std::pair, std::vector> cases; - /// @brief Default case for the switch - std::shared_ptr defaultCase = nullptr; - /// @brief If the switch is a C-style switch - bool cStyleSwitch = false; - - public: - explicit Switch(std::shared_ptr expr, std::vector cases, std::shared_ptr defaultCase = nullptr) - : expr(std::move(expr)), cases(std::move(cases), {}), defaultCase(std::move(defaultCase)) {} - explicit Switch(std::shared_ptr expr, std::vector cases, - std::shared_ptr defaultCase = nullptr) - : expr(std::move(expr)), cases({}, std::move(cases)), defaultCase(std::move(defaultCase)), cStyleSwitch(true) {} - - /// @return expression used as value for the switch - auto getExpr() const { return expr; } - /// @return cases for the switch - auto getCases() const { return cases; } - /// @return default case for the switch - auto getDefaultCase() const { return defaultCase; } - /// @return if the switch is a C-style switch - auto isCStyleSwitch() const { return cStyleSwitch; } - - // Set a visit handler for the generators - SN_GENERATOR_VISITS -}; - -} // namespace ir -} // namespace snowball - -#endif // __SNOWBALL_SWITCH_VALUE_H_ diff --git a/src/ir/values/Throw.h b/src/ir/values/Throw.h deleted file mode 100644 index 42b01512..00000000 --- a/src/ir/values/Throw.h +++ /dev/null @@ -1,44 +0,0 @@ - -#include "../../ValueVisitor/Visitor.h" -#include "../../ast/syntax/nodes.h" -#include "../../ast/types/Type.h" -#include "../../common.h" -#include "Value.h" - -#include -#include - -#ifndef __SNOWBALL_THROW_VALUE_H_ -#define __SNOWBALL_THROW_VALUE_H_ - -namespace snowball { -namespace ir { - -/** - * @brief Representation of a throw statement in the IR. - * @note This is not the same as the throw statement in C++. - * This is more like the throw statement in Java. - * @see https://docs.oracle.com/javase/tutorial/essential/exceptions/throwing.html - */ -class Throw : public AcceptorExtend { - // Expression used as value for the throw statement - std::shared_ptr expr = nullptr; - - public: - explicit Throw(std::shared_ptr expr) : expr(expr) {}; - - /** - * @return value to throw - * @note The value may be std::nullptr because - * the user might do `throw;` for void functions - */ - auto getExpr() { return expr; } - - // Set a visit handler for the generators - SN_GENERATOR_VISITS -}; - -} // namespace ir -} // namespace snowball - -#endif // __SNOWBALL_RETURN_VALUE_H_ diff --git a/src/ir/values/TryCatch.h b/src/ir/values/TryCatch.h deleted file mode 100644 index d331f064..00000000 --- a/src/ir/values/TryCatch.h +++ /dev/null @@ -1,55 +0,0 @@ - -#include "../../ValueVisitor/Visitor.h" -#include "../../ast/syntax/nodes.h" -#include "../../ast/types/Type.h" -#include "../../common.h" -#include "Value.h" - -#include -#include - -#ifndef __SNOWBALL_TRY_CATCH_VALUE_H_ -#define __SNOWBALL_TRY_CATCH_VALUE_H_ - -namespace snowball { -namespace ir { - -/** - * @brief Representation of a try-catch block in the IR. - * @note This is not the same as the try-catch block in C++. - * This is more like the try-catch block in Java. - * @see https://docs.oracle.com/javase/tutorial/essential/exceptions/try.html - */ -class TryCatch : public AcceptorExtend { - // The block to execute - std::shared_ptr block; - // The catch block - std::vector> catchBlocks; - // Catch types - std::vector> catchVars; - - public: - explicit TryCatch( - std::shared_ptr block, - std::vector> catchBlocks, - std::vector> catchVars - ) - : block(block), catchBlocks(catchBlocks), catchVars(catchVars) {}; - - /// @return body block instructions to execute - auto getBlock() { return block; } - - /// @return the catch blocks - auto getCatchBlocks() { return catchBlocks; } - - /// @return the catch types - auto getCatchVars() { return catchVars; } - - // Set a visit handler for the generators - SN_GENERATOR_VISITS -}; - -} // namespace ir -} // namespace snowball - -#endif // __SNOWBALL_TRY_CATCH_VALUE_H_ diff --git a/src/ir/values/Value.h b/src/ir/values/Value.h deleted file mode 100644 index 09527a02..00000000 --- a/src/ir/values/Value.h +++ /dev/null @@ -1,46 +0,0 @@ - -#include "../../ValueVisitor/Visitor.h" -#include "../../ast/types/Type.h" -#include "../../common.h" -#include "../ModuleHolder.h" -#include "../id.h" - -#ifndef __SNOWBALL_VALUE_H_ -#define __SNOWBALL_VALUE_H_ - -#define SN_GENERATOR_VISITS \ - void visit(codegen::ValueVisitor* v) override { v->visit(this); }; - -/** - * @brief Snowball values - */ -namespace snowball { -namespace ir { - -/// In snowball's internal IR, -class Value : public ModuleHolder, public DBGObject { - types::Type* type; - - Value(const Value*&) = delete; - Value(const Value&) = delete; - Value(const Value&&) = delete; - Value& operator=(const Value&) = delete; - - public: - virtual ~Value() noexcept = default; - Value() = default; - Value(types::Type* p_type) { type = p_type; }; - - /// @return get value's type - virtual types::Type* getType() const { return type; } - /// @brief get value's type - virtual void setType(types::Type* p_type) { type = p_type; } - - // Generate helper function - virtual void visit(codegen::ValueVisitor* v) = 0; -}; - -} // namespace ir -} // namespace snowball - -#endif // __SNOWBALL_VALUE_H_ diff --git a/src/ir/values/ValueExtract.h b/src/ir/values/ValueExtract.h deleted file mode 100644 index 82b04b16..00000000 --- a/src/ir/values/ValueExtract.h +++ /dev/null @@ -1,38 +0,0 @@ - -#include "../../ValueVisitor/Visitor.h" -#include "../../ast/syntax/nodes.h" -#include "../../ast/types/Type.h" -#include "../../common.h" -#include "Value.h" - -#include -#include - -#ifndef __SNOWBALL_VALUE_EXTRACT_VALUE_H_ -#define __SNOWBALL_VALUE_EXTRACT_VALUE_H_ - -namespace snowball { -namespace ir { - -/** - * @brief A value extract represents the use of (e.g.) an - * identifier. - */ -class ValueExtract : public AcceptorExtend { - // Value being extracted - std::shared_ptr value; - - public: - explicit ValueExtract(std::shared_ptr variable) : value(variable) {}; - - /// @return The stored value - auto getValue() { return value; } - - // Set a visit handler for the generators - SN_GENERATOR_VISITS -}; - -} // namespace ir -} // namespace snowball - -#endif // __SNOWBALL_VALUE_EXTRACT_VALUE_H_ diff --git a/src/ir/values/Variable.h b/src/ir/values/Variable.h deleted file mode 100644 index 78ffaf50..00000000 --- a/src/ir/values/Variable.h +++ /dev/null @@ -1,65 +0,0 @@ - -#include "../../ValueVisitor/Visitor.h" -#include "../../ast/syntax/nodes.h" -#include "../../ast/types/Type.h" -#include "../../common.h" -#include "Value.h" - -#include -#include - -#ifndef __SNOWBALL_VARIABLE_VALUE_H_ -#define __SNOWBALL_VARIABLE_VALUE_H_ - -namespace snowball { -namespace ir { - -/// @brief Representation of a variable access inside the IR. -class Variable : public IdMixin, public AcceptorExtend { - // Identifier we use to fetch the variable - std::string identifier; - // If the variable is marked as an argument, we can make certain - // actions for this specific occasion. - bool _isArgument = false; - // Whether or not the variable is mutable - bool _isMutable = false; - // Scope index of the variable - int scopeIndex = -1; - // Whether or not the variable is used inside a lambda - bool _isUsedInLambda = false; - // Function where the variable is defined in - Func* parentFunc = nullptr; - - public: - // Create a new variable declaration - Variable(const std::string& identifier, bool isArgument = false, bool isMutable = false, int scopeIndex = -1) - : identifier(identifier), _isArgument(isArgument), _isMutable(isMutable), scopeIndex(scopeIndex) {}; - - /// @return Variable identifier - auto getIdentifier() const { return identifier; } - /// @return Wether or not the variable points to an argument - auto isArgument() { return _isArgument; } - /// @return true if the variable is mutable - auto isMutable() { return _isMutable; } - /// @return Scope index of the variable - auto getScopeIndex() { return scopeIndex; } - /// @return true if the variable is used inside a lambda - auto isUsedInLambda() { return _isUsedInLambda; } - /// @brief Set if the variable is used inside a lambda - void setUsedInLambda(bool used = true) { _isUsedInLambda = used; } - /// @return Function where the variable is defined in - auto getParentFunc() { assert(isUsedInLambda()); return parentFunc; } - /// @brief Set the function where the variable is defined in - void setParentFunc(Func* func) { assert(isUsedInLambda()); parentFunc = func; } - - /// @brief Set the mutable flag - void setMutability(bool isMutable) { _isMutable = isMutable; } - - // Set a visit handler for the generators - SN_GENERATOR_VISITS -}; - -} // namespace ir -} // namespace snowball - -#endif // __SNOWBALL_VARIABLE_VALUE_H_ diff --git a/src/ir/values/VariableDeclaration.h b/src/ir/values/VariableDeclaration.h deleted file mode 100644 index 8def3ec4..00000000 --- a/src/ir/values/VariableDeclaration.h +++ /dev/null @@ -1,54 +0,0 @@ - -#include "../../ValueVisitor/Visitor.h" -#include "../../ast/syntax/nodes.h" -#include "../../ast/types/Type.h" -#include "../../common.h" -#include "Value.h" -#include "Variable.h" - -#include -#include - -#ifndef __SNOWBALL_VARIABLE_DECL_VALUE_H_ -#define __SNOWBALL_VARIABLE_DECL_VALUE_H_ - -namespace snowball { -namespace ir { -class Argument; - -/// @brief Representation of a variable declaration in the IR -/// Variable declarations can be then used as a way to store values -/// and access them when needed. -class VariableDeclaration : public IdMixin, public AcceptorExtend { - // Variable we are declaring - std::shared_ptr variable; - // Value stored into the current variable - std::shared_ptr value; - // If the variable has been externally declared - bool external = false; - - protected: - friend Argument; - - public: - // Create a new variable declaration - VariableDeclaration(std::shared_ptr variable, std::shared_ptr value, bool external = false) - : variable(variable), value(value), external(external) {} - - /// @return Variable value - auto& getVariable() const { return variable; } - /// @return Variable identifier - std::string getIdentifier() const { return variable->getIdentifier(); } - /// @return respective value stored into the current variable - auto getValue() const { return value; } - /// @return if the variable has been externally declared - bool isExternDecl() const { return external; } - - // Set a visit handler for the generators - SN_GENERATOR_VISITS -}; - -} // namespace ir -} // namespace snowball - -#endif // __SNOWBALL_VARIABLE_DECL_VALUE_H_ diff --git a/src/ir/values/WhileLoop.h b/src/ir/values/WhileLoop.h deleted file mode 100644 index 0fc4cde3..00000000 --- a/src/ir/values/WhileLoop.h +++ /dev/null @@ -1,65 +0,0 @@ - -#include "../../ValueVisitor/Visitor.h" -#include "../../ast/syntax/nodes.h" -#include "../../ast/types/Type.h" -#include "../../common.h" -#include "Value.h" - -#include -#include - -#ifndef __SNOWBALL_WHILE_LOOP_VALUE_H_ -#define __SNOWBALL_WHILE_LOOP_VALUE_H_ - -namespace snowball { -namespace ir { - -/** - * @class WhileLoop - * @brief A class representing a while loop in the abstract syntax tree - * (AST). - * @tparam AcceptorExtend A template parameter - * indicating that the `WhileLoop` class is an acceptor that can accept - * visitors and extends the `Value` class. - * - * This class represents a while loop statement in the AST. It is a - * subclass of `AcceptorExtend` and extends the `Value` class. The - * `WhileLoop` class is used to represent loops in the AST, where the - * loop condition is checked before each iteration of the loop body. - */ -class WhileLoop : public AcceptorExtend { - // Instructions stored inside a block each iteration - std::shared_ptr insts; - // the expression to be evaluated each iteration - std::shared_ptr cond; - // Whether to execute the instruction before or after - // each iteration - bool doWhile = false; - // For loop condition (if it's a for loop) - std::shared_ptr forCond = nullptr; - - public: - explicit WhileLoop(std::shared_ptr cond, std::shared_ptr insts, bool doWhile = false) - : cond(cond), insts(insts), doWhile(doWhile) {}; - explicit WhileLoop(std::shared_ptr cond, std::shared_ptr insts, std::shared_ptr forCond) - : cond(cond), insts(insts), forCond(forCond) {}; - - /// @return body block instructions to execute - // if the condition is met each iteration - auto getBlock() const { return insts; } - /// @return the expression to be evaluated each iteration - auto getCondition() const { return cond; } - /// @return If the condition should be checked before or after - /// each iteration - auto isDoWhile() const { return doWhile; } - /// @return The for loop condition (if it's a for loop) - auto getForCond() const { return forCond; } - - // Set a visit handler for the generators - SN_GENERATOR_VISITS -}; - -} // namespace ir -} // namespace snowball - -#endif // __SNOWBALL_WHILE_LOOP_VALUE_H_ diff --git a/src/ir/values/all.h b/src/ir/values/all.h deleted file mode 100644 index 16158755..00000000 --- a/src/ir/values/all.h +++ /dev/null @@ -1,22 +0,0 @@ - -#include "Argument.h" -#include "Body.h" -#include "Call.h" -#include "EnumInit.h" -#include "Cast.h" -#include "Conditional.h" -#include "Constants.h" -#include "Dereference.h" -#include "Func.h" -#include "IndexExtract.h" -#include "ReferenceTo.h" -#include "Return.h" -#include "Throw.h" -#include "TryCatch.h" -#include "Value.h" -#include "ValueExtract.h" -#include "Variable.h" -#include "VariableDeclaration.h" -#include "WhileLoop.h" -#include "LoopFlow.h" -#include "Switch.h" diff --git a/src/lexer/lexer.cc b/src/lexer/lexer.cc deleted file mode 100644 index 6e7a8814..00000000 --- a/src/lexer/lexer.cc +++ /dev/null @@ -1,777 +0,0 @@ - -#include "lexer/lexer.h" - -#include "errors.h" -#include "lexer/tokens/token.h" -#include "utils/utils.h" - -#include -#include -#include -#include -#include -#include - -#define GET_CHAR(m_off) (((size_t) char_ptr + m_off >= codeSize) ? '\0' : code.at((size_t) char_ptr + m_off)) -#define EAT_CHAR(m_num) \ - { \ - char_ptr += m_num; \ - cur_col += m_num; \ - } -#define EAT_LINE() \ - { \ - char_ptr++; \ - cur_col = 1; \ - cur_line++; \ - } - -#define IS_NUM(c) (('0' <= c && c <= '9')) -#define IS_HEX_CHAR(c) (IS_NUM(c) || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')) -#define IS_TEXT(c) ((c == '_') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) - -namespace snowball { -Lexer::Lexer(const SourceInfo* p_source_info) : srcInfo(p_source_info), tokens({}) { } - -void Lexer::tokenize() { - tokens = {}; - const auto& code = srcInfo->getSource(); - auto codeSize = code.size(); - if (codeSize == 0) return; - std::string comments = ""; - // Iterate every character of the source code - // and tokenize that char. Tokenizing it will - // mean that respective Token for the current - // char will also be added to the Token array - while (char_ptr < (int) codeSize) { - switch (GET_CHAR(0)) { - case 0: handle_eof(); break; - // Space, new lines and tabs - case ' ': - case '\t': EAT_CHAR(1); break; - case '\n': EAT_LINE(); break; - case '/': { - std::string comment = ""; - if (GET_CHAR(1) == '/') { // comment - // Skip characters until we encounter _EOF or NEW_LINE - while (GET_CHAR(0) != '\n' && GET_CHAR(0) != 0) { - comment += GET_CHAR(0); - EAT_CHAR(1); - } - if (GET_CHAR(0) == '\n') { - EAT_LINE(); - } else if (GET_CHAR(0) == 0) { - handle_eof(); - } - } else if (GET_CHAR(1) == '*') { // multi line comment - comment += "/*"; - EAT_CHAR(2); - while (true) { - if (GET_CHAR(0) == '*' && GET_CHAR(1) == '/') { - comment += "*/"; - EAT_CHAR(2); - break; - } else if (GET_CHAR(0) == 0) { - lexer_error( - Error::UNEXPECTED_EOF, - "Found an unexpected EOF while parsing " - "a comment", - 1, { - .help = "It seems that a multiline " - "comment in " - "your code is not properly " - "closed. \n" - "Make sure to add the closing " - "symbol " - "\"*/\" at the end of the " - "comment to " - "\nproperly close it." - } - ); - } else if (GET_CHAR(0) == '\n') { - comment += '\n'; - EAT_LINE(); - } else { - comment += GET_CHAR(0); - EAT_CHAR(1); - } - } - } else { - if (GET_CHAR(1) == '=') - consume(TokenType::OP_DIVEQ, 2); - else - consume(TokenType::OP_DIV); - break; - } - comments = comment; - break; - } - // symbols - case ':': { - if (GET_CHAR(1) == ':') - consume(TokenType::SYM_COLCOL, 2); - else - consume(TokenType::SYM_COLLON); - break; - } - case ',': consume(TokenType::SYM_COMMA); break; - case ';': consume(TokenType::SYM_SEMI_COLLON); break; - case '#': consume(TokenType::SYM_HASH); break; - case '$': consume(TokenType::SYM_DOLLAR); break; - case '?': consume(TokenType::SYM_QUESTION); break; - case '@': consume(TokenType::SYM_AT); break; - // brackets - case '(': consume(TokenType::BRACKET_LPARENT); break; - case ')': consume(TokenType::BRACKET_RPARENT); break; - case '{': consume(TokenType::BRACKET_LCURLY); break; - case '}': consume(TokenType::BRACKET_RCURLY); break; - case '[': consume(TokenType::BRACKET_LSQUARED); break; - case ']': consume(TokenType::BRACKET_RSQUARED); break; - // op - case '=': { - if (GET_CHAR(1) == '=') - consume(TokenType::OP_EQEQ, 2); - else if (GET_CHAR(1) == '>') - consume(TokenType::OP_ARROW, 2); - else - consume(TokenType::OP_EQ); - break; - } - case '+': { - if (GET_CHAR(1) == '=') - consume(TokenType::OP_PLUSEQ, 2); - else - consume(TokenType::OP_PLUS); - break; - } - case '-': { - if (GET_CHAR(1) == '=') - consume(TokenType::OP_MINUSEQ, 2); - else - consume(TokenType::OP_MINUS); - break; - } - case '*': { - if (GET_CHAR(1) == '=') - consume(TokenType::OP_MULEQ, 2); - else - consume(TokenType::OP_MUL); - break; - } - case '\\': - lexer_error(Error::SYNTAX_ERROR, "invalid character '\\'.", 1, {.info = "This character is not recognized!"}); - break; - case '%': { - if (GET_CHAR(1) == '=') - consume(TokenType::OP_MOD_EQ, 2); - else - consume(TokenType::OP_MOD); - break; - } - case '<': { - if (GET_CHAR(1) == '=') - consume(TokenType::OP_LTEQ, 2); - else if (GET_CHAR(1) == '<') { - if (GET_CHAR(2) == '=') - consume(TokenType::OP_BIT_LSHIFT_EQ, 3); - else - consume(TokenType::OP_BIT_LSHIFT, 2); - } else - consume(TokenType::OP_LT); - break; - } - case '>': { - if (GET_CHAR(1) == '=') - consume(TokenType::OP_GTEQ, 2); - else if (GET_CHAR(1) == '>') { - if (GET_CHAR(2) == '=') - consume(TokenType::OP_BIT_RSHIFT_EQ, 3); - else - // TODO: (generics cant handle >) - // consume(TokenType::OP_BIT_RSHIFT, 2); - // ^^ - // actually parse ">>" at parser when we encounter an - // operator - { - consume(TokenType::OP_GT); - consume(TokenType::OP_GT); - } - } else - consume(TokenType::OP_GT); - break; - } - case '!': { - if (GET_CHAR(1) == '=') - consume(TokenType::OP_NOTEQ, 2); - else - consume(TokenType::OP_NOT); - break; - } - case '~': consume(TokenType::OP_BIT_NOT); break; - case '|': { - if (GET_CHAR(1) == '=') - consume(TokenType::OP_BIT_OR_EQ, 2); - else if (GET_CHAR(1) == '|') - consume(TokenType::OP_OR, 2); - else if (GET_CHAR(1) == '>' && GET_CHAR(2) == '>') - consume(TokenType::OP_BIT_RSHIFT, 3); - else - consume(TokenType::OP_BIT_OR); - break; - } - case '&': { - if (GET_CHAR(1) == '=') - consume(TokenType::OP_BIT_AND_EQ, 2); - else if (GET_CHAR(1) == '&') - consume(TokenType::OP_AND, 2); - else - consume(TokenType::OP_BIT_AND); - break; - } - case '^': { - if (GET_CHAR(1) == '=') - consume(TokenType::OP_BIT_XOR_EQ, 2); - else - consume(TokenType::OP_BIT_XOR); - break; - } - case '\'': { - EAT_CHAR(1); - std::string str; - while (GET_CHAR(0) != '\'') { - if (GET_CHAR(0) == '\\') { - char c = GET_CHAR(1); - switch (c) { - case 0: // TODO: show the start of string - // location - lexer_error( - Error::UNEXPECTED_EOF, - "Unexpected EOF while lexing a " - "string scape!", - 1, { - .info = "Coudnt find scape here!", - .help = "The string in your code " - "contains " - "an " - "incomplete escape " - "sequence. Make " - "sure to provide the " - "\nnecessary " - "escape character or " - "complete the " - "escape sequence before " - "the end\n " - "of " - "the string. For example, " - "you can " - "add " - "a backslash (\"\") " - "\nbefore the " - "closing quotation mark " - "(\") to\n " - "properly escape it." - } - ); - break; - case '\\': - str += '\\'; - EAT_CHAR(2); - break; - case '\'': - str += '\''; - EAT_CHAR(2); - break; - case 't': - str += '\t'; - EAT_CHAR(2); - break; - case 'n': - str += '\n'; - EAT_CHAR(2); - break; - case '0': - str += '\0'; - EAT_CHAR(2); - break; - case '"': - str += '"'; - EAT_CHAR(2); - break; - case 'r': - str += '\r'; - EAT_CHAR(2); - break; - case '\n': - EAT_CHAR(1); - EAT_LINE(); - break; - case 'x': { - EAT_CHAR(2); - std::string hex; - while (IS_HEX_CHAR(GET_CHAR(0))) { - hex += GET_CHAR(0); - EAT_CHAR(1); - } - if (hex.size() == 0) { - lexer_error(Error::SYNTAX_ERROR, "invalid hex character", 2); - } - str += (char) std::stoi(hex, nullptr, 16); - break; - } - default: lexer_error(Error::SYNTAX_ERROR, "invalid escape character", 2); - } - } else if (GET_CHAR(0) == 0) { - lexer_error( - Error::UNEXPECTED_EOF, - "Unexpected EOF while lexing character!", - 1, { - .info = "No ending of the string found!", - .help = "It appears that the character " - "declaration in " - "your code is incomplete. \nMake sure " - "to " - "provide a valid character between " - "the single " - "quotes (\'\'). Choose a\n valid " - "character " - "and close the declaration with a " - "single " - "quote (') to resolve this issue." - } - ); - break; - } else { - str += GET_CHAR(0); - if (GET_CHAR(0) == '\n') { - lexer_error(Error::SYNTAX_ERROR, "Characters can't contain new lines!"); - } else { - EAT_CHAR(1); - } - } - } - EAT_CHAR(1); - if (str.size() != 1) { lexer_error(Error::SYNTAX_ERROR, "Character values can only have a length of 1!"); } - Token tk = {}; - tk.type = TokenType::VALUE_CHAR; - tk.value = str; // method name may be builtin func - tk.col = cur_col - ((int) str.size() + (2 /* speech marks */)); - tk.line = cur_line; - tokens.emplace_back(tk); - break; - } - case '"': { - EAT_CHAR(1); - std::string str; - auto col = cur_col; - auto line = cur_line; - while (GET_CHAR(0) != '"') { - if (GET_CHAR(0) == '\\') { - char c = GET_CHAR(1); - switch (c) { - case 0: - lexer_error( - Error::UNEXPECTED_EOF, - "unexpected EOF while lexing a " - "string scape." - ); - break; - case '\\': - str += '\\'; - EAT_CHAR(2); - break; - case '\'': - str += '\''; - EAT_CHAR(2); - break; - case 't': - str += '\t'; - EAT_CHAR(2); - break; - case 'n': - str += '\n'; - EAT_CHAR(2); - break; - case '"': - str += '"'; - EAT_CHAR(2); - break; - case 'r': - str += '\r'; - EAT_CHAR(2); - break; - case 'e': - str += '\e'; - EAT_CHAR(2); - break; - case 'x': { - EAT_CHAR(2); - std::string hex; - while (IS_HEX_CHAR(GET_CHAR(0))) { - hex += GET_CHAR(0); - EAT_CHAR(1); - } - if (hex.size() == 0) { - lexer_error(Error::SYNTAX_ERROR, "invalid hex character", 2); - } - str += (char) std::stoi(hex, nullptr, 16); - break; - } - case '\n': - EAT_CHAR(1); - EAT_LINE(); - break; - default: lexer_error(Error::SYNTAX_ERROR, "invalid escape character", 2); - } - } else if (GET_CHAR(0) == 0) { - lexer_error( - Error::UNEXPECTED_EOF, - "Unexpected EOF while lexing character!", - 1, { - .info = "No ending of the string found!", - .help = "It appears that the character " - "declaration in " - "your code is incomplete. \nMake " - "sure to " - "provide a valid character " - "between the double " - "quotes (\"\"). \nChoose a valid " - "character " - "and close the declaration with a " - "double " - "quote \n(\") to resolve this " - "issue." - } - ); - break; - } else { - str += GET_CHAR(0); - if (GET_CHAR(0) == '\n') { - EAT_LINE(); - } else { - EAT_CHAR(1); - } - } - } - EAT_CHAR(1); - Token tk = {}; - tk.type = TokenType::VALUE_STRING; - tk.value = str; // method name may be builtin func - tk.col = col - 1; - tk.line = line; - tokens.emplace_back(tk); - break; - } - default: - // TODO: 1.2e3 => is a valid float number - // float value begins with '.' - if (GET_CHAR(0) == '.' && IS_NUM(GET_CHAR(1))) { - std::string float_str(1, '.'); - EAT_CHAR(1); - while (IS_NUM(GET_CHAR(0))) { - float_str += GET_CHAR(0); - EAT_CHAR(1); - } - double float_val = std::stod(float_str); - Token tk = {}; - tk.type = TokenType::VALUE_FLOAT; - tk.line = cur_line; - tk.col = cur_col - float_str.length(); - tk.value = float_val; - tokens.emplace_back(tk); - break; - } - // integer/float value - if (IS_NUM(GET_CHAR(0))) { - std::string num(1, GET_CHAR(0)); - enum _ReadMode { - INT, - FLOAT, - BIN, - HEX, - OCT - }; - _ReadMode mode = INT; - if (GET_CHAR(0) == '0') { - if (GET_CHAR(1) == 'b' || GET_CHAR(1) == 'B') mode = BIN; - if (GET_CHAR(1) == 'x' || GET_CHAR(1) == 'X') mode = HEX; - if (GET_CHAR(1) == 'o' || GET_CHAR(1) == 'O') mode = OCT; - } - bool isRange = false; - EAT_CHAR(1); - switch (mode) { - case INT: { - while (IS_NUM(GET_CHAR(0)) || GET_CHAR(0) == '.') { - if (GET_CHAR(0) == '.' && mode == FLOAT) { - mode = INT; - num.erase(num.size() - 1); - isRange = true; - break; // It must be a range, right? - } - if (GET_CHAR(0) == '.') mode = FLOAT; - num += GET_CHAR(0); - EAT_CHAR(1); - } - } break; - case BIN: { - num += GET_CHAR(0); - EAT_CHAR(1); // eat 'b'; - while (GET_CHAR(0) == '0' || GET_CHAR(0) == '1') { - num += GET_CHAR(0); - EAT_CHAR(1); - } - } break; - case HEX: { - num += GET_CHAR(0); - EAT_CHAR(1); // eat 'x'; - while (IS_HEX_CHAR(GET_CHAR(0))) { - num += GET_CHAR(0); - EAT_CHAR(1); - } - } break; - case OCT: { - num += GET_CHAR(0); - EAT_CHAR(1); // eat 'o'; - while (GET_CHAR(0) >= '0' && GET_CHAR(0) <= '7') { - num += GET_CHAR(0); - EAT_CHAR(1); - } - } break; - default: lexer_error(Error::BUG, FMT("Unreachable number mode \"%i\"", mode), num.size()); - } - bool appendDot = false; - if (num[num.size() - 1] == '.') { - num.erase(num.size() - 1); - mode = INT; - appendDot = true; - } - Token tk = {}; - tk.line = cur_line; - tk.col = cur_col - num.length(); - tk.value = num; - if (mode == FLOAT) { - tk.type = TokenType::VALUE_FLOAT; - } else { - tk.type = TokenType::VALUE_NUMBER; - } - std::string prefix; - if (GET_CHAR(0) == 'u' || GET_CHAR(0) == 'U') { - prefix += "u"; - EAT_CHAR(1); - } else if (GET_CHAR(0) == 'i' || GET_CHAR(0) == 'I') { - prefix += "i"; - EAT_CHAR(1); - } - if (GET_CHAR(0) == 'l' || GET_CHAR(0) == 'L') { - prefix += "l"; - EAT_CHAR(1); - } - tk.value = prefix + tk.value; - tokens.emplace_back(tk); - if (isRange) { // we add '..' if it's a range expr (1..5) - consume(TokenType::SYM_DOT); - consume(TokenType::SYM_DOT); - this->char_ptr -= 1; - } - if (appendDot) { - consume(TokenType::SYM_DOT); - this->char_ptr -= 1; - } - break; - } - // identifier - if (IS_TEXT(GET_CHAR(0))) { - std::string identifier(1, GET_CHAR(0)); - EAT_CHAR(1); - while (IS_TEXT(GET_CHAR(0)) || IS_NUM(GET_CHAR(0))) { - identifier += GET_CHAR(0); - EAT_CHAR(1); - } - Token tk = { - .type = TokenType::UNKNOWN, - .line = cur_line, - .col = cur_col - (int) identifier.size(), - .value = identifier - }; - if (identifier == _SNOWBALL_KEYWORD__NEW) { - tk.type = TokenType::KWORD_NEW; - } else if (identifier == _SNOWBALL_KEYWORD__THROW) { - tk.type = TokenType::KWORD_THROW; - } else if (identifier == _SNOWBALL_KEYWORD__IF) { - tk.type = TokenType::KWORD_IF; - } else if (identifier == _SNOWBALL_KEYWORD__VARIABLE) { - tk.type = TokenType::KWORD_VAR; - } else if (identifier == _SNOWBALL_KEYWORD__FOR) { - tk.type = TokenType::KWORD_FOR; - } else if (identifier == _SNOWBALL_KEYWORD__ENUM) { - tk.type = TokenType::KWORD_ENUM; - } else if (identifier == _SNOWBALL_KEYWORD__DECLTYPE) { - tk.type = TokenType::KWORD_DECLTYPE; - } else if (identifier == _SNOWBALL_KEYWORD__FUNCTION) { - tk.type = TokenType::KWORD_FUNC; - } else if (identifier == _SNOWBALL_KEYWORD__MACRO) { - tk.type = TokenType::KWORD_MACRO; - } else if (identifier == _SNOWBALL_KEYWORD__OPERATOR) { - tk.type = TokenType::KWORD_OPERATOR; - } else if (identifier == _SNOWBALL_KEYWORD__ELSE) { - tk.type = TokenType::KWORD_ELSE; - } else if (identifier == _SNOWBALL_KEYWORD__CLASS) { - tk.type = TokenType::KWORD_CLASS; - } else if (identifier == _SNOWBALL_KEYWORD__AS) { - tk.type = TokenType::KWORD_AS; - } else if (identifier == _SNOWBALL_KEYWORD__CONSTANT) { - tk.type = TokenType::KWORD_CONST; - } else if (identifier == _SNOWBALL_KEYWORD__WHILE) { - tk.type = TokenType::KWORD_WHILE; - } else if (identifier == _SNOWBALL_KEYWORD__BREAK) { - tk.type = TokenType::KWORD_BREAK; - } else if (identifier == _SNOWBALL_KEYWORD__EXTERN) { - tk.type = TokenType::KWORD_EXTERN; - } else if (identifier == _SNOWBALL_KEYWORD__SUPER) { - tk.type = TokenType::KWORD_SUPER; - } else if (identifier == _SNOWBALL_KEYWORD__CASE) { - tk.type = TokenType::KWORD_CASE; - } else if (identifier == _SNOWBALL_KEYWORD__SWITCH) { - tk.type = TokenType::KWORD_SWITCH; - } else if (identifier == _SNOWBALL_KEYWORD__STATIC) { - tk.type = TokenType::KWORD_STATIC; - } else if (identifier == _SNOWBALL_KEYWORD__IMPORT) { - tk.type = TokenType::KWORD_IMPORT; - } else if (identifier == _SNOWBALL_KEYWORD__UNSAFE) { - tk.type = TokenType::KWORD_UNSAFE; - } else if (identifier == _SNOWBALL_KEYWORD__CONSTEXPR) { - tk.type = TokenType::KWORD_CONSTEXPR; - } else if (identifier == _SNOWBALL_KEYWORD__NAMESPACE) { - tk.type = TokenType::KWORD_NAMESPACE; - } else if (identifier == _SNOWBALL_KEYWORD__STRUCT) { - tk.type = TokenType::KWORD_STRUCT; - } else if (identifier == _SNOWBALL_KEYWORD__TYPEDEF) { - tk.type = TokenType::KWORD_TYPEDEF; - } else if (identifier == _SNOWBALL_KEYWORD__MUTABLE) { - tk.type = TokenType::KWORD_MUTABLE; - } else if (identifier == _SNOWBALL_KEYWORD__DO) { - tk.type = TokenType::KWORD_DO; - } else if (identifier == _SNOWBALL_KEYWORD__PRIVATE) { - tk.type = TokenType::KWORD_PRIVATE; - } else if (identifier == _SNOWBALL_KEYWORD__PUBLIC) { - tk.type = TokenType::KWORD_PUBLIC; - } else if (identifier == _SNOWBALL_KEYWORD__VIRTUAL) { - tk.type = TokenType::KWORD_VIRTUAL; - } else if (identifier == _SNOWBALL_KEYWORD__OVERRIDE) { - tk.type = TokenType::KWORD_OVERRIDE; - } else if (identifier == _SNOWBALL_KEYWORD__RETURN) { - tk.type = TokenType::KWORD_RETURN; - } else if (identifier == _SNOWBALL_KEYWORD__DEFAULT) { - tk.type = TokenType::KWORD_DEFAULT; - } else if (identifier == _SNOWBALL_KEYWORD__CONTINUE) { - tk.type = TokenType::KWORD_CONTINUE; - } else if (identifier == _SNOWBALL_KEYWORD__TRY) { - tk.type = TokenType::KWORD_TRY; - } else if (identifier == _SNOWBALL_KEYWORD__CATCH) { - tk.type = TokenType::KWORD_CATCH; - } else if (identifier == _SNOWBALL_KEYWORD__INTER) { - tk.type = TokenType::KWORD_INTER; - } else if (identifier == _SNOWBALL_KEYWORD__EXTENDS) { - tk.type = TokenType::KWORD_EXTENDS; - } else if (identifier == _SNOWBALL_KEYWORD__IMPLS) { - tk.type = TokenType::KWORD_IMPLEMENTS; - } else if (identifier == _SNOWBALL_KEYWORD__TRUE || identifier == _SNOWBALL_KEYWORD__FALSE) { - tk.type = TokenType::VALUE_BOOL; - } else { - tk.type = TokenType::IDENTIFIER; - } - switch (tk.type) { - case TokenType::KWORD_FUNC: - case TokenType::KWORD_MACRO: - case TokenType::KWORD_CLASS: - case TokenType::KWORD_STRUCT: - case TokenType::KWORD_ENUM: - case TokenType::KWORD_NAMESPACE: - case TokenType::KWORD_INTER: - case TokenType::KWORD_VAR: - case TokenType::KWORD_CONST: - case TokenType::KWORD_TYPEDEF: - case TokenType::KWORD_OPERATOR: - tk.comment = comments; - comments = ""; - break; - // Modifiers that should be ignored - // so that the commen tis passed to the - // next token - case TokenType::KWORD_PUBLIC: - case TokenType::KWORD_PRIVATE: - case TokenType::KWORD_VIRTUAL: - case TokenType::KWORD_STATIC: - case TokenType::KWORD_EXTERN: - case TokenType::KWORD_UNSAFE: - case TokenType::KWORD_MUTABLE: - case TokenType::IDENTIFIER: // idk about this one - break; - default: comments = ""; - } - tokens.emplace_back(tk); - break; - } - if (GET_CHAR(0) == '.') { - consume(TokenType::SYM_DOT); - break; - } - auto c = utils::getUTF8FromIndex(code, char_ptr); - if (c == "🐒") { - lexer_error( - Error::SYNTAX_ERROR, - "Unexpected MONKE found!", - 1, - {.info = "🐒🐒🐒🐒🐒🐒", .note = "This is just an easter egg!"} - ); - } else { - lexer_error(Error::SYNTAX_ERROR, FMT("Unexpected character found '%s' while lexing.", c.c_str()), 1); - } - } - } - // For some reason, sometimes the tokenizer - // does not detect the end of the source code. - // that is why we add a Token with _EOF type to - // the Token array (for later use in the parser) - if (tokens.size() == 0 || (tokens.at(tokens.size() - 1).type != TokenType::_EOF)) { - // add "false" as a param for "p_consume" - // so that the lexer does not "consume" - handle_eof(false); - } -#if _SNOWBALL_LEXER_DEBUG - PRINT_LINE("Lexer's Tokens:") - PRINT_LINE(LINE_SEPARATOR) - int index = 0; - for (Token tk : tokens) { - DEBUG_LEXER("[%i]: %s (type %i)", index, tk.to_string().c_str(), tk.type) - index++; - } - PRINT_LINE(LINE_SEPARATOR) -#endif -} - -void Lexer::handle_eof(bool p_consume) { - // Declare a new Token - Token tk = {}; - // Fill al fields for the token - // as an EOF type. - tk.type = TokenType::_EOF; - tk.line = cur_line; - tk.col = cur_col; - // Add token to the list of tokens - tokens.push_back(tk); - if (p_consume) { EAT_CHAR(1); } -} - -void Lexer::consume(TokenType p_tk, int p_eat_size) { - Token tk = {}; - tk.type = p_tk; - tk.line = cur_line; - tk.col = cur_col; - tokens.push_back(tk); - EAT_CHAR(p_eat_size); -} - -void Lexer::lexer_error(Error m_error, std::string m_msg, int char_length, ErrorInfo info) { - DBGSourceInfo* dbg_info = new DBGSourceInfo(srcInfo, std::pair(cur_line, cur_col), char_length); - throw LexerError(m_error, std::string(m_msg), dbg_info, info); -} -} // namespace snowball diff --git a/src/lexer/lexer.h b/src/lexer/lexer.h deleted file mode 100644 index e4a37040..00000000 --- a/src/lexer/lexer.h +++ /dev/null @@ -1,53 +0,0 @@ - -#include "../SourceInfo.h" -#include "../errors.h" -#include "../utils/logger.h" -#include "tokens/token.h" - -#include - -#ifndef __SNOWBALL_LEXER_H_ -#define __SNOWBALL_LEXER_H_ - -namespace snowball { -/** - * @brief Tokenizer class - * - * The lexer transforms the source code into an - * array of `tokens` that can be used for later parsing. - * - * We use tokens because it allows us to parse more easily our - * privided source code. We dont need to worry about white spaces, - * new lines, tabs and overall, very specific situations that will - * create some bugs if they are not handled properly, creating a very - * bad parser. - * - * It also facilitates us because each token contains source information - * such as location and line numbers. - */ -class Lexer { - public: - Lexer(const SourceInfo* p_source_info); - - void tokenize(); - std::vector tokens = {}; - - ~Lexer() {}; - - private: - // methods - void handle_eof(bool p_consume = true); - void consume(TokenType p_tk, int p_eat_size = 1); - void lexer_error(Error m_error, std::string m_msg, int char_length = 1, ErrorInfo info = {}); - - // vars - const SourceInfo* srcInfo; - - int cur_line = 1; - int cur_col = 1; - - int char_ptr = 0; -}; -} // namespace snowball - -#endif // __SNOWBALL_LEXER_H_ diff --git a/src/lexer/tokens/token.h b/src/lexer/tokens/token.h deleted file mode 100644 index b8cc1514..00000000 --- a/src/lexer/tokens/token.h +++ /dev/null @@ -1,335 +0,0 @@ - -#include "constants.h" -#include "utils/logger.h" - -#include -#include -#include - -#ifndef __SNOWBALL_TOKEN_H_ -#define __SNOWBALL_TOKEN_H_ - -namespace snowball { -enum class TokenType { - /* - | Indentifiers - |--------------- - | An identifier is lexical token - | (also called symbol, but not to - | be confused with the symbol primitive - | data type) that names the language's - | entities. - | - | Some of the kinds of entities an identifier - | might denote include variables, data types, - | labels, subroutines, and modules. - | - | Snowball accepts the following identifiers: - | * a - | * _thisIsValid - | * Hello_World - | * foo123 - | * BYE_BYE - */ - IDENTIFIER, - - // Literal values - VALUE_NUMBER, - VALUE_FLOAT, - VALUE_BOOL, - VALUE_STRING, - VALUE_CHAR, - - /* - | Symbols - |------------- - | This are the single - | characters tokens - */ - SYM_AT, // Symbol: @ - SYM_DOT, // Symbol: . - SYM_HASH, // Symbol: # - SYM_COMMA, // Symbol: , - SYM_COLLON, // Symbol: : - SYM_COLCOL, // Symbol: :: - SYM_DOLLAR, // Symbol: $ - SYM_QUESTION, // Symbol: ? - SYM_SEMI_COLLON, // Symbol: ; - - // |- BRACKETS -| - BRACKET_LCURLY, // Symbol: { - BRACKET_RCURLY, // Symbol: } - BRACKET_LPARENT, // Symbol: ( - BRACKET_RPARENT, // Symbol: ) - BRACKET_RSQUARED, // Symbol: [ - BRACKET_LSQUARED, // Symbol: ] - - /* - | Mathematical symbols - |---------------------- - | This tokens are used to - | do mathematical operations - | such as add and multiply - | - | note that it can also work - | with other types such as - | string concationation and - | calling the overiding function - | in a class. - */ - // TODO: Exponential - - // Single characters - OP_MUL, // Symbol: * - OP_MOD, // Symbol: % - OP_DIV, // Symbol: / - OP_PLUS, // Symbol: + - OP_MINUS, // Symbol: - - - // Double characters - OP_MULEQ, // Symbol: *= - OP_DIVEQ, // Symbol: /= - OP_MOD_EQ, // Symbol: %= - OP_PLUSEQ, // Symbol: += - OP_MINUSEQ, // Symbol: -= - - /* - | Comparasion tokens - |-------------------- - | `Comparasion tokens` are - | tokens used to compare 2 - | values. It will return - | true if the statement matches - */ - - // Single character tokens - OP_GT, // Symbol: > - OP_LT, // Symbol: < - - // Double character tokens - OP_ARROW, // Symbol: => - OP_EQEQ, // Symbol: == - OP_GTEQ, // Symbol: >= - OP_LTEQ, // Symbol: <= - OP_NOTEQ, // Symbol: != - - /* - | Asignment tokens - |------------------ - | This tokens are used - | to set a value to a - | variable. - */ - - // Single character tokens - OP_EQ, // Symbol: = - OP_NOT, // Symbol: ! - - // Double character tokens - OP_AND, // Symbol: && - OP_OR, // Symbol: || - - // Bitwise operations - OP_BIT_NOT, // Symbol: ~ - OP_BIT_OR, // Symbol: | - OP_BIT_AND, // Symbol: & - OP_BIT_XOR, // Symbol: ^ - - OP_BIT_OR_EQ, // Symbol: |= - OP_BIT_RSHIFT, // Symbol: |>> - OP_BIT_LSHIFT, // Symbol: << - OP_BIT_AND_EQ, // Symbol: &= - OP_BIT_XOR_EQ, // Symbol: ^= - OP_BIT_RSHIFT_EQ, // Symbol: >>= - OP_BIT_LSHIFT_EQ, // Symbol: <<= - - /* - | Keywords - |----------------------- - | Keywords are predefined, - | reserved words used that have - | special meanings to the - | interpreter. - */ - KWORD__START__POINT, // All keywords must be grater than this - KWORD_IF, // Symbol: if - KWORD_VAR, // Symbol: let - KWORD_NEW, // Symbol: new - KWORD_THROW, // Symbol: raise - KWORD_FOR, // Symbol: for - KWORD_ENUM, // Symbol: enum - KWORD_FUNC, // Symbol: fn - KWORD_OPERATOR, // Symbol: operator - KWORD_MACRO, // Symbol: macro - KWORD_ELSE, // Symbol: else - KWORD_BREAK, // Symbol: break - KWORD_CONST, // Symbol: const - KWORD_SUPER, // Symbol: super - KWORD_WHILE, // Symbol: while - KWORD_EXTERN, // Synbol: extern - KWORD_VIRTUAL, // Synbol: virtual - KWORD_OVERRIDE, // Synbol: override - KWORD_CLASS, // Symbol: class - KWORD_AS, // Symbol: as - KWORD_IMPORT, // Symbol: use - KWORD_UNSAFE, // Symbol: unsafe - KWORD_CONSTEXPR, // Symbol: constexpr - KWORD_TYPEDEF, // Symbol: type - KWORD_MUTABLE, // Symbol: mut - KWORD_DO, // Symbol: do - KWORD_NAMESPACE, // Symbol: namespace - KWORD_STRUCT, // Symbol: struct - KWORD_PUBLIC, // Symbol: pub - KWORD_CASE, // Symbol: case - KWORD_SWITCH, // Symbol: switch - KWORD_STATIC, // Symbol: static - KWORD_RETURN, // Symbol: return - KWORD_PRIVATE, // Symbol: priv - KWORD_DECLTYPE, // Symbol: decltype - KWORD_DEFAULT, // Symbol: default - KWORD_TRY, // Symbol: try - KWORD_CATCH, // Symbol: catch - KWORD_CONTINUE, // Symbol: continue - KWORD_INTER, // Symbol: interface - KWORD_EXTENDS, // Symbol: extends - KWORD_IMPLEMENTS, // Symbol: implements - KWORD__ENDING__POINT, // All keywords must be less than this - - /* - | Other - |----------- - | This are not specially tokens. - */ - _EOF, // End of file. This already exists in - UNKNOWN, // Other -}; - -struct Token { - TokenType type = TokenType::UNKNOWN; - int line = 0, col = 0; - - std::string value; - std::string comment = ""; - - std::string getComment() const { return comment; } - - std::string to_string() const { - switch (type) { - // Symbols - case TokenType::SYM_AT: return "@"; - case TokenType::SYM_DOT: return "."; - case TokenType::SYM_HASH: return "#"; - case TokenType::SYM_COMMA: return ","; - case TokenType::SYM_COLLON: return ":"; - case TokenType::SYM_DOLLAR: return "$"; - case TokenType::SYM_QUESTION: return "?"; - case TokenType::SYM_SEMI_COLLON: return ";"; - case TokenType::SYM_COLCOL: return "::"; - // Brackets - case TokenType::BRACKET_LCURLY: return "{"; - case TokenType::BRACKET_RCURLY: return "}"; - case TokenType::BRACKET_LPARENT: return "("; - case TokenType::BRACKET_RPARENT: return ")"; - case TokenType::BRACKET_LSQUARED: return "["; - case TokenType::BRACKET_RSQUARED: return "]"; - // Equiality - case TokenType::OP_GT: return ">"; - case TokenType::OP_LT: return "<"; - case TokenType::OP_GTEQ: return ">="; - case TokenType::OP_EQEQ: return "=="; - case TokenType::OP_LTEQ: return "<="; - case TokenType::OP_NOTEQ: return "!="; - case TokenType::OP_ARROW: return "=>"; - // Mathematical symbols - case TokenType::OP_MOD: return "%"; - case TokenType::OP_DIV: return "/"; - case TokenType::OP_MUL: return "*"; - case TokenType::OP_PLUS: return "+"; - case TokenType::OP_MINUS: return "-"; - case TokenType::OP_MULEQ: return "*="; - case TokenType::OP_DIVEQ: return "/="; - case TokenType::OP_PLUSEQ: return "+="; - case TokenType::OP_MOD_EQ: return "%="; - case TokenType::OP_MINUSEQ: return "-="; - // Asignment - case TokenType::OP_EQ: return "="; - case TokenType::OP_OR: return "||"; - case TokenType::OP_AND: return "&&"; - case TokenType::OP_NOT: return "!"; - // Bitwise operations - case TokenType::OP_BIT_OR: return "|"; - case TokenType::OP_BIT_NOT: return "~"; - case TokenType::OP_BIT_AND: return "&"; - case TokenType::OP_BIT_XOR: return "^"; - case TokenType::OP_BIT_OR_EQ: return "|="; - case TokenType::OP_BIT_LSHIFT: return "<<"; - case TokenType::OP_BIT_RSHIFT: return "|>>"; - case TokenType::OP_BIT_AND_EQ: return "&="; - case TokenType::OP_BIT_XOR_EQ: return "^="; - case TokenType::OP_BIT_LSHIFT_EQ: return "<<="; - case TokenType::OP_BIT_RSHIFT_EQ: return ">>="; - // Identifiers - case TokenType::IDENTIFIER: return value; - // Keywods - case TokenType::KWORD_PUBLIC: return _SNOWBALL_KEYWORD__PUBLIC; - case TokenType::KWORD_VIRTUAL: return _SNOWBALL_KEYWORD__VIRTUAL; - case TokenType::KWORD_OVERRIDE: return _SNOWBALL_KEYWORD__OVERRIDE; - case TokenType::KWORD_PRIVATE: return _SNOWBALL_KEYWORD__PRIVATE; - case TokenType::KWORD_IMPORT: return _SNOWBALL_KEYWORD__IMPORT; - case TokenType::KWORD_UNSAFE: return _SNOWBALL_KEYWORD__UNSAFE; - case TokenType::KWORD_CONSTEXPR: return _SNOWBALL_KEYWORD__CONSTEXPR; - case TokenType::KWORD_NAMESPACE: return _SNOWBALL_KEYWORD__NAMESPACE; - case TokenType::KWORD_STRUCT: return _SNOWBALL_KEYWORD__STRUCT; - case TokenType::KWORD_TYPEDEF: return _SNOWBALL_KEYWORD__TYPEDEF; - case TokenType::KWORD_MUTABLE: return _SNOWBALL_KEYWORD__MUTABLE; - case TokenType::KWORD_DO: return _SNOWBALL_KEYWORD__DO; - case TokenType::KWORD_CLASS: return _SNOWBALL_KEYWORD__CLASS; - case TokenType::KWORD_AS: return _SNOWBALL_KEYWORD__AS; - case TokenType::KWORD_ENUM: return _SNOWBALL_KEYWORD__ENUM; - case TokenType::KWORD_FUNC: return _SNOWBALL_KEYWORD__FUNCTION; - case TokenType::KWORD_MACRO: return _SNOWBALL_KEYWORD__MACRO; - case TokenType::KWORD_OPERATOR: return _SNOWBALL_KEYWORD__OPERATOR; - case TokenType::KWORD_VAR: return _SNOWBALL_KEYWORD__VARIABLE; - case TokenType::KWORD_CONST: return _SNOWBALL_KEYWORD__CONSTANT; - case TokenType::KWORD_IF: return _SNOWBALL_KEYWORD__IF; - case TokenType::KWORD_ELSE: return _SNOWBALL_KEYWORD__ELSE; - case TokenType::KWORD_WHILE: return _SNOWBALL_KEYWORD__WHILE; - case TokenType::KWORD_FOR: return _SNOWBALL_KEYWORD__FOR; - case TokenType::KWORD_CASE: return _SNOWBALL_KEYWORD__CASE; - case TokenType::KWORD_SWITCH: return _SNOWBALL_KEYWORD__SWITCH; - case TokenType::KWORD_DEFAULT: return _SNOWBALL_KEYWORD__DEFAULT; - case TokenType::KWORD_BREAK: return _SNOWBALL_KEYWORD__BREAK; - case TokenType::KWORD_CONTINUE: return _SNOWBALL_KEYWORD__CONTINUE; - case TokenType::KWORD_STATIC: return _SNOWBALL_KEYWORD__STATIC; - case TokenType::KWORD_SUPER: return _SNOWBALL_KEYWORD__SUPER; - case TokenType::KWORD_RETURN: return _SNOWBALL_KEYWORD__RETURN; - case TokenType::KWORD_DECLTYPE: return _SNOWBALL_KEYWORD__DECLTYPE; - case TokenType::KWORD_EXTERN: return _SNOWBALL_KEYWORD__EXTERN; - case TokenType::KWORD_NEW: return _SNOWBALL_KEYWORD__NEW; - case TokenType::KWORD_THROW: return _SNOWBALL_KEYWORD__THROW; - case TokenType::KWORD_TRY: return _SNOWBALL_KEYWORD__TRY; - case TokenType::KWORD_INTER: return _SNOWBALL_KEYWORD__INTER; - case TokenType::KWORD_EXTENDS: return _SNOWBALL_KEYWORD__EXTENDS; - case TokenType::KWORD_IMPLEMENTS: return _SNOWBALL_KEYWORD__IMPLS; - case TokenType::KWORD_CATCH: - return _SNOWBALL_KEYWORD__CATCH; - // Literal values - case TokenType::VALUE_NUMBER: - case TokenType::VALUE_FLOAT: - case TokenType::VALUE_BOOL: return value; - case TokenType::VALUE_STRING: return std::string("\"") + value + "\""; - case TokenType::VALUE_CHAR: return FMT("'%s'", value.c_str()); - // Other - case TokenType::UNKNOWN: return ""; - case TokenType::_EOF: return ""; - default: return ""; - } - // TODO: throw error: missed enum in switch case - } - - std::pair get_pos() const { return std::pair(std::make_pair(line, col)); } - uint32_t get_width() const { return (uint32_t) to_string().size(); } -}; -} // namespace snowball - -#endif // __SNOWBALL_TOKEN_H_ diff --git a/src/os/Driver.h b/src/os/Driver.h deleted file mode 100644 index 57ec0f4a..00000000 --- a/src/os/Driver.h +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include - -#ifndef __SNOWBALL_OS_DRIVER_H_ -#define __SNOWBALL_OS_DRIVER_H_ -#include "../../app/cli.h" - -namespace snowball { -namespace os { -class Driver { - public: - /** - * @brief It executes the given command. - * @param args The command to execute. - * @return The exit code of the command. - */ - static int run(std::vector args); - /** - * @brief It returns the output filename of the given input filename. - * @param input The input filename. - * @param type output type - * @return The output filename. - */ - static std::string getOutputFilename(std::string input, app::Options::EmitType type, bool isStatic = false); -}; -} // namespace os -} // namespace snowball - -#endif // __SNOWBALL_OS_DRIVER_H_ \ No newline at end of file diff --git a/src/os/Driver/getOutputFilename.cc b/src/os/Driver/getOutputFilename.cc deleted file mode 100644 index 08c16d2f..00000000 --- a/src/os/Driver/getOutputFilename.cc +++ /dev/null @@ -1,55 +0,0 @@ - -#include "../Driver.h" - -namespace snowball { -namespace os { -std::string Driver::getOutputFilename(std::string input, app::Options::EmitType type, bool isStatic) { -#ifdef __APPLE__ - std::string output = input; - switch (type) { - case app::Options::EmitType::EXECUTABLE: break; - case app::Options::EmitType::OBJECT: - if (isStatic) - output += ".a"; - else - output += ".dylib"; - break; - case app::Options::EmitType::LLVM_IR: output += ".ll"; break; - case app::Options::EmitType::ASSEMBLY: output += ".s"; break; - case app::Options::EmitType::SNOWBALL_IR: output += ".sir"; break; - } -#elif __linux__ - std::string output = input; - switch (type) { - case app::Options::EmitType::EXECUTABLE: break; - case app::Options::EmitType::OBJECT: - if (isStatic) - output += ".a"; - else - output += ".so"; - break; - case app::Options::EmitType::LLVM_IR: output += ".ll"; break; - case app::Options::EmitType::ASSEMBLY: output += ".s"; break; - case app::Options::EmitType::SNOWBALL_IR: output += ".sir"; break; - } -#elif _WIN32 - std::string output = input; - switch (type) { - case app::Options::EmitType::EXECUTABLE: output += ".exe"; break; - case app::Options::EmitType::OBJECT: - if (isStatic) - output += ".a"; - else - output += ".dll"; - break; - case app::Options::EmitType::LLVM_IR: output += ".ll"; break; - case app::Options::EmitType::ASSEMBLY: output += ".s"; break; - case app::Options::EmitType::SNOWBALL_IR: output += ".sir"; break; - } -#else -#error "Unsupported platform" -#endif - return output; -} -} // namespace os -} // namespace snowball diff --git a/src/os/Driver/run.cc b/src/os/Driver/run.cc deleted file mode 100644 index ce27006b..00000000 --- a/src/os/Driver/run.cc +++ /dev/null @@ -1,15 +0,0 @@ - -#include "../../constants.h" -#include "../../utils/utils.h" -#include "../Driver.h" - -namespace snowball { -namespace os { -int Driver::run(std::vector args) { - std::string command = utils::join(args.begin(), args.end(), " "); - DEBUG_CODEGEN("Running command: %s", command.c_str()); - int status = std::system(command.c_str()); - return status; -} -} // namespace os -} // namespace snowball diff --git a/src/parser/Parser.cc b/src/parser/Parser.cc deleted file mode 100644 index 9f6b93c6..00000000 --- a/src/parser/Parser.cc +++ /dev/null @@ -1,47 +0,0 @@ - -#include "./Parser.h" - -#include "../lexer/tokens/token.h" - -namespace snowball { -namespace parser { - -Parser::Parser(std::vector p_tokens, const SourceInfo* p_source_info, bool p_allow_comments) - : m_tokens(p_tokens), m_source_info(p_source_info), m_allow_comments(p_allow_comments) { - m_current = m_tokens.at(m_tok_index); -} - -std::vector Parser::parse() { return parseGlobal(); } - -Token Parser::next(int p_offset) { - try { - m_tok_index += (p_offset + 1); - m_current = m_tokens.at(m_tok_index); - return m_current; - } catch (std::out_of_range& _) { createError("Index error"); } - return {}; -} - -Token Parser::prev(int p_offset, bool p_safe) { - try { - m_tok_index -= (p_offset + 1); - m_current = m_tokens.at(m_tok_index); - return m_current; - } catch (std::out_of_range& _) { - if (!p_safe) createError("Index error"); - } - return {}; -} - -Token Parser::peek(int p_offset, bool p_safe) { - Token tmp = {.type = TokenType::_EOF, . value = ""}; - if ((m_tok_index + 1) + p_offset < 0 || (m_tok_index + 1) + p_offset >= (int) m_tokens.size()) { - if (p_safe) - return tmp; - else - createError("Parser::peek() index out of bounds"); - } - return m_tokens.at((m_tok_index + 1) + p_offset); -} -} // namespace parser -} // namespace snowball diff --git a/src/parser/Parser.h b/src/parser/Parser.h deleted file mode 100644 index ef3a688f..00000000 --- a/src/parser/Parser.h +++ /dev/null @@ -1,387 +0,0 @@ - -#include "../ast/syntax/nodes.h" -#include "../common.h" -#include "../errors.h" -#include "../lexer/tokens/token.h" -#include "../sourceInfo/DBGSourceInfo.h" - -#ifndef __SNOWBALL_PARSER_H_ -#define __SNOWBALL_PARSER_H_ - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wcomment" - -namespace snowball { -namespace parser { - -/** - * The parser performs syntactic analysis. - * - * Syntactic analysis is the process of analyzing a string of symbols, - * conforming to the rules of a formal grammar. - * - * This parser will generate an AST for later use to generate - * the llvm IR. - */ -class Parser { - int m_tok_index = 0; - Token m_current; - std::vector m_tokens; - - const SourceInfo* m_source_info; - Syntax::Statement::DefinedTypeDef* m_current_class = nullptr; - - bool m_inside_loop = false; - bool m_allow_comments = false; - - public: - Parser(std::vector p_tokens, const SourceInfo* p_source_info, bool p_allow_comments = false); - ~Parser() noexcept = default; - - private: - /// @brief Utility function to throw errors - template - [[nodiscard]] auto - createError(std::pair location, std::string message, ErrorInfo info = {}, Args&&... args) const { - auto dbg_info = new DBGSourceInfo(m_source_info, location, std::forward(args)...); - throw ParserError(E, message, dbg_info, info); - } - - template - [[nodiscard]] auto createError(const std::string msg, ErrorInfo info = {}) const { - auto pos = std::pair(m_current.line, m_current.col); - createError(pos, msg, info, m_current.to_string().size()); - } - - public: - using NodeVec = std::vector; - /// @brief Parse from the lexer tree - /// @return AST containing parsed node - NodeVec parse(); - - private: - // Utility functions for parsing - - /// Check if the current token is a certain token type - template - bool is() const { - return m_current.type == Ty; - } - // Check if a token type is a certain type - template - bool is(Token p_tok) const { - return p_tok.type == Ty; - } - // Comparison between 2 token types - template - bool is(TokenType p_ty) const { - return p_ty == Ty; - } - - // Check if a token mactches any of 2 types - template - bool is(Token p_tok) const { - return p_tok.type == Ty || p_tok.type == Ty2; - } - - /** - * Throws an error if the current token does not - * match. If it does, just go to the next token. - * - * @param expectation string expectation - * @return next token - */ - template - Token consume(std::string expectation) { - assert_tok(expectation); - return next(); - } - - /** - * @brief It checks if the current token is viable - * for parsing a type. - */ - bool isTypeValid() const { - return is() || is() || is() || - is() || is() || is() - || is(); - } - - /** - * @brief Throws an error if the current token does - * not match the @fn isTypeValid standard - */ - void throwIfNotType() const { - if (!isTypeValid()) { - createError( - FMT("Expected a valid type declaration but found '%s' " - "instead", - m_current.to_string().c_str()), - {.info = "Types cant start like this"} - ); - } - } - - /** - * This function throws an error if - * the current token does not match - * with the given type - * - * @param expectation string expectation - * @return given token - */ - template - Token assert_tok(std::string expectation) { - if (!is()) { - createError( - FMT("Expected %s but got '%s'", - expectation.c_str(), - (is(m_current) ? "an unexpected EOF" : m_current.to_string()).c_str()) - ); - } - return m_current; - } - - // Increment @var "m_tok_index" and - // return the current token - Token next(int p_offset = 0); - // Increment @var "m_tok_index" (+ offset) and - // return the respective token for that index. - Token peek(int p_offset = 0, bool p_safe = false); - // Decrement @var "m_tok_index" and - // return the current token - Token prev(int p_offset = 0, bool p_safe = false); - /** - * Joins a list of expressions into a single expression tree that - * follows the order of operations defined by BIDMAS (Brackets, - * Indices, Division, Multiplication, Addition, Subtraction). - * - * @param exprs A vector of pointers to Syntax::Expression::Base - * objects to be joined and ordered. - * @return A pointer to a new Syntax::Expression::Base object - * representing the expression tree. - * - * @example - * - Input: {NUMBER, PLUS_OPERATOR, NUMBER} - * - Output: OperatorExpr(l: NUMBER, r: NUMBER, op: PLUS_OPERATOR) - */ - Syntax::Expression::Base* buildOperatorTree(std::vector& exprs); - - private: - // Parsing functions - - /** - * @brief Utility method to parse a list of expressions - * acting as a global scope. - */ - NodeVec parseGlobal(TokenType terminator = TokenType::_EOF); - /** - * visibility ::= pub | priv - * funcname ::= identifier - * - * funcdef ::= [decorators] [extern] [visibility] "fn" - * funcname [generic_expr] "(" [parameter_list] ")" type "{" block - * "}" - * - * arrowfn ::= [decorators] "fn" funcname "(" - * [parameter_list] ")" type "=>" stmt - */ - Syntax::Statement::FunctionDef* - parseFunction(bool isConstructor = false, bool isOperator = false, bool isLambda = false, bool allowDecl = false); - /** - * params ::= "<" [param_args] ">" - * param_args ::= identifier ["=" default_type] - */ - std::vector parseGenericParams(); - /** - * generics_expr ::= "<" [type] ["," [type]...] ">" - */ - std::vector parseGenericExpr(); - /** - * type ::= identifier [generics_expr] - */ - Syntax::Expression::TypeRef* parseType(); - /** - * variable ::= "let" ["mut"] identifier[: [type]] = [expr] - * - * @example - * let a = "hello" - * let b: i32 = 2.4 - */ - Syntax::Statement::VariableDecl* parseVariable(); - /** - * block ::= "{" [body] "}" - * body ::= [stmt] | [expr] - */ - Syntax::Block* parseBlock(std::vector termination = {TokenType::BRACKET_RCURLY}); - /** - * return stmt ::= "return" [stmt] - */ - Syntax::Statement::Return* parseReturn(); - /** - * while stmt ::= "while" [stmt] [block] - */ - Syntax::Statement::WhileLoop* parseWhile(); - /** - * conditional ::= "if" [expr] [block] - * | "if" [expr]: [expr] - * | "if" "constexpr" - */ - Syntax::Statement::Base* parseConditional(); - /** - * visibility ::= pub | priv - * class_name ::= identifier - * class_inherit ::= "extends" [type] - * - * operator_decl ::= "operator" [op | "bool"] [function_like] - * constructor ::= [class_name == actual class name] - * [function_like] destructor ::= "~" [class_name == actual - * class name] [function_like] - * - * class_decls ::= [visibility] ":" - * | [function_declaration] ";" - * | [variable_declaration] ";" - * | [operator_decl] ";" - * | [constructor] ";" - * | [destructor] ";" - * class_body ::= "{" [class_decls] "}" - * - * class ::= [visibility] "class" [class_name] - * [class_inherit] [class_body] - */ - Syntax::Statement::DefinedTypeDef* parseClass(); - /** - * macro ::= "macro" ["!"] "(" [args] ")" "{" [body] "}" - * args ::= [identifier] "," ... - * body ::= [stmt] ... - */ - Syntax::Macro* parseMacro(); - /** - * function_call ::= [expr] "(" [args] ")" - * arguments ::= [[expr] "," ...] - * - * @param callee expression being called - */ - Syntax::Expression::FunctionCall* parseFunctionCall( - Syntax::Expression::Base* callee, - TokenType terminator = TokenType::BRACKET_RPARENT, - std::string terminatorString = ")" - ); - /** - * docstring ::= "/*" [string] "*\/" - */ - Syntax::Comment* parseDocstring(std::string content); - /** - * loop_control ::= "break" | "continue" - */ - Syntax::Statement::LoopFlow* parseLoopControl(); - /** - * function_call ::= [expr] "(" [args] ")" - * arguments ::= [[expr] "," ...] - * - * @param callee expression being called - */ - Syntax::Statement::ImportStmt* parseImportStatement(); - /** - * identifier ::= [A-Za-z0-9_] [?genericss expr] - * - * @return Syntax::Expression::Identifier* - */ - Syntax::Expression::Identifier* parseIdentifier(bool isKnownType = false, bool allowGenerics = true); - /** - * expr ::= [constant_value] | - * [function_call] | - * [index_node] | - * [new_instance] - * new_instance ::= "new" [type_ref][call] - * - * @param allowAssign Whether or not allow the assign operator. - */ - Syntax::Expression::Base* parseExpr(bool allowAssign = true); - /** - * alias ::= "type" = ; - */ - Syntax::Statement::TypeAlias* parseTypeAlias(); - /** - * clause ::= ... ":" [expressions] - * expressions ::= [expr ( "+" ...)] - * expr ::= - */ - Syntax::Expression::WhereClause* parseWhereClause(); - /** - * namespace ::= "namespace" "{" [body] "}" - */ - Syntax::Statement::Namespace* parseNamespace(); - /** - * struct ::= "struct" [generic_params] - * "{" [body] "}" [";"] - * body ::= [[identifier] ":" [expr] ","] ... - */ - Syntax::Statement::DefinedTypeDef* parseStructure(); - /** - * throw ::= "throw" [expr] ";" - */ - Syntax::Statement::Raise* parseThrow(); - /** - * block_or_expr ::= [block] | [stmt] - */ - Syntax::Block* parseBlockOrStmt(); - /** - * try ::= "try" "{" [block] "}" - * catch ::= "catch" "(" [identifier] ":" [type] ")" "{" [block] "}" - */ - Syntax::Statement::TryCatch* parseTryCatch(); - /** - * for ::= "for" [expr] ":" [expr] "{" [block] "}" - * @note It can Return Statement::ForLoop or Statement::Block (while loop for c-styled loops) - */ - Syntax::Node* parseForLoop(); - /** - * constant ::= "const" ":" "=" [expr] ";" - */ - Syntax::Statement::VariableDecl* parseConstant(); - /** - * enum ::= "enum" "{" [body] "}" - * body ::= [[identifier] "(" [types] ")" ","] ... - */ - Syntax::Statement::EnumTypeDef* parseEnum(); - /** - * case ::= "case" [expr] ":" [block] - */ - Syntax::Statement::Switch* parseSwitch(); - /// @brief Parses a statement - /// @return a statement - Syntax::Node* parseStatement(Token pk); - /** - * @brief Parses a list of attributes - */ - std::unordered_map> parseAttributes( - bool forConstexpr = false); - /** - * @brief Verifies the attributes list - * @param attributes attributes list - * @param parseFn function to parse the attribute - */ - std::unordered_map> verifyAttributes( - std::function parseFn, - std::unordered_map>& attrs - ); - std::unordered_map> verifyAttributes( - std::function parseFn - ); - /** - * @brief Assert that attributes are not accepted in the current context - */ - void assertNoAttributes(std::string context); - - private: - /// @brief Attributes list - std::unordered_map> m_attributes; -}; - -#pragma clang diagnostic pop - -} // namespace parser -} // namespace snowball - -#endif // __SNOWBALL_PARSER_H_ diff --git a/src/parser/buildOperatorTree.cc b/src/parser/buildOperatorTree.cc deleted file mode 100644 index 944e5058..00000000 --- a/src/parser/buildOperatorTree.cc +++ /dev/null @@ -1,158 +0,0 @@ - -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "../services/OperatorService.h" -#include "../utils/utils.h" -#include "./Parser.h" - -#include - -namespace snowball::parser { - -Syntax::Expression::Base* Parser::buildOperatorTree(std::vector& exprs) { - assert(exprs.size() > 0); - while (exprs.size() > 1) { - int next_op = -1; - int min_precedence = 0xFFFFF; - bool unary = false; - for (int i = 0; i < (int) exprs.size(); i++) { - auto expression = utils::cast(exprs[i]); - if (!expression || !expression->isOperator) { continue; } - int precedence = -1; - switch (expression->op_type) { - // https://en.m.wikipedia.org/wiki/Order_of_operations#Programming_languages - case Syntax::Expression::BinaryOp::OpType::NOT: - case Syntax::Expression::BinaryOp::OpType::BIT_NOT: - case Syntax::Expression::BinaryOp::OpType::UPLUS: - case Syntax::Expression::BinaryOp::OpType::REFERENCE: - case Syntax::Expression::BinaryOp::OpType::DEREFERENCE: - case Syntax::Expression::BinaryOp::OpType::UMINUS: { - precedence = 0; - break; - } - case Syntax::Expression::BinaryOp::OpType::MUL: - case Syntax::Expression::BinaryOp::OpType::DIV: - case Syntax::Expression::BinaryOp::OpType::MOD: { - precedence = 1; - break; - } - case Syntax::Expression::BinaryOp::OpType::PLUS: - case Syntax::Expression::BinaryOp::OpType::MINUS: { - precedence = 2; - break; - } - case Syntax::Expression::BinaryOp::OpType::BIT_LSHIFT: - case Syntax::Expression::BinaryOp::OpType::BIT_RSHIFT: { - precedence = 3; - break; - } - case Syntax::Expression::BinaryOp::OpType::LT: - case Syntax::Expression::BinaryOp::OpType::LTEQ: - case Syntax::Expression::BinaryOp::OpType::GT: - case Syntax::Expression::BinaryOp::OpType::GTEQ: { - precedence = 4; - break; - } - case Syntax::Expression::BinaryOp::OpType::EQEQ: - case Syntax::Expression::BinaryOp::OpType::NOTEQ: { - precedence = 5; - break; - } - case Syntax::Expression::BinaryOp::OpType::BIT_AND: { - precedence = 6; - break; - } - case Syntax::Expression::BinaryOp::OpType::BIT_XOR: { - precedence = 7; - break; - } - case Syntax::Expression::BinaryOp::OpType::BIT_OR: { - precedence = 8; - break; - } - case Syntax::Expression::BinaryOp::OpType::AND: { - precedence = 9; - break; - } - case Syntax::Expression::BinaryOp::OpType::OR: { - precedence = 10; - break; - } - case Syntax::Expression::BinaryOp::OpType::EQ: - case Syntax::Expression::BinaryOp::OpType::PLUSEQ: - case Syntax::Expression::BinaryOp::OpType::MINUSEQ: - case Syntax::Expression::BinaryOp::OpType::MULEQ: - case Syntax::Expression::BinaryOp::OpType::DIVEQ: - case Syntax::Expression::BinaryOp::OpType::MOD_EQ: - case Syntax::Expression::BinaryOp::OpType::BIT_LSHIFT_EQ: - case Syntax::Expression::BinaryOp::OpType::BIT_RSHIFT_EQ: - case Syntax::Expression::BinaryOp::OpType::BIT_AND_EQ: - case Syntax::Expression::BinaryOp::OpType::BIT_XOR_EQ: - case Syntax::Expression::BinaryOp::OpType::BIT_OR_EQ: { - precedence = 11; - break; - } - default: { - precedence = -1; - break; - } - } - if (precedence < min_precedence) { - min_precedence = precedence; - next_op = i; - auto op = expression->op_type; - unary = - (op == Syntax::Expression::BinaryOp::OpType::NOT || - op == Syntax::Expression::BinaryOp::OpType::BIT_NOT || - op == Syntax::Expression::BinaryOp::OpType::UPLUS || - op == Syntax::Expression::BinaryOp::OpType::REFERENCE || - op == Syntax::Expression::BinaryOp::OpType::UMINUS || - op == Syntax::Expression::BinaryOp::OpType::DEREFERENCE); - // break; - } - } - ASSERT(next_op >= 0); - if (unary) { - int next_expr = next_op; - while (exprs[next_expr]->isOperator) { - if (++next_expr == (int)exprs.size()) { - createError(exprs[next_expr - 1]->getDBGInfo()->pos, "expected an expression.", {}, 1); - } - } - for (int i = next_expr - 1; i >= next_op; i--) { - auto e = utils::cast(exprs[(size_t) i]); - auto op_node = new Syntax::Expression::BinaryOp(e->op_type); - op_node->setDBGInfo(e->getDBGInfo()); - op_node->left = exprs[(size_t) i + 1]; - exprs.at(i) = op_node; - exprs.erase(exprs.begin() + i + 1); - } - } else { - ASSERT(next_op >= 1 && next_op < (int) exprs.size() - 1) - ASSERT(!(exprs[(size_t) next_op + 1]->isOperator) && !(exprs[(size_t) next_op - 1]->isOperator)); - auto e = utils::cast(exprs[(size_t) next_op]); - auto op_node = new Syntax::Expression::BinaryOp(e->op_type); - op_node->setDBGInfo(e->getDBGInfo()); - if (exprs[(size_t) next_op - 1]->isOperator) { - if (Syntax::Expression::BinaryOp::is_assignment((Syntax::Expression::BinaryOp*) exprs[(size_t) next_op - 1])) { - createError(exprs[(size_t) next_op - 1]->getDBGInfo()->pos, "unexpected assignment.", {}, 1); - } - } - if (exprs[(size_t) next_op + 1]->isOperator) { - if (Syntax::Expression::BinaryOp::is_assignment((Syntax::Expression::BinaryOp*) exprs[(size_t) next_op + 1])) { - createError(exprs[(size_t) next_op + 1]->getDBGInfo()->pos, "unexpected assignment.", {}, 1); - } - } - op_node->left = exprs[(size_t) next_op - 1]; - op_node->right = exprs[(size_t) next_op + 1]; - exprs.at((size_t) next_op - 1) = op_node; - exprs.erase(exprs.begin() + next_op); - exprs.erase(exprs.begin() + next_op); - } - } - return exprs[0]; -} - -} // namespace snowball::parser - -#undef IF_TOKEN diff --git a/src/parser/parseAttributes.cc b/src/parser/parseAttributes.cc deleted file mode 100644 index 5c50fef3..00000000 --- a/src/parser/parseAttributes.cc +++ /dev/null @@ -1,101 +0,0 @@ -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "./Parser.h" - -#include - -namespace snowball::parser { - -std::unordered_map> Parser::parseAttributes( - bool forConstexpr) { - assert(is() || forConstexpr); - std::unordered_map> attributes; - while (is() || forConstexpr) { - if (!forConstexpr) next(); - std::unordered_map attrArgs; - auto attr = m_current.to_string(); - if (!(m_current.type > TokenType::KWORD__START__POINT && m_current.type < TokenType::KWORD__ENDING__POINT)) - assert_tok("an identifier"); - if (is(peek())) { - next(); - while (true) { - next(); - if (is()) { break; } - // TODO: check for already deifned ones - auto name = assert_tok("an identifier").to_string(); - next(); - if (is()) { - next(); - if (is()) { - auto val = m_current.to_string(); - if (is()) val = val.substr(1, val.size() - 2); // remove " - attrArgs[name] = val; - } else if (is()) { - attrArgs[name] = m_current.to_string(); - } else { - createError( - FMT("Expected a string or a number value but found '%s' instead", peek().to_string().c_str()) - ); - } - } else { - attrArgs[name] = ""; - prev(); - } - auto pk = peek(); - if (is(pk) || is(pk)) { - if (is(pk)) next(); - continue; - } else { - next(); - createError(FMT("Expected a ',' or a ')' but found '%s' instead", pk.to_string().c_str())); - } - } - } - if (attributes.find(attr) != attributes.end()) { - createError(FMT("Attribute '%s' is already defined!", attr.c_str())); - } - attributes.insert({attr, attrArgs}); - if (forConstexpr) break; - next(); - } - if (!forConstexpr) { - prev(); - m_attributes = attributes; - } - return attributes; -} - -std::unordered_map> Parser::verifyAttributes( - std::function parseFn -) { - return verifyAttributes(parseFn, m_attributes); -} - -std::unordered_map> Parser::verifyAttributes( - std::function parseFn, - std::unordered_map>& attrs -) { - std::unordered_map> attributes; - for (auto& [attr, args] : attrs) { - auto attrType = parseFn(attr); - if (attr == "cfg") { - attrType = Attributes::CFG; - } else if (attr == "attr") { - attrType = Attributes::ATTR; - } -if (attrType == Attributes::INVALID) { - createError(FMT("Invalid attribute '%s'", attr.c_str())); - } - attributes[attrType] = args; - } - attrs.clear(); - return attributes; -} - -void Parser::assertNoAttributes(std::string context) { - if (m_attributes.size() > 0) { - createError(FMT("Attributes are not allowed inside a %s", context.c_str())); - } -} - -} // namespace snowball::parser diff --git a/src/parser/parseBlock.cc b/src/parser/parseBlock.cc deleted file mode 100644 index 35849eba..00000000 --- a/src/parser/parseBlock.cc +++ /dev/null @@ -1,30 +0,0 @@ - -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "./Parser.h" - -#include - -namespace snowball::parser { - -Syntax::Block* Parser::parseBlock(std::vector termination) { - assert(!is()); - std::vector stmts; - while (true) { - auto pk = peek(); - for (auto t : termination) { - if (pk.type == t) { - next(); - return new Syntax::Block(stmts); - } - } - if (is(pk)) { - next(); - continue; - } - stmts.push_back(parseStatement(pk)); - } - return nullptr; // to remove warnings -} - -} // namespace snowball::parser diff --git a/src/parser/parseBlockOrStmt.cc b/src/parser/parseBlockOrStmt.cc deleted file mode 100644 index 97ab2aa0..00000000 --- a/src/parser/parseBlockOrStmt.cc +++ /dev/null @@ -1,23 +0,0 @@ -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "./Parser.h" - -#include - -namespace snowball::parser { - -Syntax::Block* Parser::parseBlockOrStmt() { - if (is(peek())) { - next(); - return parseBlock(); - } else { - auto dbg = DBGSourceInfo::fromToken(m_source_info, m_current); - auto tk = peek(); - auto expr = parseStatement(tk); - auto block = Syntax::N(std::vector {expr}); - block->setDBGInfo(dbg); - return block; - } -} - -} // namespace snowball::parser \ No newline at end of file diff --git a/src/parser/parseClass.cc b/src/parser/parseClass.cc deleted file mode 100644 index 027484bb..00000000 --- a/src/parser/parseClass.cc +++ /dev/null @@ -1,291 +0,0 @@ - -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "../services/OperatorService.h" -#include "./Parser.h" - -#include -#define IS_CONSTRUCTOR(tk) is(tk) && tk.value == name - -namespace snowball::parser { - -Syntax::Statement::DefinedTypeDef* Parser::parseClass() { - bool isInterface = is(); - assert(is() || isInterface); - auto comment = parseDocstring(m_current.getComment()); - next(); // East "class" or "interface" - bool isPublic = false; - bool extends = false; - if (is(peek(-3, true))) { - isPublic = is(peek(-3, true)); - } - auto attributes = verifyAttributes([&](std::string attr) { - if (attr == "__internal__") { - return Attributes::BUILTIN; - } else if (attr == "no_constructor") { - return Attributes::NO_CONSTRUCTOR; - } -return Attributes::INVALID; - }); - if (is()) { - next(); - attributes[Attributes::CLASS_EXTENDS] = {}; - extends = true; - } - std::string name; - // TODO: check this is only for std lib builds!!! - if (is()) { - next(); - if (is()) { - name = _SNOWBALL_MUT_PTR; - } else { - assert_tok("'const' or 'mut'"); - name = _SNOWBALL_CONST_PTR; - } - } else { - name = assert_tok("class identifier").to_string(); - } - auto dbg = DBGSourceInfo::fromToken(m_source_info, m_current); - Syntax::Expression::TypeRef* parentClass = nullptr; - Syntax::Statement::GenericContainer<>::GenericList generics; - bool hasGenerics = false; - std::vector impls; - if (is(peek())) { - next(); - hasGenerics = true; - generics = parseGenericParams(); - prev(); - } - next(); - if (is()) { - next(); - throwIfNotType(); - parentClass = parseType(); - } - if (is()) { - next(); - while (true) { - impls.push_back(parseType()); - if (is()) { - next(); - continue; - } - break; - } - } - assert_tok("'{'"); - bool inPrivateScope = true; - bool hasConstructor = false; - auto cls = Syntax::N( - name, - parentClass, - Syntax::Statement::Privacy::fromInt(isPublic), - isInterface ? Syntax::Statement::DefinedTypeDef::Type::INTERFACE : - Syntax::Statement::DefinedTypeDef::Type::CLASS - ); - cls->setImpls(impls); - if (hasGenerics) - cls->setGenerics(generics); - cls->setDBGInfo(dbg); - for (auto attr : attributes) cls->addAttribute(attr.first, attr.second); - if (cls->hasAttribute(Attributes::BUILTIN)) { - if (name == "IntegerImpl") - cls->unsafeSetName(_SNOWBALL_INT_IMPL); - else if (name == "FunctionImpl") - cls->unsafeSetName(_SNOWBALL_FUNC_IMPL); - else if (name != _SNOWBALL_CONST_PTR - && name != _SNOWBALL_MUT_PTR) createError(FMT("Unknown builtin class '%s'", name.c_str())); - } - auto classBackup = m_current_class; - m_current_class = cls; - while (true) { - next(); - switch (m_current.type) { - case TokenType::KWORD_PRIVATE: { - assertNoAttributes("before private keyword"); - inPrivateScope = true; - next(); - assert_tok("':'"); - } break; - case TokenType::KWORD_PUBLIC: { - assertNoAttributes("before public keyword"); - inPrivateScope = false; - next(); - assert_tok("':'"); - } break; - case TokenType::KWORD_CONST: { - assertNoAttributes("before const keyword"); - if (isInterface) { - createError("Interfaces can't have constants!"); - } else if (extends) { - createError("Classes that extend other types cant have *new* constants!"); - } - auto var = parseConstant(); - var->setPrivacy(Syntax::Statement::Privacy::fromInt(!inPrivateScope)); - if (var->getValue() == nullptr) { - createError("expected a value for constant declaration!"); - } - cls->addVariable(var); - assert_tok("a ';'"); - } break; - case TokenType::KWORD_ENUM: { - if (extends) { - createError("Classes that extend other types cant have *new* enums!"); - } else if (isInterface) { - createError("Interfaces can't have enums!"); - } - auto enumDecl = parseEnum(); - enumDecl->setPrivacy(Syntax::Statement::Privacy::fromInt(!inPrivateScope)); - cls->addChildType(enumDecl); - } break; - case TokenType::SYM_AT: { - parseAttributes(); - } break; - case TokenType::KWORD_STATIC: { - auto pk = peek(); - if (pk.type == TokenType::KWORD_MUTABLE) { - next(); - createError( - "Static members cant be mutable!", { - .note = "To fix this error, you can remove the 'static' or 'mut' keyword.", - .help = "If you want to have a static mutable member, you can use a \nstatic pointer to a " - "mutable member." - } - ); - } - if (pk.type != TokenType::KWORD_FUNC && - pk.type != TokenType::KWORD_OPERATOR && pk.type != TokenType::KWORD_UNSAFE && (!IS_CONSTRUCTOR(pk)) - && pk.type != TokenType::KWORD_OVERRIDE) { - next(); - createError("expected keyword \"func\", \"override\", \"let\", \"operator\", \"unsafe\" or a " - "constructor " - "declaration after static member"); - } - } break; - case TokenType::KWORD_OVERRIDE: { - auto pk = peek(); - if (pk.type != TokenType::KWORD_FUNC && pk.type != TokenType::KWORD_OPERATOR && pk.type != TokenType::KWORD_UNSAFE - && pk.type != TokenType::KWORD_MUTABLE && pk.type != TokenType::KWORD_VIRTUAL) { - next(); - createError("expected keyword \"func\" or \"operator\", \"unsafe\", \"mut\" or \"virtual\" " - "after override declaration!"); - } - } break; - case TokenType::KWORD_UNSAFE: { - auto pk = peek(); - if (pk.type != TokenType::KWORD_FUNC && pk.type != TokenType::KWORD_OPERATOR && pk.type != TokenType::KWORD_STATIC - && pk.type != TokenType::KWORD_MUTABLE) { - next(); - createError("expected keyword \"func\" or \"operator\", \"static\" or \"mut\" after unsafe " - "declaration!"); - } - } break; - case TokenType::KWORD_FUNC: { - auto func = parseFunction(false, false, false, isInterface); - func->setPrivacy(Syntax::Statement::Privacy::fromInt(!inPrivateScope)); - cls->addFunction(func); - } break; - case TokenType::KWORD_OPERATOR: { - auto func = parseFunction(false, true); - func->setPrivacy(Syntax::Statement::Privacy::fromInt(!inPrivateScope)); - cls->addFunction(func); - } break; - case TokenType::KWORD_MUTABLE: { - auto pk = peek(); - if (pk.type != TokenType::KWORD_FUNC && pk.type != TokenType::KWORD_OPERATOR && - pk.type != TokenType::KWORD_UNSAFE && pk.type != TokenType::KWORD_OVERRIDE) { - next(); - createError("expected keyword \"func\", \"unsafe\" or \"operator\" after mutable declaration!"); - } - } break; - case TokenType::KWORD_VIRTUAL: { - auto pk = peek(); - if (pk.type == TokenType::KWORD_STATIC) { - next(); - createError("Virtual methods cant be static!"); - } else if (extends) { - next(); - createError("Classes that extend other types cant have *new* virtual methods!"); - } else if (pk.type != TokenType::KWORD_FUNC && pk.type != TokenType::KWORD_MUTABLE) { - next(); - createError("Expected keyword \"func\" or \"mut\" after virtual declaration!"); - } - } break; - case TokenType::KWORD_VAR: { - assertNoAttributes("a variable"); - auto var = parseVariable(); - var->setPrivacy(Syntax::Statement::Privacy::fromInt(!inPrivateScope)); - cls->addVariable(var); - assert_tok("a ';'"); - if (extends) { createError("Classes that extend other types cant have *new* variables!"); } - } break; - case TokenType::BRACKET_RCURLY: { - assertNoAttributes("before '}'"); - cls->hasConstructor = hasConstructor; - m_current_class = classBackup; - cls->setComment(comment); - return cls; - } - case TokenType::KWORD_TYPEDEF: { - assertNoAttributes("a type alias"); - if (extends) { - createError("Classes that extend other types cant have *new* type aliases!"); - } else if (isInterface) { - createError("Interfaces can't have type aliases!"); - } - auto typeDef = parseTypeAlias(); - typeDef->setPrivacy(Syntax::Statement::Privacy::fromInt(!inPrivateScope)); - cls->addChildType(typeDef); - assert_tok("a ';'"); - } break; - case TokenType::KWORD_CLASS: - case TokenType::KWORD_INTER: { - if (extends) { - createError("Classes that extend other types cant have *new* classes!"); - } else if (isInterface) { - createError("Interfaces can't have classes!"); - } - auto innerClass = parseClass(); - innerClass->setPrivacy(Syntax::Statement::Privacy::fromInt(!inPrivateScope)); - cls->addChildType(innerClass); - } break; - case TokenType::KWORD_STRUCT: { - if (extends) { - createError("Classes that extend other types cant have *new* structs!"); - } else if (isInterface) { - createError("Interfaces can't have structs!"); - } - auto innerStruct = parseStructure(); - innerStruct->setPrivacy(Syntax::Statement::Privacy::fromInt(!inPrivateScope)); - cls->addChildType(innerStruct); - } break; - // note: This case should be always at the bottom! - case TokenType::IDENTIFIER: { - assertNoAttributes("before identifier"); - if (IS_CONSTRUCTOR(m_current)) { - if (isInterface) { - createError("Interfaces can't have constructors!"); - } else if (extends) { - // NOTE: If we end up allowing this, we need to make sure enums can't have constructors! - createError("Classes that extend other types cant have *new* constructors!"); - } - hasConstructor = true; - auto func = parseFunction(true); - func->setPrivacy(Syntax::Statement::Privacy::fromInt(!inPrivateScope)); - func->setName(services::OperatorService::getOperatorMangle(services::OperatorService::CONSTRUCTOR)); - func->setStatic(); - cls->addFunction(func); - break; - } - __attribute__((fallthrough)); - } - default: { - createError( - FMT("Unexpected token ('%s') found while parsing class body", m_current.to_string().c_str()) - ); - } - } - } -} - -} // namespace snowball::parser diff --git a/src/parser/parseComment.cc b/src/parser/parseComment.cc deleted file mode 100644 index 856668d4..00000000 --- a/src/parser/parseComment.cc +++ /dev/null @@ -1,65 +0,0 @@ - -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "./Parser.h" - -#include -#include -#include - -namespace snowball::parser { -using CommentType = Syntax::Comment; - -static const std::regex tagRegex("@(\\w+)\\s*(.*)"); - -CommentType* Parser::parseDocstring(std::string p_content) { - if (!m_allow_comments) return nullptr; - auto comment = m_current.getComment(); - bool valid = true; - std::map tags; - std::string content; - if (utils::startsWith(comment, "///")) { - comment = comment.substr(3); - } else if (utils::startsWith(comment, "/**")) { - comment = comment.substr(3); - comment = comment.substr(0, comment.size() - 2); - } else { - valid = false; - } - if (valid) { - int paramCount = 0; - auto lines = utils::split(comment, "\n"); - std::smatch matches; - std::string lastTag; - for (auto& line : lines) { - if (std::regex_search(line, matches, tagRegex)) { - std::string tag = matches[1]; - std::string content = matches[2]; - if (tag == "param") { - tag = "param$" + std::to_string(paramCount++); - } - tags[tag] = content; - lastTag = tag; - } else { - auto trim = line; - utils::replaceAll(trim, " ", ""); - if (utils::startsWith(trim, "*")) { - auto idx = line.find_first_of("*"); - line = line.substr(idx + 1); - } - if ((trim.empty() || (trim == "*")) && !lastTag.empty()) lastTag = ""; - if (utils::startsWith(line, " ") && (!trim.empty() || !(trim != "*")) && !lastTag.empty()) { - tags[lastTag] += "\n" + line.substr(1); - } else { - if (!line.empty()) { - content += line + "\n"; - } - } - } - } - return new CommentType(tags, content, valid); - } - return nullptr; -} - -} // namespace snowball::parser diff --git a/src/parser/parseConditional.cc b/src/parser/parseConditional.cc deleted file mode 100644 index b6b6fd37..00000000 --- a/src/parser/parseConditional.cc +++ /dev/null @@ -1,41 +0,0 @@ - -#include "../ast/types/PrimitiveTypes.h" -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "./Parser.h" - -#include - -using namespace snowball::Syntax::Statement; -using namespace snowball::Syntax; -namespace snowball::parser { - -Statement::Base* Parser::parseConditional() { - assert(is()); - auto info = DBGSourceInfo::fromToken(m_source_info, m_current); - // If the next token is a constexpr, then this is a compile-time conditional. - if (is(peek())) { - createError("Compile-time conditionals are not yet supported"); - next(); - auto attrs = parseAttributes(true); - next(); - auto block = parseBlock(); - //auto node = Syntax::N(block); - //for (auto [n, a] : verifyAttributes([](auto _) { return Attributes::INVALID; }, attrs)) { node->addAttribute(n, a); } - //node->setDBGInfo(info); - //return node; - } - // Otherwise, parse a runtime conditional. - auto expr = parseExpr(false); - next(); - auto block = parseBlock(); - Block* elseBlock = nullptr; - if (is(peek())) { - next(); - elseBlock = parseBlockOrStmt(); - } - auto node = Syntax::N(expr, block, elseBlock); - node->setDBGInfo(info); - return node; -} -} // namespace snowball::parser diff --git a/src/parser/parseConstant.cc b/src/parser/parseConstant.cc deleted file mode 100644 index 59fe1495..00000000 --- a/src/parser/parseConstant.cc +++ /dev/null @@ -1,61 +0,0 @@ - -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "./Parser.h" - -#include - -namespace snowball::parser { - -Syntax::Statement::VariableDecl* Parser::parseConstant() { - assert(is()); - auto comment = parseDocstring(m_current.getComment()); - auto attributes = verifyAttributes([&](std::string attr) { - return Attributes::INVALID; - }); - next(); - bool isPublic = false; - bool isExternal = false; - bool isStatic = false; - if (is(peek(-3, true))) { - isPublic = is(peek(-3, true)); - } else if (is(peek(-3, true))) { - isExternal = true; - isPublic = is(peek(-4, true)); - } else if (is(peek(-3, true))) { - isStatic = true; - isPublic = is(peek(-4, true)); - } - if (!isStatic && m_current_class != nullptr) { - createError("Cannot declare a non-static constant inside a class", { - .info = "Not static constant", - .note = "This is because constants are not tied to a specific instance of a class,\n" - "and therefore cannot be accessed from an instance of a class", - .help = "Make the constant static by adding the 'static' keyword\nbefore the 'const' keyword", - }); - } - auto token = assert_tok("an identifier"); - next(); // consume identifier - auto name = token.to_string(); - // TODO: actually find type definition - Syntax::Expression::TypeRef* typeDef = nullptr; - consume("':' for a type declaration"); - typeDef = parseType(); - Syntax::Expression::Base* value = nullptr; - if (!isExternal) { - assert_tok("'=' for a variable declaration"); - value = parseExpr(false); - } - if (is(peek(0, true))) next(); - auto v = Syntax::N(name, value, false, true); - v->setDefinedType(typeDef); - v->setPrivacy(Syntax::Statement::Privacy::fromInt(isPublic)); - auto info = new DBGSourceInfo(m_source_info, token.get_pos(), token.get_width()); - v->setDBGInfo(info); - v->setComment(comment); - v->setExternDecl(isExternal); - for (auto[n, a] : attributes) { v->addAttribute(n, a); } - return v; // to remove warnings -} - -} // namespace snowball::parser diff --git a/src/parser/parseEnum.cc b/src/parser/parseEnum.cc deleted file mode 100644 index 47f3e161..00000000 --- a/src/parser/parseEnum.cc +++ /dev/null @@ -1,86 +0,0 @@ - -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "../services/OperatorService.h" -#include "./Parser.h" - -#include - -namespace snowball::parser { - -Syntax::Statement::EnumTypeDef* Parser::parseEnum() { - assert(is()); - auto comment = parseDocstring(m_current.getComment()); - next(); // East "enum" - bool isPublic = false; - if (is(peek(-3, true))) { - isPublic = is(peek(-3, true)); - } - auto attributes = verifyAttributes([&](std::string attr) { - return Attributes::INVALID; - }); - auto name = assert_tok("enum identifier").to_string(); - auto dbg = DBGSourceInfo::fromToken(m_source_info, m_current); - Syntax::Statement::GenericContainer<>::GenericList generics; - bool hasGenerics = false; - if (is(peek())) { - next(); - hasGenerics = true; - generics = parseGenericParams(); - prev(); - } - next(); - assert_tok("'{'"); - next(); - auto cls = Syntax::N( - name, Syntax::Statement::Privacy::fromInt(isPublic) - ); - if (hasGenerics) - cls->setGenerics(generics); - cls->setDBGInfo(dbg); - bool keepParsing = true; - while (keepParsing) { - switch (m_current.type) { - case TokenType::IDENTIFIER: { - auto name = m_current.to_string(); - if (is(peek())) { - next(); - std::vector fields; - while (true) { - next(); - fields.push_back(parseType()); - if (!is()) { - break; - } - } - assert_tok("')'"); - cls->addField({name, fields}); - } else { - cls->addField({name, {}}); - } - next(); - if (!is()) { - assert_tok("',' or '}'"); - next(); - } - break; - } - case TokenType::BRACKET_RCURLY: { - keepParsing = false; - break; - } - default: { - createError( - FMT("Expected a valid member declaration but found '%s'", m_current.to_string().c_str()) - ); - break; - } - } - } - assert_tok("'}'"); - cls->setComment(comment); - for (auto attr : attributes) cls->addAttribute(attr.first, attr.second); - return cls; -} - -} // namespace snowball::parser diff --git a/src/parser/parseExpr.cc b/src/parser/parseExpr.cc deleted file mode 100644 index 28f387a2..00000000 --- a/src/parser/parseExpr.cc +++ /dev/null @@ -1,276 +0,0 @@ - -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "../services/OperatorService.h" -#include "../utils/utils.h" -#include "./Parser.h" - -#include -#define TOKEN(comp) is() - -#define RIGHT_NEXT_TO(atPos, iPos) (atPos.first == iPos.first) && (atPos.second == (iPos.second - 1)) - -using Operators = snowball::services::OperatorService; - -namespace snowball::parser { - -Syntax::Expression::Base* Parser::parseExpr(bool allowAssign) { - std::vector exprs; - while (true) { - auto tk = next(); - Syntax::Expression::Base* expr = nullptr; - bool parseNormal = false; - auto dbg = DBGSourceInfo::fromToken(m_source_info, m_current); - if (TOKEN(SYM_HASH)) { - if (TOKEN(SYM_HASH) && is(peek())) { - auto atPos = m_current.get_pos(); - next(); - auto iPos = m_current.get_pos(); - if (RIGHT_NEXT_TO(atPos, iPos)) { - auto dbg = DBGSourceInfo::fromToken(m_source_info, m_current); - dbg->pos.second++; - dbg->width++; - auto var = Syntax::N(m_current.to_string()); - var->setDBGInfo(dbg); - expr = var; - } else { - prev(); - parseNormal = true; - } - } else - parseNormal = true; - } else if (TOKEN(IDENTIFIER), is(peek())) { - auto atPos = m_current.get_pos(); - atPos.second = atPos.second + m_current.to_string().size() - 1; - auto name = m_current.to_string(); - next(); - auto iPos = m_current.get_pos(); - if (RIGHT_NEXT_TO(atPos, iPos)) { - auto dbg = DBGSourceInfo::fromToken(m_source_info, m_current); - next(); - assert_tok("'('"); - dbg->width--; - std::vector args; - next(); - if (!is()) { - prev(1); - while (true) { - next(); - auto pk = peek(); - if (is(pk)) { - next(1); - args.push_back(parseType()); - prev(); - } else { - args.push_back(parseStatement(pk)); - } - if (is(peek())) { - } else { - next(); - break; - } - } - assert_tok("')'"); - auto var = Syntax::N(name); - var->setDBGInfo(dbg); - var->setArgs(args); - expr = var; - } else { - auto var = Syntax::N(name); - var->setDBGInfo(dbg); - var->setArgs(args); - expr = var; - } - } else { - prev(); - parseNormal = true; - } - } else - parseNormal = true; - if (parseNormal) { - if (TOKEN(BRACKET_LPARENT)) { - expr = parseExpr(allowAssign); - next(); - assert_tok("')'"); - } else if (TOKEN(VALUE_NUMBER) || TOKEN(VALUE_FLOAT) || TOKEN(VALUE_STRING) || TOKEN(VALUE_CHAR) || TOKEN(VALUE_BOOL)) { - auto ty = Syntax::Expression::ConstantValue::deduceType(m_current.type); - expr = Syntax::N(ty, m_current.to_string()); - } else if (TOKEN(IDENTIFIER)) { - if (is(peek())) { - auto identifier = m_current.to_string(); - auto atPos = m_current.get_pos(); - next(); - auto iPos = m_current.get_pos(); - if (RIGHT_NEXT_TO(atPos, iPos)) { - auto ty = Syntax::Expression::ConstantValue::deduceType(m_current.type); - expr = Syntax::N(ty, m_current.to_string(), identifier); - } else { - prev(); - } - } - if (expr == nullptr) - expr = parseIdentifier(); - } else if (TOKEN(KWORD_NEW)) { - next(); - auto ty = parseType(); - assert_tok("'('"); - auto call = parseFunctionCall(ty); - expr = Syntax::N(call, ty); - expr->setDBGInfo(call->getDBGInfo()); - } else if (TOKEN(OP_NOT) || TOKEN(OP_PLUS) || TOKEN(OP_MINUS) || TOKEN(OP_BIT_NOT) || TOKEN(OP_BIT_AND) - || TOKEN(OP_MUL)) { - if (tk.type == TokenType::OP_NOT) - exprs.push_back(Syntax::N(Operators::OperatorType::NOT)); - else if (tk.type == TokenType::OP_PLUS) - exprs.push_back(Syntax::N(Operators::OperatorType::UPLUS)); - else if (tk.type == TokenType::OP_MINUS) - exprs.push_back(Syntax::N(Operators::OperatorType::UMINUS)); - else if (tk.type == TokenType::OP_BIT_NOT) - exprs.push_back(Syntax::N(Operators::OperatorType::BIT_NOT)); - else if (tk.type == TokenType::OP_BIT_AND) { - exprs.push_back(Syntax::N(Operators::OperatorType::REFERENCE)); - if (is(peek())) { - next(); - ((Syntax::Expression::BinaryOp*)exprs.back())->isMutableReference = true; - } - } else if (tk.type == TokenType::OP_MUL) - exprs.push_back(Syntax::N(Operators::OperatorType::DEREFERENCE)); - exprs.back()->isOperator = true; - exprs.back()->setDBGInfo(dbg); - continue; - } else if (TOKEN(KWORD_FUNC)) { - auto f = parseFunction(false, false, true); - expr = Syntax::N(utils::cast(f)); - expr->setDBGInfo(f->getDBGInfo()); - } else { - createError(FMT("Expected a valid expression but got '%s'", m_current.to_string().c_str())); - } - } - if (expr->getDBGInfo() == nullptr) expr->setDBGInfo(dbg); - while (true) { - tk = peek(0, true); - if (is(tk)) { - next(); - // auto callee = expr; - expr = parseFunctionCall(expr); - } else if (is(tk)) { - next(); - auto indexExpr = parseExpr(false); - auto dbg = DBGSourceInfo::fromToken(m_source_info, m_current); - auto bop = Syntax::N(Syntax::Expression::BinaryOp::OpType::INDEX); - bop->isOperator = false; - bop->setDBGInfo(dbg); - next(); - assert_tok("']'"); - bop->left = expr; - bop->right = indexExpr; - expr = bop; - } else if (is(tk) || is(tk)) { - auto isStatic = is(tk); - auto x = peek(1, true); - if (!isStatic && is(peek(1, true))) { // Range expr (1..5) - auto dbg = DBGSourceInfo::fromToken(m_source_info, m_current); - auto bop = Syntax::N(Syntax::Expression::BinaryOp::OpType::RANGE); - bop->isOperator = false; - bop->setDBGInfo(dbg); - bop->left = expr; - next(1); - bop->right = parseExpr(false); - expr = bop; - } else { - next(1); - assert_tok("an identifier"); - auto index = parseIdentifier(); - auto dbgInfo = new DBGSourceInfo( - m_source_info, - expr->getDBGInfo()->pos, - expr->getDBGInfo()->width + index->getDBGInfo()->width + 2 - ); - expr = Syntax::N(expr, index, isStatic); - expr->setDBGInfo(dbgInfo); - } - } else if (is(tk)) { - next(1); - throwIfNotType(); - auto ty = parseType(); - prev(); - auto dbgInfo = new DBGSourceInfo( - m_source_info, - expr->getDBGInfo()->pos, - ty->getDBGInfo()->pos.second - expr->getDBGInfo()->pos.second + ty->getDBGInfo()->width - ); - expr = Syntax::N(expr, ty); - expr->setDBGInfo(dbgInfo); - } else { - break; - } - } - bool valid = true; - exprs.emplace_back(expr); - services::OperatorService::OperatorType op_type; - tk = peek(); -#define OP_CASE(m_tk, m_op) \ -case TokenType::m_tk: { \ - op_type = services::OperatorService::OperatorType::m_op; \ - break; \ - } - switch (tk.type) { - OP_CASE(OP_EQ, EQ); - OP_CASE(OP_EQEQ, EQEQ); - OP_CASE(OP_PLUS, PLUS); - OP_CASE(OP_PLUSEQ, PLUSEQ); - OP_CASE(OP_MINUS, MINUS); - OP_CASE(OP_MINUSEQ, MINUSEQ); - OP_CASE(OP_MUL, MUL); - OP_CASE(OP_MULEQ, MULEQ); - OP_CASE(OP_DIV, DIV); - OP_CASE(OP_DIVEQ, DIVEQ); - OP_CASE(OP_MOD, MOD); - OP_CASE(OP_MOD_EQ, MOD_EQ); - OP_CASE(OP_LT, LT); - OP_CASE(OP_LTEQ, LTEQ); - OP_CASE(OP_GT, GT); - OP_CASE(OP_GTEQ, GTEQ); - OP_CASE(OP_AND, AND); - OP_CASE(OP_OR, OR); - OP_CASE(OP_NOT, NOT); - OP_CASE(OP_NOTEQ, NOTEQ); - OP_CASE(OP_BIT_NOT, BIT_NOT); - OP_CASE(OP_BIT_LSHIFT, BIT_LSHIFT); - OP_CASE(OP_BIT_LSHIFT_EQ, BIT_LSHIFT_EQ); - OP_CASE(OP_BIT_RSHIFT, BIT_RSHIFT); - OP_CASE(OP_BIT_RSHIFT_EQ, BIT_RSHIFT_EQ); - OP_CASE(OP_BIT_OR, BIT_OR); - OP_CASE(OP_BIT_OR_EQ, BIT_OR_EQ); - OP_CASE(OP_BIT_AND, BIT_AND); - OP_CASE(OP_BIT_AND_EQ, BIT_AND_EQ); - OP_CASE(OP_BIT_XOR, BIT_XOR); - OP_CASE(OP_BIT_XOR_EQ, BIT_XOR_EQ); - default: valid = false; -#undef OP_CASE - } - if (valid) { - next(); // Eat peeked token. - auto dbg = DBGSourceInfo::fromToken(m_source_info, m_current); - auto bop = Syntax::N(op_type); - bop->isOperator = true; - bop->setDBGInfo(dbg); - exprs.push_back(bop); - } else { - break; - } - } - auto expr = buildOperatorTree(exprs); - if (auto x = utils::cast(expr)) { - if (!allowAssign && Syntax::Expression::BinaryOp::is_assignment(x)) { - createError( - expr->getDBGInfo()->pos, "assignment is not allowed inside expression.", {}, x->to_string().size() - ); - } - } - return expr; // to remove warnings -} - -} // namespace snowball::parser - -#undef IF_TOKEN diff --git a/src/parser/parseForLoop.cc b/src/parser/parseForLoop.cc deleted file mode 100644 index 2701d305..00000000 --- a/src/parser/parseForLoop.cc +++ /dev/null @@ -1,66 +0,0 @@ - -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "../services/OperatorService.h" -#include "./Parser.h" - -#include - -namespace snowball::parser { - -Syntax::Node* Parser::parseForLoop() { - assert(is()); - auto dbg = DBGSourceInfo::fromToken(m_source_info, m_current); - next(); // Eat "for" - if (is()) { - auto var = m_current.to_string(); - next(); - if (is() && m_current.to_string() == "in") { - auto expr = parseExpr(); - next(); - bool backupLoop = m_inside_loop; - m_inside_loop = true; - assert_tok("'{'"); - auto body = parseBlock(); - m_inside_loop = backupLoop; - auto loop = Syntax::N(var, expr, body); - loop->setDBGInfo(dbg); - return loop; - } - prev(); - } - prev(); - std::vector block; - Syntax::Expression::Base* condExpr = nullptr; - Syntax::Node* step = nullptr; - // C-style for loop - if (!is(peek())) { - auto init = parseStatement(peek()); - assert_tok("';'"); - block.push_back(init); - } else next(); - if (!is(peek())) { - condExpr = parseExpr(false); - next(); - assert_tok("';'"); - } else next(); - if (!is(peek())) { - step = parseExpr(); - } - next(); - bool backupLoop = m_inside_loop; - m_inside_loop = true; - assert_tok("'{'"); - auto body = parseBlock(); - m_inside_loop = backupLoop; - // Convert it into a simple while loop with a parent block - if (!condExpr) - condExpr = Syntax::N(Syntax::Expression::ConstantValue::Bool, "true"); - auto whileLoop = Syntax::N(condExpr, body, step); - block.push_back(whileLoop); - auto loopBlock = Syntax::N(block); - loopBlock->setDBGInfo(dbg); - return loopBlock; -} - -} // namespace snowball::parser diff --git a/src/parser/parseFunction.cc b/src/parser/parseFunction.cc deleted file mode 100644 index 5eaf33b1..00000000 --- a/src/parser/parseFunction.cc +++ /dev/null @@ -1,581 +0,0 @@ - -#include "../ast/types/PrimitiveTypes.h" -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "Parser.h" - -#include - -#define CHECK_PRIVACY(var) \ - var = true; \ - if (is(peek(peekCount - 1, true))) { \ - isPublic = is(peek(peekCount - 1, true)); \ - } - -using namespace snowball::Syntax; -using namespace snowball::Syntax::Statement; - -namespace snowball::parser { - -FunctionDef* Parser::parseFunction(bool isConstructor, bool isOperator, bool isLambda, bool allowDecl) { - assert((is() && (!isConstructor && !isOperator)) || - (is() && (isConstructor && !isOperator)) || (isOperator)); - auto comment = parseDocstring(m_current.getComment()); - if (!isConstructor && (!isLambda)) next(); - bool isExtern = false; - bool isPublic = false; - bool isStatic = false; - bool isVirtual = false; - bool isMutable = false; - bool isGeneric = false; - bool isUnsafe = false; - bool isOverride = false; - bool isNotImplemented = false; - std::string name; - std::string externName; - // Constructor specific only - std::vector superArgs; - bool hasSuperArgs = false; - std::map constructorInitArgs; - bool isLLVMFunction = false; - // Check if the tokens behind the function keyword - // have some meaning to this statement. For example, - // you can have: - // pub fn ... - // ^^^ - // to indicate that the function is public. - int peekCount = -3; -fetch_attrs: - auto pk = peek(peekCount, true); - if (is(pk)) { - isUnsafe = true; - peekCount--; - goto fetch_attrs; - } else if (is(pk)) { - CHECK_PRIVACY(isExtern) - } else if (is(pk)) { - CHECK_PRIVACY(isStatic) - } else if (is(pk)) { - isVirtual = true; - peekCount--; - goto fetch_attrs; - } else if (is(pk)) { - isPublic = pk.type == TokenType::KWORD_PUBLIC; - } else if (is(pk)) { - isMutable = true; - peekCount--; - goto fetch_attrs; - } else if (is(pk)) { - isOverride = true; - peekCount--; - goto fetch_attrs; - } - if (isOperator) { - consume("'func' keyword"); - } - if (isOverride && isStatic) { - createError("Static functions can't be overriden!"); - } - auto dbg = m_current.get_pos(); - auto width = 0; - auto attributes = verifyAttributes([&](std::string attr) { - if (attr == "llvm_function") { - isLLVMFunction = true; - return Attributes::LLVM_FUNC; - } else if (attr == "internal_linkage") { - return Attributes::INTERNAL_LINKAGE; - } else if (attr == "external_linkage") { - return Attributes::EXTERNAL_LINKAGE; - } else if (attr == "inline") { - return Attributes::INLINE; - } else if (attr == "no_inline") { - return Attributes::NO_INLINE; - } else if (attr == "test") { - return Attributes::TEST; - } else if (attr == "no_mangle") { - return Attributes::NO_MANGLE; - } else if (attr == "export") { - return Attributes::EXPORT; - } else if (attr == "bench") { - return Attributes::BENCH; - } else if (attr == "__internal__") { - return Attributes::BUILTIN; - } else if (attr == "__no_pointer_self__") { - return Attributes::NO_POINTER_SELF; - } else if (attr == "unsafe_fn_not_body") { - return Attributes::UNSAFE_FUNC_NOT_BODY; - } else if (attr == "intrinsic") { - return Attributes::INTRINSIC; - } -return Attributes::INVALID; - }); - if (isOverride) { - attributes[Attributes::OVERRIDE] = {}; - } - if (isOperator) { - services::OperatorService::OperatorType opType = services::OperatorService::OperatorType::INVALID; - switch (m_current.type) { - case TokenType::OP_EQ: { - opType = services::OperatorService::OperatorType::EQ; - break; - } - case TokenType::OP_EQEQ: { - opType = services::OperatorService::OperatorType::EQEQ; - break; - } - case TokenType::OP_PLUS: { - opType = services::OperatorService::OperatorType::PLUS; - break; - } - case TokenType::OP_PLUSEQ: { - opType = services::OperatorService::OperatorType::PLUSEQ; - break; - } - case TokenType::OP_MINUS: { - opType = services::OperatorService::OperatorType::MINUS; - break; - } - case TokenType::OP_MINUSEQ: { - opType = services::OperatorService::OperatorType::MINUSEQ; - break; - } - case TokenType::OP_MUL: { - opType = services::OperatorService::OperatorType::MUL; - break; - } - case TokenType::OP_MULEQ: { - opType = services::OperatorService::OperatorType::MULEQ; - break; - } - case TokenType::OP_DIV: { - opType = services::OperatorService::OperatorType::DIV; - break; - } - case TokenType::OP_DIVEQ: { - opType = services::OperatorService::OperatorType::DIVEQ; - break; - } - case TokenType::OP_MOD: { - opType = services::OperatorService::OperatorType::MOD; - break; - } - case TokenType::OP_MOD_EQ: { - opType = services::OperatorService::OperatorType::MOD_EQ; - break; - } - case TokenType::OP_LT: { - opType = services::OperatorService::OperatorType::LT; - break; - } - case TokenType::OP_LTEQ: { - opType = services::OperatorService::OperatorType::LTEQ; - break; - } - case TokenType::OP_GT: { - opType = services::OperatorService::OperatorType::GT; - break; - } - case TokenType::OP_GTEQ: { - opType = services::OperatorService::OperatorType::GTEQ; - break; - } - case TokenType::OP_AND: { - opType = services::OperatorService::OperatorType::AND; - break; - } - case TokenType::OP_OR: { - opType = services::OperatorService::OperatorType::OR; - break; - } - case TokenType::OP_NOT: { - opType = services::OperatorService::OperatorType::NOT; - break; - } - case TokenType::OP_NOTEQ: { - opType = services::OperatorService::OperatorType::NOTEQ; - break; - } - case TokenType::OP_BIT_NOT: { - opType = services::OperatorService::OperatorType::BIT_NOT; - break; - } - case TokenType::OP_BIT_LSHIFT: { - opType = services::OperatorService::OperatorType::BIT_LSHIFT; - break; - } - case TokenType::OP_BIT_LSHIFT_EQ: { - opType = services::OperatorService::OperatorType::BIT_LSHIFT_EQ; - break; - } - case TokenType::OP_BIT_RSHIFT: { - opType = services::OperatorService::OperatorType::BIT_RSHIFT; - break; - } - case TokenType::OP_BIT_RSHIFT_EQ: { - opType = services::OperatorService::OperatorType::BIT_RSHIFT_EQ; - break; - } - case TokenType::OP_BIT_OR: { - opType = services::OperatorService::OperatorType::BIT_OR; - break; - } - case TokenType::OP_BIT_OR_EQ: { - opType = services::OperatorService::OperatorType::BIT_OR_EQ; - break; - } - case TokenType::OP_BIT_AND: { - opType = services::OperatorService::OperatorType::BIT_AND; - break; - } - case TokenType::OP_BIT_AND_EQ: { - opType = services::OperatorService::OperatorType::BIT_AND_EQ; - break; - } - case TokenType::OP_BIT_XOR: { - opType = services::OperatorService::OperatorType::BIT_XOR; - break; - } - case TokenType::OP_BIT_XOR_EQ: { - opType = services::OperatorService::OperatorType::BIT_XOR_EQ; - break; - } - case TokenType::BRACKET_LSQUARED: { - if (is(peek())) { - opType = services::OperatorService::OperatorType::INDEX; - next(); - break; - } - goto snowballInvalidDefaultOperatorCase; - } - case TokenType::IDENTIFIER: { - if (m_current.to_string() == "bool") { - opType = services::OperatorService::OperatorType::BOOL; - break; - } - goto snowballInvalidDefaultOperatorCase; - } - case TokenType::BRACKET_LPARENT: { - if (is(peek())) { - opType = services::OperatorService::OperatorType::CALL; - break; - } - goto snowballInvalidDefaultOperatorCase; - } -snowballInvalidDefaultOperatorCase: - default: { - createError( - FMT("Expected a valid operator type but instead got '%s'", m_current.to_string().c_str()) - ); - } - } - name = services::OperatorService::getOperatorMangle(opType); - externName = name; - } else if (isLambda) { - } else { - // Get the function name - if (is()) { - name = m_current.to_string(); - width = name.size(); - externName = name; - } else if (is() && isExtern) { - // External functions can have the capacity of having 2 separate - // names. This can be useful for things such as accessing - // external functions that contians special characters. - // - // example: - // extern fn "hello.world$woah" as my_fn() ... - // - // ========================================= - // - // We get a substring from the first and last - // characters. This is because string literals - // contains '"' inside them. - auto s = m_current.to_string(); - externName = s.substr(1, s.size() - 2); - next(); - consume("'as' keyword"); - dbg = m_current.get_pos(); - name = assert_tok("an identifier").to_string(); - width = name.size(); - } else { - std::string e = isExtern ? "Expected an identifier or a string constant but got " - "'%s' while parsing an extern function declaration" : - "Expected an identifier but got '%s' while parsing a " - "function declaration"; - createError(FMT(e.c_str(), m_current.to_string().c_str())); - } - } - next(); - // Create a new instance of a node - auto privacy = Syntax::Statement::Privacy::fromInt(isPublic); - // Check for generic expressions - std::vector generics; - if (is()) { - isGeneric = true; - if (isLambda) { createError("Cant define a lambda with generics"); } - generics = parseGenericParams(); - width = (m_current.get_pos().second - dbg.second); - } - assert_tok("'('"); - int argumentCount = 0; - bool isVarArg = false; - std::vector arguments; - while (true) { - auto pk = peek(); - if (is(pk)) { break; } - next(); - if (isExtern && isTypeValid() && (!is(peek()))) { - throwIfNotType(); - auto type = parseType(); - auto arg = new Syntax::Expression::Param(FMT("$extern-arg-%i", argumentCount), type); - if (is()) { - auto expr = parseExpr(false); - arg->setDefaultValue(expr); - next(); - } - arguments.push_back(arg); - } else if (is() && is(peek()) && is(peek(1, true))) { - next(2); - isVarArg = true; - } else { - bool isMutable = false; - if (is()) { - isMutable = true; - next(); - } - auto name = m_current.to_string(); - consume("an identifier"); - consume("':'"); - auto type = parseType(); - if (name == "self" && argumentCount == 0 && (!isStatic) && (!isConstructor) && (m_current_class != nullptr)) { - attributes[Attributes::FIRST_ARG_IS_SELF] = {}; - } else if (name == "self") { - createError("'self' can only be used as the first argument inside a class non-static function!"); - } - auto arg = new Syntax::Expression::Param(name, type); - arg->setMutable(isMutable); - if (is()) { - auto expr = parseExpr(false); - arg->setDefaultValue(expr); - next(); - } - arguments.push_back(arg); - } - argumentCount++; - if (is()) { - if (isVarArg) createError("Variadic arguments should be the last argument!"); - // if (!isExtern) prev(); - } else if (is()) { - prev(); - } else { - createError(FMT("Expected a ',' or a ')' but found '%s' instead", m_current.to_string().c_str())); - } - } - next(); - consume("')'"); - Syntax::Expression::TypeRef* returnType = nullptr; - if (isTypeValid()) { - if (isConstructor) { - createError( - "Contructor can't have return types.", { - .info = "Constructors return type default to the parent's " - "class type!" - } - ); - } - returnType = parseType(); - } else { - auto info = new DBGSourceInfo(m_source_info, m_current.get_pos(), m_current.get_width()); - returnType = new Syntax::Expression::TypeRef(SN_VOID_TYPE, info); - } - if (isConstructor) { // We assume m_current_class is not nullptr - if (is()) { - next(); - if (is()) { - hasSuperArgs = true; - if (!m_current_class->getParent()) { - createError("Cant call super on a class that doesn't extend " - "from another class!"); - } - next(); - assert_tok("'('"); - while (true) { - auto pk = peek(); - if (is(pk)) { break; } - auto expr = parseExpr(false); - superArgs.push_back(expr); - next(); - if (is()) { - } else if (is()) { - prev(); - break; - } else { - createError( - FMT("Expected a ',' or a ')' but found '%s' instead", m_current.to_string().c_str()) - ); - } - } - next(); - consume("')'"); - if (is()) { - next(); - assert_tok("an identifier"); - } - } - while (is()) { - auto name = parseIdentifier(false, false); - if (constructorInitArgs.find(name) != constructorInitArgs.end()) { - createError(FMT("Duplicate constructor init argument '%s'", name->getIdentifier().c_str())); - } - next(); - assert_tok("'('"); - auto expr = parseExpr(false); - constructorInitArgs[name] = expr; - next(); - consume("')'"); - if (is()) { - next(); - assert_tok("an identifier"); - } else if (is()) { - break; - } else { - createError(FMT("Expected a ',' or a '{' but found '%s' instead", m_current.to_string().c_str()) - ); - } - } - } - if (m_current_class->getParent() && !hasSuperArgs) { - createError("Expected a 'super' call for constructors inside a class " - "that extends form a type!"); - } - } - auto info = new DBGSourceInfo(m_source_info, dbg, width); - Syntax::Block* block = nullptr; - std::string llvmCode; - std::vector llvmTypesUsed; - bool hasBlock = false; - if (isExtern) { - // TODO: external functions can have bodies! - assert_tok("';'"); - } else if (is()) { - next(); - if (is()) { - auto number = m_current.to_string(); - if (number != "0") { - createError( - "Expected a '0' for the function body!", { - .info = "Expected a '0' for the function body!", - .note = "The function body must be a '0' for now.", - .help = "You have to set the function body to '0'.\n" - "For example:\n" - "1 | virt fn my_fn() = 0\n" - "2 |" - } - ); - } - if (!isVirtual) { - createError( - "Function body can only be '0' for virtual functions!", { - .info = "Function body can only be '0' for virtual functions!", - .note = "The function body must be a '0' for now.", - .help = "You have to set the function body to '0'.\n" - "For example:\n" - "1 | virt fn my_fn() = 0\n" - "2 |" - } - ); - } - isNotImplemented = true; - hasBlock = true; - block = new Syntax::Block(); - next(); - } else { - createError("Expected a number literal for the function body!"); - } - } else if (is()) { - if (isConstructor) { createError("Constructors cant be declared as extern!"); } - } else { - assert_tok("'{'"); - if (isLLVMFunction) { - auto startPos = m_current.get_pos(); - auto depth = 1; - while (depth != 0) { - next(); - if (is()) { - depth++; - if (is(peek())) { - next(1); - llvmTypesUsed.push_back(parseType()); - depth--; - // TODO: make sure they are in the same line - assert_tok("'}'"); - } - } else if (is()) { - depth--; - } else if (is()) { - createError("Unterminated LLVM function block code!"); - } - } - auto endPos = m_current.get_pos(); - llvmCode = utils::getSubstringByRange(m_source_info->getSource(), startPos, endPos); - llvmCode = llvmCode.substr(1, llvmCode.size() - 1); // Ignore speech marks - } else { - block = parseBlock(); - } - hasBlock = true; - assert_tok("'}'"); - } - if (!hasBlock && isLLVMFunction) { createError("LLVM defined functions must have a body!"); } - if (isOperator && ((arguments.size() == 0) || ((arguments.size() == 1) - && attributes.count(Attributes::FIRST_ARG_IS_SELF)))) { - // Transform to unary operators for +, - (TODO: some more) - auto op = services::OperatorService::operatorID(name); - OperatorService::OperatorType newType; - bool valid = true; - switch (op) { - case services::OperatorService::OperatorType::MINUS: { - newType = OperatorService::OperatorType::UMINUS; - break; - } - case services::OperatorService::OperatorType::PLUS: { - newType = OperatorService::OperatorType::UPLUS; - break; - } - default: valid = false; - } - if (valid) { name = OperatorService::getOperatorMangle(newType); } - } - FunctionDef* fn = nullptr; - if (isConstructor) { - assert(hasBlock); - isMutable = true; - auto constructor = Syntax::N(hasSuperArgs, block, name); - constructor->setSuperArgs(superArgs); - constructor->setInitArgs(constructorInitArgs); - fn = utils::cast(constructor); - } else if (isExtern) { - fn = Syntax::N(externName, name); - } else if (isLLVMFunction) { - fn = Syntax::N(llvmCode, llvmTypesUsed, name); - } else if (hasBlock) { - fn = Syntax::N(block, name); - } else { - fn = Syntax::N(name); - } - for (auto[n, a] : attributes) { fn->addAttribute(n, a); } - if (isUnsafe) fn->addAttribute(Attributes::UNSAFE); - fn->setVirtual(isVirtual); - fn->setVariadic(isVarArg); - fn->setPrivacy(privacy); - fn->setArgs(arguments); - fn->setDBGInfo(info); - fn->setRetType(returnType); - if (isGeneric) fn->setGenerics(generics); - if (isNotImplemented) fn->addAttribute(Attributes::NOT_IMPLEMENTED); - fn->setStatic(isStatic); - fn->isMutable(isMutable); - fn->setComment(comment); - return fn; -} - -} // namespace snowball::parser diff --git a/src/parser/parseFunctionCall.cc b/src/parser/parseFunctionCall.cc deleted file mode 100644 index ef772c9c..00000000 --- a/src/parser/parseFunctionCall.cc +++ /dev/null @@ -1,42 +0,0 @@ - - -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "./Parser.h" - -#include - -using namespace snowball::Syntax::Expression; - -namespace snowball::parser { - -FunctionCall* -Parser::parseFunctionCall(Syntax::Expression::Base* callee, TokenType terminator, std::string terminatorString) { - assert(callee != nullptr); - std::vector arguments; - while (true) { - auto pk = peek(); - if (terminator == pk.type) { break; } - auto val = parseExpr(false); - arguments.push_back(val); - pk = peek(); - if (is(pk) || terminator == pk.type) { - if (is(pk)) next(); - continue; - } else { - next(); - createError( - FMT("Expected a ',' or a '%s' but found '%s' instead", terminatorString.c_str(), pk.to_string().c_str()) - ); - } - } - next(); // Consume "(" - auto call = Syntax::N(callee, arguments); - //dbg->width += 2; - // TODO: dbg info should start at the "(", maybe? - call->setSourceInfo(m_source_info); - call->setDBGInfo(callee->getDBGInfo()); - return call; -} - -} // namespace snowball::parser diff --git a/src/parser/parseGenericExpr.cc b/src/parser/parseGenericExpr.cc deleted file mode 100644 index 31301421..00000000 --- a/src/parser/parseGenericExpr.cc +++ /dev/null @@ -1,44 +0,0 @@ -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "./Parser.h" - -#include - -using namespace snowball::Syntax::Expression; - -namespace snowball::parser { - -std::vector Parser::parseGenericExpr() { - assert(is()); - // If it's not a '?' it means that we 100% know that it's a generic expression - if (is(peek())) next(); // Current token: OP_LT - std::vector types; - while (true) { - next(); - if (is()) { - createError("Found an unexpected EOF while parsing generic expression"); - } else if (isTypeValid()) { - // Generate a new parameter instance - auto ty = parseType(); - types.push_back(ty); - if (is()) { - next(); - break; - } else if (is()) { - continue; - } - assert_tok("a comma or a >"); - } else if (is()) { - next(); - break; - } else { - createError( - FMT("Expected a vaid generic expression but got '%s'", m_current.to_string().c_str()), - {.info = "Not a valid generic expression"} - ); - } - } - return types; -} - -} // namespace snowball::parser \ No newline at end of file diff --git a/src/parser/parseGenericParams.cc b/src/parser/parseGenericParams.cc deleted file mode 100644 index b87d8022..00000000 --- a/src/parser/parseGenericParams.cc +++ /dev/null @@ -1,64 +0,0 @@ - - -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "./Parser.h" - -#include - -using namespace snowball::Syntax::Expression; - -namespace snowball::parser { - -std::vector Parser::parseGenericParams() { - assert(is()); - std::vector params; - while (true) { - next(); - if (is()) { - createError("Found an unexpected EOF while " - "parsing generic declaration"); - } else if (is()) { - // Get the current name for the parameter - auto name = m_current.to_string(); - // Define the default type. The default - // value is a null pointer, meaning that - // there are no default parameters defined. - TypeRef* default_ty = nullptr; - // Statements to be executed in order to perform - // checks for the selected generics. - WhereClause* whereClause = nullptr; - // Consume identifier - next(); - // Parse [where_clause] - if (is()) whereClause = parseWhereClause(); - // "=" [default_type] - if (is()) { - next(); - default_ty = parseType(); - } - // Generate a new parameter instance - auto param = new Param(name, default_ty, Param::Generic); - param->setWhereClause(whereClause); - params.push_back(param); - if (is()) { - next(); - break; - } else if (is() && is(peek(0, true))) { - continue; - } - assert_tok("a ',', ':' or a '>'"); - } else if (is()) { - next(); - break; - } else { - createError( - FMT("Expected a vaid generic declaration but got '%s'", m_current.to_string().c_str()), - {.info = "Unexpected token here"} - ); - } - } - return params; -} - -} // namespace snowball::parser diff --git a/src/parser/parseGlobal.cc b/src/parser/parseGlobal.cc deleted file mode 100644 index 9a7c8981..00000000 --- a/src/parser/parseGlobal.cc +++ /dev/null @@ -1,120 +0,0 @@ - -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "./Parser.h" - -#include - -using namespace snowball::Syntax::Expression; - -namespace snowball::parser { - -Parser::NodeVec Parser::parseGlobal(TokenType terminator) { - bool keep_parsing = true; - std::vector global; - while (keep_parsing) { - if (terminator == m_current.type) { - keep_parsing = false; - } else { - switch (m_current.type) { - case TokenType::_EOF: - // Unexpected because it shoud've been caught by the conditional above - createError("unexpected end of file"); - case TokenType::SYM_SEMI_COLLON: break; - case TokenType::KWORD_MACRO: { - global.push_back(parseMacro()); - break; - } - case TokenType::KWORD_PUBLIC: - case TokenType::KWORD_PRIVATE: { - auto pk = peek(); - if (!is(pk) && !is(pk) && !is(pk) - && !is(pk) && - !is(pk) && !is(pk) && !is(pk) && - !is(pk) && !is(pk) && !is(pk) && - !is(pk)) { - createError("expected keyword \"func\", \"static\", \"unsafe\", \"class\", " - "\"let\", \"const\", \"enum\" " - "or " - "\"external\" after public/private declaration"); - } - break; - } - case TokenType::SYM_AT: { - parseAttributes(); - break; - } - case TokenType::KWORD_EXTERN: { - auto pk = peek(); - if (!is(pk) && !is(pk) && !is(pk)) { - createError("expected 'func' or 'const' keyword after an " - "external symbol declaration"); - } - break; - } - case TokenType::KWORD_STATIC: { - auto pk = peek(); - if (!is(pk) && !is(pk)) { - next(); - createError("expected 'func' or 'unsafe' keyword after a " - "static function declaration"); - } - break; - } - case TokenType::KWORD_UNSAFE: { - auto pk = peek(); - if (!is(pk)) { - createError("expected 'func' keyword after an " - "unsafe function declaration"); - } - break; - } - case TokenType::KWORD_NAMESPACE: { - global.push_back(parseNamespace()); - break; - } - case TokenType::KWORD_ENUM: { - global.push_back(parseEnum()); - break; - } - case TokenType::KWORD_STRUCT: { - global.push_back(parseStructure()); - break; - } - case TokenType::KWORD_VAR: { - global.push_back(parseVariable()); - break; - } - case TokenType::KWORD_CONST: { - global.push_back(parseConstant()); - break; - } - case TokenType::KWORD_FUNC: { - global.push_back(parseFunction()); - break; - } - case TokenType::KWORD_CLASS: - case TokenType::KWORD_INTER: { - global.push_back(parseClass()); - break; - } - case TokenType::KWORD_IMPORT: { - global.push_back(parseImportStatement()); - break; - } - case TokenType::KWORD_TYPEDEF: { - assertNoAttributes("type alias"); - global.push_back(parseTypeAlias()); - break; - } - default: - createError(FMT("Unexpected token ('%s') found", m_current.to_string().c_str())); - } - } - if (keep_parsing && !is(m_current)) next(); - } - assertNoAttributes("after global or namespace declaration"); - return global; -} - -} // namespace snowball::parser diff --git a/src/parser/parseIdentifier.cc b/src/parser/parseIdentifier.cc deleted file mode 100644 index d12dae7e..00000000 --- a/src/parser/parseIdentifier.cc +++ /dev/null @@ -1,39 +0,0 @@ -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "./Parser.h" - -#include - -using namespace snowball::Syntax::Expression; - -namespace snowball::parser { - -Syntax::Expression::Identifier* Parser::parseIdentifier(bool isKnownType, bool allowGenerics) { - if (!is()) - createError( - "Expected an identifier but got '" + m_current.to_string() + "'", {.info = "Not a valid identifier"} - ); - auto dbg = DBGSourceInfo::fromToken(m_source_info, m_current); - auto genericContainsQuestion = is(peek(1, true)); - if (allowGenerics && (is(peek()) && (isKnownType || genericContainsQuestion))) { - if (genericContainsQuestion && isKnownType) - createError( - "Expected a valid generic expression but got '?'", {.info = "Not a valid generic expression"} - ); - auto name = m_current.to_string(); - next(); - auto generics = parseGenericExpr(); - auto width = m_current.get_pos().second - dbg->pos.second; - dbg->width = width; - prev(); - auto i = Syntax::N(name, generics); - i->setDBGInfo(dbg); - return i; - } else { - auto i = Syntax::N(m_current.to_string()); - i->setDBGInfo(dbg); - return i; - } -} - -} // namespace snowball::parser \ No newline at end of file diff --git a/src/parser/parseImportStatement.cc b/src/parser/parseImportStatement.cc deleted file mode 100644 index ac06f5c6..00000000 --- a/src/parser/parseImportStatement.cc +++ /dev/null @@ -1,80 +0,0 @@ - -#include "Parser.h" - -#include - -namespace snowball { -namespace parser { - -Syntax::Statement::ImportStmt* Parser::parseImportStatement() { - assert(is()); - auto dbg = DBGSourceInfo::fromToken(m_source_info, m_current); - next(); - auto attributes = verifyAttributes([&](std::string attr) { - if (attr == "use_macro" || attr == "use_macros") { return Attributes::MACROS; } - return Attributes::INVALID; - }); - std::string package = assert_tok("an identifier for package reference").to_string(); - next(); - std::vector paths; - std::string exportName; - std::vector> vars; - if (is()) { - next(); - paths.push_back(assert_tok("an identifier").to_string()); - next(); - if (is()) while (is()) { - next(); - if (is()) { - paths.push_back(m_current.to_string()); - } else if (is() && is(peek())) { - paths.push_back(".."); - } else if (is()) { - // var imports - next(); - while (!is()) { - if (is()) { - std::string name = m_current.to_string(); - std::string alias = name; - next(); - if (is()) { - next(); - alias = assert_tok("an identifier for variable alias").to_string(); - next(); - } - vars.push_back({name, alias}); - if (is()) { - next(); - } else { - break; - } - } else { - createError("an identifier for variable import"); - } - } - consume("'}'"); - break; - } else { - prev(); - break; - } - next(); - } - } - if (is()) { - next(); - exportName = assert_tok("an identifier for export name").to_string(); - next(); - } - // TODO: handle all import types - auto width = m_current.get_pos().second - dbg->pos.second; - dbg->width = width; - prev(); - auto import = Syntax::N(paths, package, vars, exportName); - import->setDBGInfo(dbg); - for (auto[n, a] : attributes) { import->addAttribute(n, a); } - return import; -} - -} // namespace parser -} // namespace snowball diff --git a/src/parser/parseLoopControl.cc b/src/parser/parseLoopControl.cc deleted file mode 100644 index 8c14d546..00000000 --- a/src/parser/parseLoopControl.cc +++ /dev/null @@ -1,32 +0,0 @@ - -#include "Parser.h" - -#include - -namespace snowball { -namespace parser { - -using namespace Syntax; - -Syntax::Statement::LoopFlow* Parser::parseLoopControl() { - assert(is() || is()); - Statement::LoopFlow::FlowType type; - switch (m_current.type) { - case TokenType::KWORD_BREAK: type = Statement::LoopFlow::FlowType::Break; break; - case TokenType::KWORD_CONTINUE: type = Statement::LoopFlow::FlowType::Continue; break; - default: assert(false); - } - if (!m_inside_loop) { - createError("Cannot use loop control outside of a loop!", { - .info = "Not inside a loop", - .note = "You can only use loop control statements inside of a loop" - }); - } - auto dbg = DBGSourceInfo::fromToken(m_source_info, m_current); - auto flow = N(type); - flow->setDBGInfo(dbg); - return flow; -} - -} // namespace parser -} // namespace snowball diff --git a/src/parser/parseMacro.cc b/src/parser/parseMacro.cc deleted file mode 100644 index d669bae7..00000000 --- a/src/parser/parseMacro.cc +++ /dev/null @@ -1,93 +0,0 @@ - -#include "Parser.h" - -#include - -namespace snowball { -namespace parser { - -Syntax::Macro* Parser::parseMacro() { - assert(is()); - auto comment = parseDocstring(m_current.getComment()); - next(); - // TODO: expression macro: 'macro foo() = 1 + 1' - auto dbg = DBGSourceInfo::fromToken(m_source_info, m_current); - bool isStatementMacro = true; - auto attributes = verifyAttributes([&](std::string attr) { - if (attr == "export") { return Attributes::EXPORT; } - return Attributes::INVALID; - }); - auto name = assert_tok("an identifier for macro name").to_string(); - next(); - consume("'('"); - std::vector> args; - while (is()) { - auto name = m_current.to_string(); - next(); - consume("':'"); - auto type = m_current.to_string(); - Syntax::Macro::ArguementType argType; - if (type == "expr") { - argType = Syntax::Macro::ArguementType::EXPRESSION; - } else if (type == "type") { - argType = Syntax::Macro::ArguementType::TYPE; - } else if (type == "const") { - argType = Syntax::Macro::ArguementType::CONSTANT; - next(); - if (is()) { - next(); - auto val = assert_tok("an identifier for constant value").to_string(); - next(); - assert_tok("']'"); - if (val == "str") { - argType = Syntax::Macro::ArguementType::CONSTANT_STRING; - } else if (val == "num") { - argType = Syntax::Macro::ArguementType::CONSTANT_NUMBER; - } else if (val == "chr") { - argType = Syntax::Macro::ArguementType::CONSTANT_CHAR; - } else { - createError("Expected 'str', 'num', or 'chr' for constant type"); - } - } - } else if (type == "stmt") { - argType = Syntax::Macro::ArguementType::STATEMENT; - } else { - createError("Expected 'expr' or 'stmt' for macro arguement type"); - } - Syntax::Node* defaultArg = nullptr; - if (is(peek())) { - next(); - defaultArg = parseStatement(peek()); - } - // TODO: check for existant args - args.push_back(std::make_tuple(name, argType, defaultArg)); - next(); - if (is()) { - next(); - } else { - break; - } - } - consume("')'"); - if (is()) { - isStatementMacro = false; - auto expr = parseExpr(false); - auto macro = Syntax::N( - name, args, Syntax::N(std::vector {expr}), isStatementMacro - ); - macro->setDBGInfo(dbg); - for (auto[n, a] : attributes) { macro->addAttribute(n, a); } - macro->setComment(comment); - return macro; - } - assert_tok("'{'"); - auto body = parseBlock(); - auto macro = Syntax::N(name, args, body, isStatementMacro); - macro->setDBGInfo(dbg); - for (auto[n, a] : attributes) { macro->addAttribute(n, a); } - macro->setComment(comment); - return macro; -} - -} // namespace parser -} // namespace snowball diff --git a/src/parser/parseNamespace.cc b/src/parser/parseNamespace.cc deleted file mode 100644 index b000c1bf..00000000 --- a/src/parser/parseNamespace.cc +++ /dev/null @@ -1,29 +0,0 @@ - -#include "Parser.h" -#include - -namespace snowball { -namespace parser { - -Syntax::Statement::Namespace* Parser::parseNamespace() { - assert(is()); - auto dbg = DBGSourceInfo::fromToken(m_source_info, m_current); - auto comment = parseDocstring(m_current.getComment()); - auto attributes = verifyAttributes([&](std::string attr) { - return Attributes::INVALID; - }); - next(); - auto name = assert_tok("an identifier for namespace").to_string(); - next(); - consume("'{'"); - auto body = parseGlobal(TokenType::BRACKET_RCURLY); - assert_tok("'}'"); - auto ns = Syntax::N(name, body); - ns->setDBGInfo(dbg); - for (auto[n, a] : attributes) { ns->addAttribute(n, a); } - ns->setComment(comment); - return ns; -} - -} // namespace parser -} // namespace snowball diff --git a/src/parser/parseReturn.cc b/src/parser/parseReturn.cc deleted file mode 100644 index e9499a0b..00000000 --- a/src/parser/parseReturn.cc +++ /dev/null @@ -1,21 +0,0 @@ - -#include "../ast/types/PrimitiveTypes.h" -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "./Parser.h" - -#include - -using namespace snowball::Syntax::Statement; -namespace snowball::parser { - -Syntax::Statement::Return* Parser::parseReturn() { - assert(is()); - auto info = DBGSourceInfo::fromToken(m_source_info, m_current); - Syntax::Expression::Base* expr = nullptr; - if (!is(peek())) expr = parseExpr(false); - auto node = Syntax::N(expr); - node->setDBGInfo(info); - return node; -} -} // namespace snowball::parser diff --git a/src/parser/parseStatement.cc b/src/parser/parseStatement.cc deleted file mode 100644 index f1f7e5f6..00000000 --- a/src/parser/parseStatement.cc +++ /dev/null @@ -1,114 +0,0 @@ - -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "./Parser.h" - -#include - -namespace snowball::parser { - -Syntax::Node* Parser::parseStatement(Token pk) { - switch (pk.type) { - case TokenType::_EOF: { - next(); // eat EOF - createError("Found an unexpected EOF while parsing a block"); - } break; - case TokenType::KWORD_UNSAFE: { - assertNoAttributes("unsafe block"); - next(1); - assert_tok("'{' expected after 'unsafe' keyword"); - auto b = parseBlock(); - b->addAttribute(Attributes::UNSAFE); - return b; - } break; - case TokenType::BRACKET_LCURLY: { - next(); - return parseBlock(); - break; - } - case TokenType::KWORD_CONST: { - assertNoAttributes("constant declaration"); - next(); - return parseConstant(); - break; - } - case TokenType::SYM_SEMI_COLLON: { - next(); - break; - } - case TokenType::KWORD_BREAK: - case TokenType::KWORD_CONTINUE: { - assertNoAttributes("loop control statement"); - next(); - return parseLoopControl(); - break; - } - case TokenType::KWORD_SWITCH: - case TokenType::KWORD_CASE: { - assertNoAttributes("case statement"); - next(); - return parseSwitch(); - break; - } - case TokenType::KWORD_THROW: { - assertNoAttributes("throw statement"); - next(); - return parseThrow(); - break; - } - case TokenType::KWORD_VAR: { - assertNoAttributes("variable declaration"); - next(); - return parseVariable(); - break; - } - // TODO: can const be declared at block level in rust? - case TokenType::KWORD_FOR: { - assertNoAttributes("for loop"); - next(); - return parseForLoop(); - break; - } - case TokenType::KWORD_WHILE: - case TokenType::KWORD_DO: { - assertNoAttributes("while loop"); - next(); - return parseWhile(); - break; - } - case TokenType::KWORD_TYPEDEF: { - assertNoAttributes("type alias"); - next(); - return parseTypeAlias(); - break; - } - case TokenType::KWORD_IF: { - assertNoAttributes("if statement"); - next(); - return parseConditional(); - break; - } - case TokenType::KWORD_TRY: { - assertNoAttributes("try-catch statement"); - next(); - return parseTryCatch(); - break; - } - case TokenType::KWORD_RETURN: { - assertNoAttributes("return statement"); - next(); - return parseReturn(); - break; - } - default: { - assertNoAttributes("expression statement"); - auto expr = parseExpr(); - if (auto x = utils::cast(expr)) { x->asStatement = true; } - return expr; - } - } - assert(false); - return nullptr; // to remove warnings -} - -} // namespace snowball::parser diff --git a/src/parser/parseStructure.cc b/src/parser/parseStructure.cc deleted file mode 100644 index 62121a18..00000000 --- a/src/parser/parseStructure.cc +++ /dev/null @@ -1,78 +0,0 @@ - -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "../services/OperatorService.h" -#include "./Parser.h" - -#include - -namespace snowball::parser { - -Syntax::Statement::DefinedTypeDef* Parser::parseStructure() { - assert(is()); - auto comment = parseDocstring(m_current.getComment()); - next(); // East "struct" - bool isPublic = false; - if (is(peek(-3, true))) { - isPublic = is(peek(-3, true)); - } - auto attributes = verifyAttributes([&](std::string attr) { - return Attributes::INVALID; - }); - auto name = assert_tok("structure identifier").to_string(); - auto dbg = DBGSourceInfo::fromToken(m_source_info, m_current); - Syntax::Statement::GenericContainer<>::GenericList generics; - if (is(peek())) { - next(); - generics = parseGenericParams(); - prev(); - } - next(); - assert_tok("'{'"); - next(); - auto cls = Syntax::N( - name, nullptr, Syntax::Statement::Privacy::fromInt(isPublic), Syntax::Statement::DefinedTypeDef::Type::STRUCT - ); - cls->setGenerics(generics); - cls->setDBGInfo(dbg); - bool keepParsing = true; - while (keepParsing) { - switch (m_current.type) { - case TokenType::KWORD_PUBLIC: - case TokenType::KWORD_PRIVATE: { - createError("Cannot declare a member as public or private inside a structure", { - .note = "Structure members are always public" - }); - break; - } - case TokenType::KWORD_VAR: { - auto member = parseVariable(); - consume("';'"); - member->setPrivacy(Syntax::Statement::Privacy::PUBLIC); - if (member->getValue()) { - createError("Cannot declare a member with a value inside a structure", { - .note = "Structure members are always public\nAlso, this may be available in the future!", - }); - } - cls->addVariable(member); - break; - } - case TokenType::BRACKET_RCURLY: { - keepParsing = false; - break; - } - default: { - createError( - FMT("Expected a valid member declaration but found '%s'", m_current.to_string().c_str()) - ); - break; - } - } - } - assert_tok("'}'"); - cls->setComment(comment); - for (auto attr : attributes) cls->addAttribute(attr.first, attr.second); - return cls; -} - -} // namespace snowball::parser diff --git a/src/parser/parseSwitch.cc b/src/parser/parseSwitch.cc deleted file mode 100644 index 4965beee..00000000 --- a/src/parser/parseSwitch.cc +++ /dev/null @@ -1,118 +0,0 @@ - -#include "../ast/types/PrimitiveTypes.h" -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "./Parser.h" - -#include - -using namespace snowball::Syntax::Statement; -using namespace snowball::Syntax::Expression; - -namespace snowball::parser { - -Syntax::Statement::Switch* Parser::parseSwitch() { - assert(is() || is()); - auto cStyleSwitch = is(); - auto info = DBGSourceInfo::fromToken(m_source_info, m_current); - Syntax::Expression::Base* expr = parseExpr(); - assert(expr); - next(); - consume("'{' expected after 'case' expression"); - std::vector cases; - while (!is()) { - auto pk = m_current; - switch (pk.type) { - case TokenType::IDENTIFIER: { - if (!cStyleSwitch) { - auto id = m_current.to_string(); - next(); - bool variadic = false; - std::vector args; - if (is()) { - next(); - while (!is()) { - if (is() && is(peek()) && is(peek(1, true))) { - variadic = true; - next(2); - break; - } else { - assert_tok("identifier expected as case argument"); - args.push_back(m_current.to_string()); - next(); - } - if (is()) { - next(); - } else if (!is()) { - createError("expected ',' or ')' after case argument"); - } else break; - } - assert_tok("')' expected after case arguments"); - next(); - } - assert_tok("'=>' expected after case name"); - auto body = parseBlockOrStmt(); - cases.push_back(Syntax::Statement::Switch::CaseBlock{ - .expression = {nullptr, id}, - .args = args, - .isDefault = false, - .isVariadic = variadic, - .block = body, - }); - pk = peek(); - if (!is(pk)) { - next(); - consume("',' expected after case block"); - } else next(); - break; - } - __attribute__((fallthrough)); - } - case TokenType::KWORD_DEFAULT: { - next(); - assert_tok("'=>' expected after 'default' keyword"); - auto body = parseBlockOrStmt(); - cases.push_back(Syntax::Statement::Switch::CaseBlock{ - .expression = {nullptr, ""}, - .args = {}, - .isDefault = true, - .isVariadic = false, - .block = body, - }); - next(); - if (is()) { - next(); - } else if (!is()) { - createError("expected ',' or '}' after case block"); - } - } break; - default: { - if (cStyleSwitch) { - prev(); - auto stmt = parseExpr(false); - next(); - auto body = parseBlockOrStmt(); - cases.push_back(Syntax::Statement::Switch::CaseBlock{ - .expression = {stmt, ""}, - .args = {}, - .isDefault = false, - .isVariadic = false, - .block = body, - }); - next(); - if (is()) { - next(); - } else if (!is()) { - createError("expected ',' or '}' after case block"); - } else next(); - break; - } - createError("expected 'case name' or 'default' keyword"); - } break; - } - } - auto node = Syntax::N(expr, cases, cStyleSwitch); - node->setDBGInfo(info); - return node; -} -} // namespace snowball::parser diff --git a/src/parser/parseThrow.cc b/src/parser/parseThrow.cc deleted file mode 100644 index ba5a2ede..00000000 --- a/src/parser/parseThrow.cc +++ /dev/null @@ -1,20 +0,0 @@ - -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "../services/OperatorService.h" -#include "./Parser.h" - -#include - -namespace snowball::parser { - -Syntax::Statement::Raise* Parser::parseThrow() { - assert(is()); - auto dbg = DBGSourceInfo::fromToken(m_source_info, m_current); - auto expr = parseExpr(false); - auto raise = Syntax::N(expr); - raise->setDBGInfo(dbg); - return raise; -} - -} // namespace snowball::parser diff --git a/src/parser/parseTryCatch.cc b/src/parser/parseTryCatch.cc deleted file mode 100644 index aaf19275..00000000 --- a/src/parser/parseTryCatch.cc +++ /dev/null @@ -1,36 +0,0 @@ - -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "../services/OperatorService.h" -#include "./Parser.h" - -#include - -namespace snowball::parser { - -Syntax::Statement::TryCatch* Parser::parseTryCatch() { - assert(is()); - auto dbg = DBGSourceInfo::fromToken(m_source_info, m_current); - next(); - assert_tok("a left curly brace '{' to start the try block"); - auto tryBlock = parseBlock(); - next(); // We know it's a right curly brace, but we don't need to check it - std::vector catchBlocks; - assert_tok("a catch block"); - while (is()) { - next(); - consume("a left parenthesis '(' to start the catch block"); - auto name = assert_tok("an identifier for the exception variable").to_string(); - next(); - consume("a collon ':' to separate the exception variable from the type"); - auto type = parseType(); - consume("a right parenthesis ')' to end the catch block header"); - auto block = parseBlock(); - catchBlocks.push_back(new Syntax::Statement::TryCatch::CatchBlock(type, name, block)); - } - auto tryCatch = new Syntax::Statement::TryCatch(tryBlock, catchBlocks); - tryCatch->setDBGInfo(dbg); - return tryCatch; -} - -} // namespace snowball::parser diff --git a/src/parser/parseType.cc b/src/parser/parseType.cc deleted file mode 100644 index 7c6f5507..00000000 --- a/src/parser/parseType.cc +++ /dev/null @@ -1,122 +0,0 @@ - - -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "./Parser.h" - -#include - -using namespace snowball::Syntax::Expression; - -namespace snowball::parser { - -TypeRef* Parser::parseType() { - throwIfNotType(); - assert(is() || is() || is() || - is() || is() || is() || - is()); - auto pos = m_current.get_pos(); - auto dbg = new DBGSourceInfo(m_source_info, pos, m_current.get_pos().second - pos.second); - if (is()) { - next(); - assert_tok("'('"); - auto expr = parseExpr(false); - next(); - consume("')'"); - return Syntax::N(expr, dbg); - } else if (is()) { - std::vector fnArgs; - next(); - assert_tok("'('"); - while (!is()) { - next(); - if (is()) break; - auto arg = parseType(); - fnArgs.push_back(arg); - if (is()) { - } else if (is()) { - } else { - createError("Expected ')' or ','"); - } - } - consume("')'"); - consume("'=>'"); - auto retType = parseType(); - return Syntax::N(fnArgs, retType, dbg); - } else if (is()) { - std::vector generics; - while (true) { - next(); - if (is()) break; - auto arg = parseType(); - generics.push_back(arg); - if (is()) { - } else if (is()) { - break; - } else { - createError("Expected ')' or ','"); - } - } - next(); - auto ty = Syntax::N(generics, dbg); - return ty; - } - if (is()) { - next(); - if (is()) { - next(); - return Syntax::N(parseType(), false, dbg); - } else if (is()) { - next(); - return Syntax::N(parseType(), true, dbg); - } else { - createError( - "Expected 'const' or 'mut' after '*' (pointer type specifier)", { - .note = "If you want to use '*' as a multiplication operator, use parentheses around the " - "expression", - .help = "check the documentation for more information " - "(https://snowball-lang.gitbook.io/docs/language-reference/types/pointer-types)", - } - ); - } - } else if (is()) { // we treat op and as 2 bit ands - next(); - auto isMutable = is(); - if (isMutable) next(); - auto ref = Syntax::N(parseType(), dbg); - ref->setMutable(isMutable); - return ref; - } else if (is()) { - next(); - auto isMutable = is(); - if (isMutable) next(); - auto ref = Syntax::N(parseType(), dbg); - ref->setMutable(isMutable); - return ref; - } - bool isMutable = false; - auto ident = parseIdentifier(true); - Base* ast = ident; - auto name = ident->getIdentifier(); - auto id = ident->getIdentifier(); - auto g = utils::cast(ast); - auto generics = (g != nullptr) ? g->getGenerics() : std::vector {}; - next(); - while (is()) { - next(); - auto i = parseIdentifier(true); - name += "::" + i->getIdentifier(); - id += "." + i->getIdentifier(); - ast = Syntax::N(ast, i, true); - ast->setDBGInfo(i->getDBGInfo()); - auto g = utils::cast(i); - generics = (g != nullptr) ? g->getGenerics() : std::vector {}; - next(); - } - auto t = Syntax::TR(ast, name, dbg, id); - t->setGenerics(generics); - t->setMutable(isMutable); - return t; -} - -} // namespace snowball::parser \ No newline at end of file diff --git a/src/parser/parseTypeAlias.cc b/src/parser/parseTypeAlias.cc deleted file mode 100644 index 3c4835a7..00000000 --- a/src/parser/parseTypeAlias.cc +++ /dev/null @@ -1,39 +0,0 @@ - -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "../services/OperatorService.h" -#include "./Parser.h" - -#include - -namespace snowball::parser { - -Syntax::Statement::TypeAlias* Parser::parseTypeAlias() { - assert(is()); - auto comment = parseDocstring(m_current.getComment()); - next(); // East "type" - bool isPublic = false; - bool isGeneric = false; - if (is(peek(-3, true))) { - isPublic = is(peek(-3, true)); - } - auto name = assert_tok("type identifier").to_string(); - auto dbg = DBGSourceInfo::fromToken(m_source_info, m_current); - Syntax::Statement::GenericContainer<>::GenericList generics; - next(); - if (is()) { - isGeneric = true; - generics = parseGenericParams(); - } - consume("'='"); - auto type = parseType(); - auto privacy = Syntax::Statement::Privacy::fromInt(isPublic); - auto node = Syntax::N(name, type); - node->setPrivacy(privacy); - node->setDBGInfo(dbg); - node->setComment(comment); - if (isGeneric) node->setGenerics(generics); - return node; -} - -} // namespace snowball::parser diff --git a/src/parser/parseVariable.cc b/src/parser/parseVariable.cc deleted file mode 100644 index f66a3c88..00000000 --- a/src/parser/parseVariable.cc +++ /dev/null @@ -1,62 +0,0 @@ - -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "./Parser.h" - -#include - -namespace snowball::parser { - -Syntax::Statement::VariableDecl* Parser::parseVariable() { - assert(is()); - auto comment = parseDocstring(m_current.getComment()); - next(); - auto attributes = verifyAttributes([&](std::string attr) { - return Attributes::INVALID; - }); - bool isPublic = false; - if (is(peek(-3, true))) { - isPublic = is(peek(-3, true)); - } - bool isMutable = false; - if (is()) { - isMutable = true; - next(); - } - auto token = assert_tok("an identifier"); - next(); // consume identifier - auto name = token.to_string(); - // TODO: actually find type definition - Syntax::Expression::TypeRef* typeDef = nullptr; - if (is()) { - next(); - typeDef = parseType(); - } - Syntax::Expression::Base* value = nullptr; - if (is()) { - value = parseExpr(false); - if (is(peek(0, true))) next(); - } else if (!is()) { - createError( - "Invalid variable declaration syntax!", {.info = "Expected '=' for a variable declaration"} - ); - } else if (typeDef == nullptr) { - createError( - "Undeclared type for uninitialized variable declaration!", { - .info = "Variable declarations must have type definition if " - "it's not " - "initialized" - } - ); - } - auto v = Syntax::N(name, value, isMutable); - v->setDefinedType(typeDef); - v->setPrivacy(Syntax::Statement::Privacy::fromInt(isPublic)); - v->setComment(comment); - auto info = new DBGSourceInfo(m_source_info, token.get_pos(), token.get_width()); - v->setDBGInfo(info); - for (auto[n, a] : attributes) { v->addAttribute(n, a); } - return v; // to remove warnings -} - -} // namespace snowball::parser diff --git a/src/parser/parseWhereClause.cc b/src/parser/parseWhereClause.cc deleted file mode 100644 index 314e0d75..00000000 --- a/src/parser/parseWhereClause.cc +++ /dev/null @@ -1,22 +0,0 @@ - -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "./Parser.h" - -#include - -using namespace snowball::Syntax::Expression; - -namespace snowball::parser { - -WhereClause* Parser::parseWhereClause() { - assert(is()); - WhereClause::ChecksVectorType tests; - do { - next(); - tests.push_back(parseType()); - } while (is()); - return new WhereClause(tests); -} - -} // namespace snowball::parser diff --git a/src/parser/parseWhile.cc b/src/parser/parseWhile.cc deleted file mode 100644 index e2e92f13..00000000 --- a/src/parser/parseWhile.cc +++ /dev/null @@ -1,41 +0,0 @@ - - -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "./Parser.h" - -#include - -using namespace snowball::Syntax::Statement; - -namespace snowball::parser { - -WhileLoop* Parser::parseWhile() { - assert(is() || is()); - auto token = m_current; - bool isDoWhile = is(token); - Syntax::Expression::Base* expr = nullptr; - Syntax::Block* block = nullptr; - bool backupLoop = m_inside_loop; - m_inside_loop = true; - if (!isDoWhile) { - expr = parseExpr(false); - next(); - block = parseBlock(); - } else { - next(); - block = parseBlock(); - next(); - assert_tok("'while'"); - expr = parseExpr(false); - next(); - assert_tok("';'"); - } - m_inside_loop = backupLoop; - auto v = Syntax::N(expr, block, isDoWhile); - auto info = DBGSourceInfo::fromToken(m_source_info, token); - v->setDBGInfo(info); - return v; -} - -} // namespace snowball::parser \ No newline at end of file diff --git a/src/pm/Manager.cc b/src/pm/Manager.cc deleted file mode 100644 index 052637d0..00000000 --- a/src/pm/Manager.cc +++ /dev/null @@ -1,188 +0,0 @@ - -#include "Manager.h" -#include "curl/curl.h" - -namespace fs = std::filesystem; - -namespace snowball { -namespace pm { - -Manager::Manager(toml::parse_result p_package, bool p_silent, std::string p_cwd, std::string p_configFolder) { - package = p_package; - silent = p_silent; - cwd = p_cwd; - configFolder = p_configFolder; -} - -std::string Manager::getGit() { - std::string git = "git"; - if (getenv("SNOWBALL_GIT_PATH") != NULL) { - git = getenv("SNOWBALL_GIT_PATH"); - } - return git; -} - -int Manager::runAsMain() { - if (!package["dependencies"]) return EXIT_SUCCESS; - (void)chdir(((fs::path)configFolder / "deps").c_str()); - // example: "owner/repo" = { version = "1.0.0" } - auto packages = package["dependencies"].as_table(); - if (package["dependencies"].is_table()) { - std::vector packagesInfo; - packages->for_each([&](auto&& key, auto&& value) { - auto repo = (std::string)key.str(); - auto packageData = package["dependencies"][repo]; - Package packageInfo; - packageInfo.name = repo; - packageInfo.version = packageData["version"].value_or("latest"); - packageInfo.dependencies = {}; - if (packageData["dependencies"].is_table()) { - packageData["dependencies"].as_table()->for_each([&](auto&& key, auto&& value) { - Package dependency; - dependency.name = (std::string)key.str(); - dependency.version = value.as_table()->get("version")->as_string()->get(); - packageInfo.dependencies.push_back(dependency); - }); - } - packagesInfo.push_back(packageInfo); - }); - for (auto& p : packagesInfo) { - auto result = install(p); - if (result != EXIT_SUCCESS) { - throw SNError(Error::PM_ERROR, FMT("Failed to install package %s", p.name.c_str())); - } - } - } - (void)chdir(cwd.c_str()); - return EXIT_SUCCESS; -} - -bool Manager::isInstalled(Package p_package) { - // check on folder structure - auto packageFolder = (fs::path)configFolder / "deps" / p_package.name; - return fs::is_directory(packageFolder); -} - -int Manager::install(Package p_package) { - if (isInstalled(p_package)) return EXIT_SUCCESS; - std::string git = getGit(); - auto pkgInfo = getPackageInfoFromRepo(p_package.name); - if (!silent) { - Logger::reset_status(); - Logger::raw_message("Downloading", FMT(": Package %s%s%s from git repository", BOLD, p_package.name.c_str(), RESET)); - } - auto packageFolder = (fs::path)configFolder / "deps" / p_package.name; - std::string downloadUrl = pkgInfo["download_url"]; - if (downloadUrl.empty()) { - throw SNError(Error::PM_ERROR, FMT("Failed to install package '%s'. No download_url found in package info", - p_package.name.c_str())); - } - auto versions = pkgInfo["versions"]; - std::string commitId; - if (versions.is_array()) { - auto version = p_package.version; - if (version == "latest") { - version = versions[0]; - } - auto found = false; - for (auto& v : versions) { - if (v == version) { - found = true; - break; - } - } - if (!found) { - throw SNError(Error::PM_ERROR, FMT("Failed to install package '%s'. Version '%s' not found in package info", - p_package.name.c_str(), version.c_str())); - } - commitId = version; - } - auto gitCommand = std::vector {}; - gitCommand.push_back(git); - gitCommand.push_back("-c"); - gitCommand.push_back("advice.detachedHead=false"); // Disable warning about detached head - gitCommand.push_back("clone"); - gitCommand.push_back(downloadUrl); - gitCommand.push_back(packageFolder); - gitCommand.push_back("--depth=1"); - gitCommand.push_back("--quiet"); - if (!commitId.empty()) { - gitCommand.push_back("--branch"); - gitCommand.push_back(commitId); - } - auto status = os::Driver::run(gitCommand); - if (status != EXIT_SUCCESS) { - throw SNError(Error::PM_ERROR, FMT("Failed to install package '%s'. See the output above", p_package.name.c_str())); - } - auto packageConfig = packageFolder / "sn.toml"; - if (!fs::exists(packageConfig)) { - throw SNError(Error::PM_ERROR, FMT("Failed to install package '%s'. No sn.toml found in package", - p_package.name.c_str())); - } - auto packageConfigData = toml::parse_file(packageConfig.string()); - Logger::reset_status(); - Logger::message("Installed", FMT("Package %s%s%s", BOLD, p_package.name.c_str(), RESET)); - this->package = packageConfigData; - auto result = runAsMain(); - if (result != EXIT_SUCCESS) { - throw SNError(Error::PM_ERROR, FMT("Failed to install package '%s'. See the output above", p_package.name.c_str())); - } - return EXIT_SUCCESS; -} - -namespace { -std::size_t writeCallback( - const char* in, - std::size_t size, - std::size_t num, - std::string* out) { - const std::size_t totalBytes(size * num); - out->append(in, totalBytes); - return totalBytes; -} -} - -nlohmann::json Manager::getPackageInfoFromRepo(std::string p_repo) { - auto packageInfo = nlohmann::json{}; - std::unique_ptr httpData(new std::string()); - auto curl = curl_easy_init(); - if (curl) { - auto url = _SNOWBALL_PACKAGE_REGISTRY + p_repo + ".json"; - long httpCode(0); - curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback); - curl_easy_setopt(curl, CURLOPT_USERAGENT, - "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.0; Win64; x64 Trident/6.0)"); - curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); - // Don't wait forever, time out after 10 seconds. - curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10); - // Acces https without ca verification - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get()); - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); - if (!silent) { - Logger::raw_message("Fetching", FMT("Package info for %s%s%s from registry", BOLD, p_repo.c_str(), RESET)); - } - auto curlCode = curl_easy_perform(curl); - curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode); - curl_easy_cleanup(curl); - if (curlCode != CURLE_OK) { - throw SNError(Error::PM_ERROR, FMT("Failed to get package info from registry. CURL code %s", - curl_easy_strerror(curlCode))); - } - if (httpCode != 200) { - throw SNError(Error::PM_ERROR, FMT("Failed to get package info from registry. HTTP code %d", httpCode)); - } - } else { - throw SNError(Error::PM_ERROR, "Failed to initialize curl"); - } - try { - packageInfo = nlohmann::json::parse(*httpData); - } catch (const std::exception& e) { - throw SNError(Error::PM_ERROR, FMT("Failed to parse package info from registry. %s", e.what())); - } - return packageInfo; -} - -} // namespace pm -} // namespace snowball diff --git a/src/pm/Manager.h b/src/pm/Manager.h deleted file mode 100644 index 3a17842b..00000000 --- a/src/pm/Manager.h +++ /dev/null @@ -1,68 +0,0 @@ - - -#include -#include -#include -#include - -#include "vendor/toml.hpp" - -#include "../utils/utils.h" -#include "../errors.h" -#include "../constants.h" -#include "../os/Driver.h" - -#include "nlohmann/json.hpp" - -#ifndef __SNOOZE__APP__PM__MANAGER_H__ -#define __SNOOZE__APP__PM__MANAGER_H__ - -namespace snowball { -namespace pm { - -struct Package { - std::string name; - std::string version; - - std::vector dependencies; -}; - -/** - * @brief Snowball's package manager. - * - * This class is responsible for managing packages on the system. - * It is responsible for installing, removing, and updating packages. - * - Installing packages - * - Removing packages - * - Updating packages - * - Listing packages - * - Searching for packages - * - Querying packages - * ... - * - * Packages are installed from a git repository. The git repository - * contains a package manifest file, which is a toml file that - * describes the package. -*/ -class Manager { - toml::parse_result package; - bool silent; - std::string cwd; - std::string configFolder; - - public: - Manager(toml::parse_result p_package, bool p_silent, std::string p_cwd, std::string p_configFolder); - - int runAsMain(); - std::string getGit(); - - bool isInstalled(Package p_package); - int install(Package p_package); - - nlohmann::json getPackageInfoFromRepo(std::string package); -}; - -} // namespace pm -} // namespace snowball - -#endif // __SNOOZE__APP__PM__MANAGER_H__ diff --git a/src/services/ImportCache.cc b/src/services/ImportCache.cc deleted file mode 100644 index 75432b33..00000000 --- a/src/services/ImportCache.cc +++ /dev/null @@ -1,29 +0,0 @@ - -#include "ImportCache.h" - -#include "../utils/utils.h" - -#include -#include - -// clang-format off -namespace fs = std::filesystem; - -namespace snowball { -namespace services { - -void ImportCache::addModule(fs::path p, std::shared_ptr m) { - auto i = modules.find(p); assert(i == modules.end()); - modules.insert({p, m}); -} -std::optional> -ImportCache::getModule(fs::path p) { - auto i = modules.find(p); - return i == modules.end() ? std::nullopt : - std::make_optional>(i->second); -} - -// clang-format on - -} // namespace services -} // namespace snowball diff --git a/src/services/ImportCache.h b/src/services/ImportCache.h deleted file mode 100644 index 7655cf55..00000000 --- a/src/services/ImportCache.h +++ /dev/null @@ -1,37 +0,0 @@ - -#include "../ir/module/Module.h" - -#include -#include -#include - -#ifndef __SNOWBALL_IMPORT_CACHE_H_ -#define __SNOWBALL_IMPORT_CACHE_H_ - -namespace snowball { -namespace services { - -/** - * @brief It keeps track of the already-imported modules - * and stores them as a cache. - */ -class ImportCache { - /// @brief A map containing the stored modules. - /// @note The map key is a full abstract path. - std::map> modules; - - public: - ImportCache() noexcept = default; - - /// @brief Set a new module to the map - void addModule(std::filesystem::path p, std::shared_ptr m); - /// @return a shared pointer to a module if it exists inside the map - std::optional> getModule(std::filesystem::path p); - - ~ImportCache() noexcept = default; -}; - -} // namespace services -} // namespace snowball - -#endif // __SNOWBALL_IMPORT_CACHE_H_ diff --git a/src/services/ImportService.cc b/src/services/ImportService.cc deleted file mode 100644 index 337ea5fd..00000000 --- a/src/services/ImportService.cc +++ /dev/null @@ -1,80 +0,0 @@ - -#include "ImportService.h" - -#include "../utils/utils.h" -#include "../vendor/toml.hpp" - -#include - -namespace fs = std::filesystem; - -namespace snowball { -namespace services { - -inline const std::string ImportService::CORE_UUID = "@sn.std."; -fs::path ImportService::getPackagePath(const std::string package) { - if (package == "std") { - return (fs::path) utils::get_lib_folder(); - } else if (package == "pkg") { - return fs::current_path(); - } - return getPackagesPath() / (_SNOWBALL_PACKAGES_DIR) / package; -} - -std::string ImportService::getExportName(std::filesystem::path path, std::string symbol) { - return symbol.empty() ? path.stem().string() : symbol; -} - -bool ImportService::isExternalModule(std::string package) { return package != "pkg"; } - -std::string ImportService::getModuleUUID(std::filesystem::path path) { - std::string result = path.string(); - // Remove getPackagesPath() from the path - result = result.substr(getPackagesPath().string().length() + 1); - // Remove the extension - result = ((fs::path)result).replace_extension(""); - // Replace all slashes with dots - utils::replaceAll(result, "/", "::"); - return "pkg::" + result; -} - -std::tuple -ImportService::getImportPath(const std::string package, std::vector path, const std::string extension) { - auto packagePath = getPackagePath(package); - fs::path definedPath; - for (auto p : path) { definedPath /= p; } - fs::path fullPath = packagePath / definedPath; - bool exists = false; - std::string foundExt; - // if it's a directory - for (auto ext : extensions) { - if (exists) { return {"", "", "Multiple paths found without an extension defined"}; } - exists = access((fullPath.string() + ext).c_str(), F_OK) != -1; - if (exists) { foundExt = ext; } - } - if (!exists) { - if (fs::is_directory(fullPath)) { - auto configFile = fullPath / "sn.toml"; - auto config = toml::parse_file(configFile.string()); - auto entry = config["package"]["main"].value_or(""); - if (entry == "") { - return {"", "", "Package doesn't have a main entry defined!"}; - } - auto finalPath = fullPath / entry; - if (fullPath.stem().empty()) fullPath = fullPath.parent_path(); - assert(access(finalPath.c_str(), F_OK) != -1); - return {finalPath, fullPath, ""}; - } - } - if (!exists) { - return {"", "", - FMT("Coudnt find module '%s' imported from '%s' (%s)!", - utils::join(path.begin(), path.end(), "::").c_str(), - package.c_str(), fullPath.string().c_str())}; - } - auto finalPath = fullPath.string() + foundExt; - return {finalPath, finalPath, ""}; -} - -} // namespace services -} // namespace snowball diff --git a/src/services/ImportService.h b/src/services/ImportService.h deleted file mode 100644 index a2124354..00000000 --- a/src/services/ImportService.h +++ /dev/null @@ -1,88 +0,0 @@ - -#include "../common.h" -#include "ImportCache.h" - -#ifndef __SNOWBALL_SERVICES_IMPORT_H_ -#define __SNOWBALL_SERVICES_IMPORT_H_ - -namespace snowball { -namespace services { - -/** - * @brief It manages imports and module caches - */ -class ImportService { - public: - /// @brief A cache containing all of the alread-generated modules - /// used at compile time. - ImportCache* cache = new ImportCache(); - /// @brief A list of possible pre-defined file extensions used to - /// search - /// if no extension has been defined. - const std::vector extensions = {".sn", /* TODO */}; - /// @brief Core library custom UUID - static const std::string CORE_UUID; - /// @brief Path to the current package being generated - std::filesystem::path currentPackagePath; - /// @brief Root path to the packages folder - std::filesystem::path packagesPath; - - public: - ImportService(std::filesystem::path packagesPath) : packagesPath(packagesPath) {} - /** - * @brief Get the package path based on it's identifier - * @note if package name is "pkg" it will return the current package - * being generated - */ - std::filesystem::path getPackagePath(const std::string package); - /** - * @brief Get the corresponding import path from a set of rules. - * @note The path will be absolute and paths will be returned if the - * file exist. - * - * @param package package to search from (e.g. std). @note if the - * package is - * "pkg" it will find inside the current package being generated. - * @param path the path to search for - * @param extension extension to find for (search for common ones - * for ) - * @return std::filesystem::path found path to import and - * std::string an error message if any - */ - std::tuple - getImportPath(const std::string package, std::vector path, const std::string extension = ""); - /** - * @brief Check if a module is external or not - */ - bool isExternalModule(std::string package); - /** - * @brief Gets the exported name based on the path if the export - * symbol is empty. - */ - std::string getExportName(std::filesystem::path path, std::string symbol); - /** - * @brief Get the respective UUID based on the path it's imported - * from - * - * @param path path to transform - * @return std::string resultant UUID for the module path. - */ - std::string getModuleUUID(std::filesystem::path path); - /** - * @brief Get the current package path - */ - std::filesystem::path getCurrentPackagePath() const { return currentPackagePath; } - /** - * @brief Set the current package path - */ - void setCurrentPackagePath(std::filesystem::path path) { currentPackagePath = path; } - /** - * @brief Get the packages path - */ - std::filesystem::path getPackagesPath() const { return packagesPath; } -}; - -} // namespace services -} // namespace snowball - -#endif // __SNOWBALL_SERVICES_IMPORT_H_ diff --git a/src/services/OperatorService.cc b/src/services/OperatorService.cc deleted file mode 100644 index 5829f7b6..00000000 --- a/src/services/OperatorService.cc +++ /dev/null @@ -1,33 +0,0 @@ - -#include "OperatorService.h" - -#include -#include - -namespace snowball { -namespace services { -using OpType = services::OperatorService::OperatorType; - -std::string OperatorService::getOperatorId(OperatorService::OperatorType id) { return operators.at(id); } - -bool OperatorService::isOperator(const std::string& name) { return utils::startsWith(name, "#"); } - -const std::string& OperatorService::operatorName(OperatorType id) { return operatorNames.at(id); } - -OperatorService::OperatorType OperatorService::operatorID(const std::string& n) { - std::string name = n; - if (isOperator(name)) { name = name.substr(1, name.size() - 1); } - auto it = std::find(operators.begin(), operators.end(), name); - assert(it != operators.end()); - return (OperatorService::OperatorType) std::distance(operators.begin(), it); -} - -std::string OperatorService::getOperatorMangle(OperatorService::OperatorType id) { return "#" + getOperatorId(id); } - -bool OperatorService::isUnary(OperatorService::OperatorType op_type) { - return op_type == OpType::NOT || op_type == OpType::BIT_NOT || op_type == OpType::UPLUS || - op_type == OpType::UMINUS || op_type == OpType::REFERENCE || op_type == OpType::DEREFERENCE; -} - -} // namespace services -} // namespace snowball diff --git a/src/services/OperatorService.h b/src/services/OperatorService.h deleted file mode 100644 index 53af52df..00000000 --- a/src/services/OperatorService.h +++ /dev/null @@ -1,80 +0,0 @@ - -#include "../common.h" -#include "../utils/utils.h" - -#include -#include - -#ifndef __SNOWBALL_SERVICES_OPERATORS_H_ -#define __SNOWBALL_SERVICES_OPERATORS_H_ - -namespace snowball { -namespace services { - -/** - * @brief It manages all of the operator-related - * stuff such as operator name, etc... - * @note It will only contain static functions for - * utility-related things - */ -class OperatorService { - public: -#define OPERATOR(o, n, s, p) o = n, - /** - * @brief A list containing all of the possible overload-able - * operators that a class can define. - */ - enum OperatorType { -#include "../defs/operators.def" - }; -#undef OPERATOR - /** - * @brief A list containing the respective operator identifier - * as a list of strings - */ - static const std::vector operators; - /** - * @brief A vector that contains the corresponding operator - * names (nice names for output) - */ - static const std::vector operatorNames; - - public: - /// @brief Get the respective operator identifier - static std::string getOperatorId(OperatorType id); - /// @brief Get operator identifier but with an "#" - /// prepended to it. - static std::string getOperatorMangle(OperatorType id); - /// @brief Check if a name is a operator-like name - static bool isOperator(const std::string& name); - /// @brief Operator ID to constructor - static const std::string& operatorName(OperatorType id); - /// @return the corresponding ID from a @param name - static OperatorType operatorID(const std::string& name); - /// @brief Check if an operator is unary - static bool isUnary(OperatorType op_type); - /// @brief Check if a name has equality towards an operator ID - template - static bool opEquals(const std::string& name) { - return (isOperator(name) && operatorID(name) == op); - } -}; - -#define OPERATOR(o, n, s, p) s, -inline const std::vector OperatorService::operators = { -#include "../defs/operators.def" -}; -#undef OPERATOR -#define OPERATOR(o, n, s, p) p, -inline const std::vector OperatorService::operatorNames = { -#include "../defs/operators.def" -}; -#undef OPERATOR - -} // namespace services - -using OperatorType = services::OperatorService::OperatorType; -using namespace services; -} // namespace snowball - -#endif // __SNOWBALL_SERVICES_OPERATORS_H_ diff --git a/src/sourceInfo/DBGSourceInfo.cc b/src/sourceInfo/DBGSourceInfo.cc deleted file mode 100644 index 85efcc04..00000000 --- a/src/sourceInfo/DBGSourceInfo.cc +++ /dev/null @@ -1,69 +0,0 @@ - -#include "sourceInfo/DBGSourceInfo.h" - -#include "sourceInfo/SourcedObject.h" - -#include -#include - -namespace snowball { -DBGSourceInfo::DBGSourceInfo(const SourceInfo* p_source_info, uint32_t p_line) - : SrcObject(p_source_info), line(p_line) { } - -DBGSourceInfo::DBGSourceInfo(const SourceInfo* p_source_info, std::pair p_pos, uint32_t p_width) - : pos(p_pos), line((uint32_t) p_pos.first), width(p_width), SrcObject(p_source_info) { } - -void DBGSourceInfo::prepare_for_error() { - uint64_t cur_line = 1; - line_before.clear(); - line_before_before.clear(); - line_str.clear(); - line_after.clear(); - line_after_after.clear(); - const auto& source = m_srci->getSource(); - for (auto c : source) { - if (c == '\n') { - if (cur_line >= line + 2) break; - cur_line++; - } else if (cur_line == line - 2) { - line_before_before += c; - } else if (cur_line == line - 1) { - line_before += c; - } else if (cur_line == line) { - line_str += c; - } else if (cur_line == line + 1) { - line_after += c; - } else if (cur_line == line + 2) { - line_after_after += c; - } - } -} - -std::string DBGSourceInfo::get_pos_str() const { - // var x = blabla; - // ^^^^^^ - std::stringstream ss_pos; - size_t cur_col = 0; - bool done = false; - for (size_t i = 0; i < line_str.size(); i++) { - cur_col++; - if (cur_col == (size_t)pos.second) { - for (uint32_t i = 0; i < width; i++) { ss_pos << '~'; } - done = true; - break; - } else if (line_str[i] != '\t') { - ss_pos << ' '; - } else { - ss_pos << '\t'; - } - } - if (!done) ss_pos << '^'; - auto ret = ss_pos.str(); - return ret; -} - -DBGObject::DBGObject() { /* noop */ -} -DBGSourceInfo* DBGObject::getDBGInfo() { return dbg; } -void DBGObject::setDBGInfo(DBGSourceInfo* i) { dbg = i; } -} // namespace snowball \ No newline at end of file diff --git a/src/sourceInfo/DBGSourceInfo.h b/src/sourceInfo/DBGSourceInfo.h deleted file mode 100644 index 14a3b799..00000000 --- a/src/sourceInfo/DBGSourceInfo.h +++ /dev/null @@ -1,80 +0,0 @@ - - -#include "../SourceInfo.h" -#include "../common.h" -#include "../lexer/tokens/token.h" -#include "../utils/logger.h" -#include "SourcedObject.h" - -#ifndef __SNOWBALL_DBG_INFO_H_ -#define __SNOWBALL_DBG_INFO_H_ - -#define NO_DBGINFO (DBGSourceInfo*) nullptr - -namespace snowball { - -/** - * DBGSource info is used by the error handling - * system. It basically get's the line and some - * offset lines from a source file depending on - * the possition. - * - * This is usefull to do pretty errors that can - * display the contents of a line. - */ -class DBGSourceInfo : public SrcObject { - public: - DBGSourceInfo(const SourceInfo* source_info, uint32_t p_line); - DBGSourceInfo(const SourceInfo* source_info, std::pair p_pos, uint32_t p_width); - - uint32_t width = 0; - uint32_t line = 0; - std::pair pos; - - std::string line_before; - std::string line_before_before; - std::string line_str; - std::string line_after; - std::string line_after_after; - - public: - std::string get_pos_str() const; - void prepare_for_error(); - friend SrcObject; - - auto getDBGInfo() { return this; } - - /** - * @brief Create a new instance of dbg source info - * using a token as reference. - */ - static auto fromToken(const SourceInfo* i, Token tk) { return new DBGSourceInfo(i, tk.get_pos(), tk.get_width()); } - - ~DBGSourceInfo() = delete; -}; - -/** - * This class is used as a parent so that objects can - * inherit from it. - * - * It's used as a wrapper for `DBGSourceInfo` so that - * objects can contain dbg information instead of - * passing it into each function that needs into in. - * This just saves some messy code. - */ -class DBGObject : public SrcObject { - protected: - DBGSourceInfo* dbg = nullptr; - - public: - /// @brief Contruct a new DBGObject - DBGObject(); - - /// @return Debug information - virtual DBGSourceInfo* getDBGInfo(); - /// @brief Set a new dbg object - virtual void setDBGInfo(DBGSourceInfo* i); -}; -} // namespace snowball - -#endif // __SNOWBALL_DBG_INFO_H_ diff --git a/src/sourceInfo/SourcedObject.h b/src/sourceInfo/SourcedObject.h deleted file mode 100644 index bcaa96d7..00000000 --- a/src/sourceInfo/SourcedObject.h +++ /dev/null @@ -1,35 +0,0 @@ - -#include "SourceInfo.h" -#include "common.h" - -#ifndef __SNOWBALL_SRC_OBJECT_H_ -#define __SNOWBALL_SRC_OBJECT_H_ - -namespace snowball { - -static const SourceInfo* TEMP_DBG_INFO = new SourceInfo("", ""); - -/// @brief A class that contains source information -/// @details This class is used to store source information -/// in the AST nodes. -/// It is used to store the file path, the line and column -/// of the source code. -/// It is also used to store the source code itself. -/// @see SrcObject -class SrcObject { - protected: - const SourceInfo* m_srci; - - public: - SrcObject(const SourceInfo* i) : m_srci(i) { } - SrcObject() : m_srci(TEMP_DBG_INFO) { } - - /// @brief get the instance of the source info - auto& getSourceInfo() const { return m_srci; } - /// @brief Declare a new instance of source info - void setSourceInfo(const SourceInfo* i) { m_srci = i; } -}; - -} // namespace snowball - -#endif // __SNOWBALL_SRC_OBJECT_H_ diff --git a/src/utils/colors.cc b/src/utils/colors.cc deleted file mode 100644 index 8e063be9..00000000 --- a/src/utils/colors.cc +++ /dev/null @@ -1,83 +0,0 @@ -#include "colors.h" - -namespace snowball { -const char* BLK = "\e[0;90m"; -const char* RED = "\e[0;31m"; -const char* GRN = "\e[0;32m"; -const char* YEL = "\e[0;33m"; -const char* BLU = "\e[0;34m"; -const char* MAG = "\e[0;35m"; -const char* CYN = "\e[0;36m"; -const char* WHT = "\e[0;37m"; - -// Regular bold text -const char* BBLK = "\e[1;30m"; -const char* BRED = "\e[1;31m"; -const char* BGRN = "\e[1;32m"; -const char* BYEL = "\e[1;33m"; -const char* BBLU = "\e[1;34m"; -const char* BMAG = "\e[1;35m"; -const char* BCYN = "\e[1;36m"; -const char* BWHT = "\e[1;37m"; - -// Regular underline text -const char* UBLK = "\e[4;30m"; -const char* URED = "\e[4;31m"; -const char* UGRN = "\e[4;32m"; -const char* UYEL = "\e[4;33m"; -const char* UBLU = "\e[4;34m"; -const char* UMAG = "\e[4;35m"; -const char* UCYN = "\e[4;36m"; -const char* UWHT = "\e[4;37m"; - -// Regular background -const char* BLKB = "\e[40m"; -const char* REDB = "\e[41m"; -const char* GRNB = "\e[42m"; -const char* YELB = "\e[43m"; -const char* BLUB = "\e[44m"; -const char* MAGB = "\e[45m"; -const char* CYNB = "\e[46m"; -const char* WHTB = "\e[47m"; - -// High intensty background -const char* BLKHB = "\e[0;100m"; -const char* REDHB = "\e[0;101m"; -const char* GRNHB = "\e[0;102m"; -const char* YELHB = "\e[0;103m"; -const char* BLUHB = "\e[0;104m"; -const char* MAGHB = "\e[0;105m"; -const char* CYNHB = "\e[0;106m"; -const char* WHTHB = "\e[0;107m"; - -// High intensty text -const char* HBLK = "\e[0;90m"; -const char* HRED = "\e[0;91m"; -const char* HGRN = "\e[0;92m"; -const char* HYEL = "\e[0;93m"; -const char* HBLU = "\e[0;94m"; -const char* HMAG = "\e[0;95m"; -const char* HCYN = "\e[0;96m"; -const char* HWHT = "\e[0;97m"; - -// Bold high intensity text -const char* BHBLK = "\e[1;90m"; -const char* BHRED = "\e[1;91m"; -const char* BHGRN = "\e[1;92m"; -const char* BHYEL = "\e[1;93m"; -const char* BHBLU = "\e[1;94m"; -const char* BHMAG = "\e[1;95m"; -const char* BHCYN = "\e[1;96m"; -const char* BHWHT = "\e[1;97m"; - -// MORE CODES -const char* RESET = "\e[0m"; -const char* DIM = "\e[22m"; -const char* BLINK = "\e[5m"; -const char* HIDDEN = "\e[8m"; -const char* REVERSE = "\e[7m"; -const char* BOLD = "\e[1m"; -const char* UNDERLINE = "\e[4m"; -const char* STRIKE = "\e[9m"; - -} // namespace snowball diff --git a/src/utils/colors.h b/src/utils/colors.h deleted file mode 100644 index 18af278d..00000000 --- a/src/utils/colors.h +++ /dev/null @@ -1,88 +0,0 @@ - -#ifndef __SNOWBALL_COLORS_H_ -#define __SNOWBALL_COLORS_H_ - -namespace snowball { - -// Regular text -extern const char* BLK; -extern const char* RED; -extern const char* GRN; -extern const char* YEL; -extern const char* BLU; -extern const char* MAG; -extern const char* CYN; -extern const char* WHT; - -// Regular bold text -extern const char* BBLK; -extern const char* BRED; -extern const char* BGRN; -extern const char* BYEL; -extern const char* BBLU; -extern const char* BMAG; -extern const char* BCYN; -extern const char* BWHT; - -// Regular underline text -extern const char* UBLK; -extern const char* URED; -extern const char* UGRN; -extern const char* UYEL; -extern const char* UBLU; -extern const char* UMAG; -extern const char* UCYN; -extern const char* UWHT; - -// Regular background -extern const char* BLKB; -extern const char* REDB; -extern const char* GRNB; -extern const char* YELB; -extern const char* BLUB; -extern const char* MAGB; -extern const char* CYNB; -extern const char* WHTB; - -// High intensty background -extern const char* BLKHB; -extern const char* REDHB; -extern const char* GRNHB; -extern const char* YELHB; -extern const char* BLUHB; -extern const char* MAGHB; -extern const char* CYNHB; -extern const char* WHTHB; - -// High intensty text -extern const char* HBLK; -extern const char* HRED; -extern const char* HGRN; -extern const char* HYEL; -extern const char* HBLU; -extern const char* HMAG; -extern const char* HCYN; -extern const char* HWHT; - -// Bold high intensity text -extern const char* BHBLK; -extern const char* BHRED; -extern const char* BHGRN; -extern const char* BHYEL; -extern const char* BHBLU; -extern const char* BHMAG; -extern const char* BHCYN; -extern const char* BHWHT; - -// MORE CODES -extern const char* RESET; -extern const char* DIM; -extern const char* BLINK; -extern const char* HIDDEN; -extern const char* REVERSE; -extern const char* BOLD; -extern const char* UNDERLINE; -extern const char* STRIKE; -} // namespace snowball - -#endif // __SNOWBALL_COLORS_H_ diff --git a/src/utils/logger.cc b/src/utils/logger.cc deleted file mode 100644 index 304b406f..00000000 --- a/src/utils/logger.cc +++ /dev/null @@ -1,84 +0,0 @@ - -#include "utils/logger.h" - -#include -#include -#include -#include -#include - -#define _SN_LOGGER_BAR_WIDTH 20 - -namespace snowball { -void Logger::log(std::string message) { - printf("%s\n", message.c_str()); - fflush(stdout); -} -void Logger::rlog(std::string message) { - printf("%s", message.c_str()); - fflush(stdout); -} -void Logger::elog(std::string message) { - fprintf(stderr, "%s\n", message.c_str()); - fflush(stderr); -} - -void Logger::info(std::string message) { printf("%s[info]%s: %s\n", BGRN, RESET, message.c_str()); } -void Logger::help(std::string message) { printf("%s[help]%s: %s\n", BGRN, RESET, message.c_str()); } -void Logger::error(std::string message) { printf("%s[error]%s: %s\n", BRED, RESET, message.c_str()); } -void Logger::warning(std::string message) { printf("%s[warning]%s: %s\n", BYEL, RESET, message.c_str()); } -void Logger::verbose(std::string message) { printf("%s[verbose]%s: %s\n", BMAG, RESET, message.c_str()); } -void Logger::success(std::string message) { printf("%s[success]%s: %s\n", BGRN, RESET, message.c_str()); } - -void Logger::message(std::string topic, std::string message) { - std::cout << BGRN << std::setw(15) << std::fixed << topic << RESET << ' ' << message << std::endl; -} - -void Logger::raw_message(std::string topic, std::string message) { - std::cout << BGRN << std::setw(15) << std::fixed << topic << RESET << ' ' << message; - fflush(stdout); -} - -// status -void Logger::reset_status() { - printf("\33[2K\r"); - fflush(stdout); -}; -void Logger::compiling(std::string message, std::string status) { - std::cout << BCYN << std::setw(15) << status << RESET << ' ' << message; - fflush(stdout); -}; - -std::string Logger::progress(float progress, std::string message) { - std::stringstream output; - reset_status(); - output << "["; - int pos = _SN_LOGGER_BAR_WIDTH * progress; - for (int i = 0; i < _SN_LOGGER_BAR_WIDTH; ++i) { - if (i < pos) - output << "="; - else if (i == pos) - output << ">"; - else - output << " "; - } - output << "] " << int(progress * 100.0); - output << "%"; - if (!message.empty()) output << " " << message; - output << "\r"; - output.flush(); - return output.str(); -} - -std::string FMT(const char* p_format, ...) { - va_list argp; - va_start(argp, p_format); - size_t result_size = vsnprintf(NULL, 0, p_format, argp); - char buffer[result_size + 1]; // +1 for the terminating character - va_end(argp); - va_start(argp, p_format); - int len = vsprintf(buffer, p_format, argp); - va_end(argp); - return std::string(buffer, len); -} -} // namespace snowball diff --git a/src/utils/logger.h b/src/utils/logger.h deleted file mode 100644 index 219a18b3..00000000 --- a/src/utils/logger.h +++ /dev/null @@ -1,38 +0,0 @@ - -#include "colors.h" - -#include - -#ifndef __SNOWBALL_LOGGER_H_ -#define __SNOWBALL_LOGGER_H_ - -#define FMT(...) Logger::format(__VA_ARGS__) - -namespace snowball { - -class Logger { - public: - static void log(std::string message); - static void rlog(std::string message); - static void elog(std::string message); - - static void info(std::string message); - static void help(std::string message); - static void error(std::string message); - static void warning(std::string message); - static void verbose(std::string message); - static void success(std::string message); - - static void message(std::string topic, std::string message); - static void raw_message(std::string topic, std::string message); - - // status messages - static void reset_status(); - static void compiling(std::string message, std::string status = "Compiling"); - - static std::string progress(float progress = 0, std::string message = ""); - static std::string format(const char* p_format, ...); -}; -} // namespace snowball - -#endif // __SNOWBALL_LOGGER_H_ diff --git a/src/utils/utils.cc b/src/utils/utils.cc deleted file mode 100644 index 725604be..00000000 --- a/src/utils/utils.cc +++ /dev/null @@ -1,159 +0,0 @@ - -#include "utils/utils.h" - -#include "errors.h" - -#include -#include - -#ifdef _WIN32 -#include //GetModuleFileNameW -#else -#include -#include //readlink -#endif - -#include -#include - -#ifdef __APPLE__ -#include -#endif - -namespace fs = std::filesystem; - -namespace snowball { -namespace utils { - -std::string get_exe_folder() { -#ifdef _WIN32 - // Windows specific - wchar_t szPath[MAX_PATH]; - GetModuleFileNameW(NULL, szPath, MAX_PATH); -#elif __APPLE__ - const size_t bufSize = PATH_MAX + 1; - char dirNameBuffer[bufSize]; - uint32_t size = bufSize; - if (_NSGetExecutablePath(dirNameBuffer, &size) != 0) { - // Buffer size is too small. - abort(); - } - std::string szPath(dirNameBuffer); -#else - // Linux specific - char szPath[PATH_MAX]; - ssize_t count = readlink("/proc/self/exe", szPath, PATH_MAX); - if (count < 0 || count >= PATH_MAX) return {}; // some error - szPath[count] = '\0'; -#endif - return std::filesystem::path {szPath}.parent_path() / ""; // to finish the folder path with (back)slash -} - -std::string -getSubstringByRange(const std::string& str, const std::pair& start, const std::pair& end) { - int startPos = 0; - int endPos = 0; - int currentLine = 1; - int currentColumn = 1; - // Iterate over the string to find the starting and ending positions - // of the substring - for (int i = 0; i < (int)str.length(); i++) { - if (currentLine == start.first && currentColumn == start.second) { startPos = i; } - if (currentLine == end.first && currentColumn == end.second) { - endPos = i; - break; - } - if (str[i] == '\n') { - currentLine++; - currentColumn = 1; - } else { - currentColumn++; - } - } - // Return the substring - return str.substr(startPos, endPos - startPos); -} - -std::string getUTF8FromIndex(const std::string& s, const int index) { - std::string result; - unsigned char c = s[index]; - if (c & 0x80) { // check if it's a multi-byte sequence - if ((c & 0xE0) == 0xC0) { // 2-byte sequence - result = s.substr(index, 2); - } else if ((c & 0xF0) == 0xE0) { // 3-byte sequence - result = s.substr(index, 3); - } else if ((c & 0xF8) == 0xF0) { // 4-byte sequence - result = s.substr(index, 4); - } - } else { // single byte character - result = c; - } - return result; -} - -fs::path get_lib_folder() { -#if defined(_SNOWBALL_BUILD_FOR_CE) - fs::path exe_folder = get_exe_folder(); - fs::path full_path = exe_folder / ".." / _SNOWBALL_LIBRARY_DIR; -#elif _SN_DEBUG - fs::path exe_folder = get_exe_folder(); // bin/Debug - fs::path full_path = exe_folder / ".." / ".." / _SNOWBALL_LIBRARY_DIR; -#else - fs::path home = getenv("HOME"); - fs::path exe_folder = home / (std::string) STATICLIB_DIR; - fs::path full_path = exe_folder / _SNOWBALL_LIBRARY_DIR; -#endif - bool filepathExists = fs::is_directory(full_path); - if (!filepathExists) { - throw snowball::SNError( - snowball::Error::IO_ERROR, FMT("Could not find system libraries! (%s)", full_path.string().c_str()) - ); - } - return full_path; -} - -void replaceAll(std::string& str, const std::string& from, const std::string& to) { - if (from.empty()) return; - size_t start_pos = 0; - while ((start_pos = str.find(from, start_pos)) != std::string::npos) { - str.replace(start_pos, from.length(), to); - start_pos += to.length(); // In case 'to' contains 'from', like - // replacing 'x' with 'yx' - } -} - -std::list split(std::string str, std::string token) { - std::list result; - while (str.size()) { - int index = str.find(token); - if (index != (int)std::string::npos) { - result.push_back(str.substr(0, index)); - str = str.substr(index + token.size()); - if (str.size() == 0) result.push_back(str); - } else { - result.push_back(str); - str = ""; - } - } - return result; -} - -bool isNumber(const std::string& s) { - return !s.empty() && std::find_if(s.begin(), s.end(), [](unsigned char c) { return !std::isdigit(c); }) == s.end(); -} - -bool endsWith(const std::string& mainStr, const std::string& toMatch) { - return (mainStr.size() >= toMatch.size() && - mainStr.compare(mainStr.size() - toMatch.size(), toMatch.size(), toMatch) == 0); -} - -bool startsWith(const std::string& str, const std::string& comp) { return str.rfind(comp, 0) == 0; } - -std::string itos(int i) { // convert int to string - std::stringstream s; - s << i; - return s.str(); -} - -} // namespace utils -} // namespace snowball diff --git a/src/utils/utils.h b/src/utils/utils.h deleted file mode 100644 index 11956e72..00000000 --- a/src/utils/utils.h +++ /dev/null @@ -1,163 +0,0 @@ -#include "../common.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef __SNOWBALL_UTILS__MAIN_H_ -#define __SNOWBALL_UTILS__MAIN_H_ - -#define ASSERT(x) assert(x); - -namespace snowball { -namespace utils { - -std::string get_exe_folder(); -std::string itos(int i); -std::filesystem::path get_lib_folder(); -bool isNumber(const std::string& s); -std::string getUTF8FromIndex(const std::string& s, const int index); -std::list split(std::string str, std::string token); -bool endsWith(const std::string& mainStr, const std::string& toMatch); -bool startsWith(const std::string& str, const std::string& comp); -void replaceAll(std::string& str, const std::string& from, const std::string& to); -std::string -getSubstringByRange(const std::string& str, const std::pair& start, const std::pair& end); -template -// https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file -std::string join(Iter begin, Iter end, std::string const& separator, std::function cb = [](Iter i) { - return *i; - }) { - std::ostringstream result; - if (begin != end) result << cb(begin++); - while (begin != end) result << separator << cb(begin++); - return result.str(); -} - -template -std::vector vector_iterate(std::vector p_vec, std::function p_function) { - // Why did the programmer quit his job? He didn't get arrays. - std::vector vec; - for (auto item : p_vec) { - auto v1 = p_function(item); - vec.push_back(v1); - } - return vec; -} - -template -std::pair, std::vector> -vectors_iterate(std::vector p_vec, std::function(StTy)> p_function) { - std::vector vec1; - std::vector vec2; - for (auto item : p_vec) { - auto[v1, v2] = p_function(item); - vec1.push_back(v1); - vec2.push_back(v2); - } - return {vec1, vec2}; -} - -template -std::vector map(std::map p_map, std::function)> cb) { - std::vector vec; - for (auto item : p_map) { vec.push_back(cb(item)); } - return vec; -} - -template -IteratorType at(std::list _list, int _i) { - typename std::list::iterator it = _list.begin(); - for (int i = 0; i < _i; i++) { ++it; } - return *it; -} - -template -std::vector map(std::list> p_map, std::function)> cb) { - std::vector vec; - for (auto item : p_map) { vec.push_back(cb(item)); } - return vec; -} - -template -[[nodiscard]] inline decltype(auto) cast(Current curr) { - return dynamic_cast(curr); -} - -template -[[nodiscard]] inline decltype(auto) is(Current curr) { - return cast(curr) != nullptr; -} - -template -[[nodiscard]] inline decltype(auto) copy_shared(std::shared_ptr x) { - return std::make_shared(*x); -} - -template -[[nodiscard]] inline decltype(auto) dyn_cast(std::shared_ptr curr) { - return std::dynamic_pointer_cast(curr); -} - -template -std::vector _x_to_vec(T x) { - std::vector vec; - for (auto i : x) { vec.push_back(i.second); } - return vec; -} - -template -std::vector list2vec(std::list l) { - std::vector vec; - for (auto i : l) { vec.push_back(i); } - return vec; -} - -template -std::vector map_to_vector(std::map m) { - return _x_to_vec, Value>(m); -} -template -std::vector list_to_vector(std::list> l) { - return _x_to_vec>, Value>(l); -} - -template -void assert_value_type() { - static_assert(std::is_same::value, "value types must be the same!"); -} - -template -[[nodiscard]] inline decltype(auto) copy(T* x) { - return new T(*x); -} - -#if _SNOWBALL_TIMERS_DEBUG -template -double _timer(F&& f, Ts&&... args) { - clock_t start = clock(); - std::forward(f)(std::forward(args)...); - return static_cast(clock() - start) / static_cast(CLOCKS_PER_SEC); -} -#endif - -template -std::string gen_random() { - static const char alphanum[] = "0123456789" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz"; - std::string tmp_s; - tmp_s.reserve(len); - for (int i = 0; i < len; ++i) { tmp_s += alphanum[rand() % (sizeof(alphanum) - 1)]; } - return tmp_s; -} - -} // namespace utils -} // namespace snowball - -#endif // __SNOWBALL_UTILS__MAIN_H_ diff --git a/src/vendor/pretty_print.hpp b/src/vendor/pretty_print.hpp deleted file mode 100644 index b251309f..00000000 --- a/src/vendor/pretty_print.hpp +++ /dev/null @@ -1,442 +0,0 @@ - -// Copyright (c) 2017 Tristan Brindle (tcbrindle at gmail dot com) -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#ifndef TCB_PRETTY_PRINT_HPP_INCLUDED -#define TCB_PRETTY_PRINT_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include -#include - -#if __cplusplus >= 201700 -#include -#include -#define TCB_PRETTY_PRINT_HAVE_CPP17 -#endif - -namespace tcb { -inline namespace pretty_print { - -namespace detail { - -template -using void_t = void; - -template -using iterator_t = decltype(std::begin(std::declval())); - -template -using iterator_category_t = typename std::iterator_traits::iterator_category; - -template -using array_element_t = std::remove_pointer_t>; - -template -struct is_quotable : std::false_type { -}; - -template -struct is_quotable> : std::true_type { -}; - -#ifdef TCB_PRETTY_PRINT_HAVE_CPP17 -template -struct is_quotable> : std::true_type { -}; -#endif - -template <> -struct is_quotable : std::true_type { -}; -template <> -struct is_quotable : std::true_type { -}; -template <> -struct is_quotable : std::true_type { -}; -template <> -struct is_quotable : std::true_type { -}; - -template -constexpr bool is_quotable_v = is_quotable::value; - -template -struct quoter { - const T& operator()(const T& t) const { return t; } -}; - -#ifndef TCB_PRETTY_PRINT_NO_STRING_QUOTING -template -struct quoter>>> { - decltype(auto) operator()(const T& t) const { return std::quoted(t); } -}; -#endif - -template -decltype(auto) quoted(const T& t) -{ - return quoter{}(t); -} - -template -struct is_range_like : std::false_type { -}; - -// A type is "Range-like" if std::begin(R) returns a type whose -// iterator_traits::iterator_category is derived from std::input_iterator_tag -// This definition would probably make Eric and Casey scream ;) -template -struct is_range_like< - T, std::enable_if_t>>::value>> - : std::true_type { -}; - -template -constexpr bool is_range_like_v = is_range_like::value; - -template -struct is_map_like : std::false_type { -}; - -// A map-like type is a range-like whose iterator type has -// 'first' and 'second' members. This is true for std::map and -// std::unordered_map, and for std::vector> (commonly used as a flat -// map). -template -struct is_map_like>, - decltype(std::declval>()->first), - decltype(std::declval>()->second)>> - : std::true_type { -}; - -template -constexpr bool is_map_like_v = is_map_like::value; - -template -struct is_tuple_like : std::false_type { -}; - -// A tuple-like type is one for which is specialisation of std::tuple_size -// exists, the 'value' member of which is of type std::size_t. -// FIXME: this definition sucks -- we really ought to check that tuple_element -// exists too for each I in [0, N) -template -struct is_tuple_like< - T, - std::enable_if_t::value)>, std::size_t>::value>> - : std::true_type { -}; - -template -constexpr bool is_tuple_like_v = is_tuple_like::value; - -template -struct is_optional_like : std::false_type { -}; - -// A type is optional-like for our purposes if it has a dereference operator, -// and is explicitly convertible to bool. This is true for std::optional, -// boost::optional and all pointer types, although we disable overloads for the -// latter by default. -template -struct is_optional_like()), - decltype(static_cast(std::declval()))>> - : std::true_type { -}; - -template -constexpr bool is_optional_like_v = is_optional_like::value; - -template -struct is_streamable : std::false_type { -}; - -template -struct is_streamable< - StreamT, T, - std::enable_if_t() - << std::declval()), - std::ios_base&>::value>> - : std::true_type { -}; - -template -constexpr bool is_streamable_v = is_streamable::value; - -// I'm sure clever non-recursive things could be done here with -// std::index_sequence and/or fold expressions, but this has -// the advantage that I actually understand what's going on :) -template -struct tuple_printer { - template - OStream& operator()(OStream& os, const Tuple& t) const - { - using std::get; - os << ", " << quoted(get(t)); - return tuple_printer{}(os, t); - } -}; - -template -struct tuple_printer { - template - OStream& operator()(OStream& os, const Tuple& t) const - { - using std::get; - os << '(' << quoted(get<0>(t)); - return tuple_printer{}(os, t); - } -}; - -template -struct tuple_printer { - template - OStream& operator()(OStream& os, const Tuple& t) const - { - os << ')'; - return os; - } -}; - -// Handle zero-sized tuples -template -struct tuple_printer { - template - OStream& operator()(OStream& os, const Tuple& t) const - { - os << "()"; - return os; - } -}; - -template -tuple_printer::value> -make_tuple_printer(const Tuple& t) -{ - return {}; -} - -// This is the test used to decide whether to enable the range stream function. -// it looks a bit complicated, but it's not that bad really. Basically, -// for this function to be enabled, we require -// -// * Range is range-like (that is, std::begin(c) returns an iterator), -// -- BUT it's not map-like, which we handle separately, -// * AND it does not already have an output stream function (don't stomp on -// std::string or custom containers' operator<<()s) -// -- except for the case where Range is a raw C array whose element type is -// different from the stream's character type -// -// To explain the last case, cout << int[5] will work with just the standard -// ostream headers, but pointer decay will occur and something like 0xDEADBEEF -// will be printed, which is not very useful. So we enable this overload for raw -// arrays, which becomes a better match (array->pointer conversion is not -// required). However, we still want char arrays to be printed as strings, so we -// disable this (again) if Range is a raw array of the same type as the -// OStream's character type. -// -// Phew! -template -constexpr bool should_print_range_v = - is_range_like_v && !is_map_like_v && - (!is_streamable_v || - (std::is_array::value && - !std::is_same, - typename OStream::char_type>::value)); - -// For maps it's simple -- we print it if it is map-like -template -constexpr bool should_print_map_v = is_map_like_v; - -// std::arrays are both tuple-like and range-like, but we prefer to regard them -// as ranges -template -constexpr bool should_print_tuple_v = - is_tuple_like_v && !is_range_like_v; - -// Raw C arrays are both optional-like (per our definition) -// and range-like. We prefer to treat them as ranges. -template -constexpr bool should_print_optional_v = - is_optional_like_v && !is_range_like_v -#ifndef TCB_PRETTY_PRINT_POINTERS_ARE_OPTIONALS - && !std::is_pointer::value -#endif - && !std::is_same, - typename OStream::char_type>::value; - -} // namespace detail - -// To ensure that all our print functions can call each other, we need to -// declare them all first, and then define them later. - -template < - typename OStream, typename Range, - std::enable_if_t, int> = 0> -OStream& operator<<(OStream& os, const Range& rng); - -template , int> = 0> -OStream& operator<<(OStream& os, const Map& map); - -template , int> = 0> -OStream& operator<<(OStream& os, const Tuple& tuple); - -template , - int> = 0> -OStream& operator<<(OStream& os, const Optional& opt); - -#ifdef TCB_PRETTY_PRINT_HAVE_CPP17 -template -OStream& operator<<(OStream& os, const std::variant& var); -#endif - -// http://en.cppreference.com/w/cpp/experimental/ostream_joiner -template -struct ostream_joiner { - using char_type = CharT; - using traits_type = Traits; - using ostream_type = std::basic_ostream; - using value_type = void; - using difference_type = void; - using pointer = void; - using reference = void; - using iterator_category = std::output_iterator_tag; - - ostream_joiner(ostream_type& stream, const DelimT& delim) - : os_(std::addressof(stream)), delim_(delim) - { - } - - ostream_joiner(ostream_type& stream, DelimT&& delim) - : os_(std::addressof(stream)), delim_(std::move(delim)) - { - } - - template - ostream_joiner& operator=(const T& value) - { - if (!first_) { - *os_ << delim_; - } - first_ = false; - *os_ << value; - return *this; - } - - ostream_joiner& operator*() noexcept { return *this; } - - ostream_joiner& operator++() noexcept { return *this; } - - ostream_joiner& operator++(int) noexcept { return *this; } - -private: - ostream_type* os_; - DelimT delim_; - bool first_ = true; -}; - -template -ostream_joiner, CharT, Traits> -make_ostream_joiner(std::basic_ostream& os, DelimT&& delimiter) -{ - return ostream_joiner, CharT, Traits>( - os, std::forward(delimiter)); -} - -template , int>> -OStream& operator<<(OStream& os, const Range& rng) -{ - os << '['; - auto joiner = make_ostream_joiner(os, ", "); - for (const auto& e : rng) { - joiner = detail::quoted(e); - } - os << ']'; - return os; -} - -template , int>> -OStream& operator<<(OStream& os, const Map& map) -{ - os << '{'; - - auto next = std::begin(map); - const auto last = std::end(map); - - if (next != last) { - os << detail::quoted(next->first) << ": " - << detail::quoted(next->second); - ++next; - } - - while (next != last) { - os << ", " << detail::quoted(next->first) << ": " - << detail::quoted(next->second); - ++next; - } - - os << '}'; - return os; -} - -template , int>> -OStream& operator<<(OStream& os, const Tuple& tuple) -{ - const auto printer = detail::make_tuple_printer(tuple); - return printer(os, tuple); -} - -template , int>> -OStream& operator<<(OStream& os, const Opt& opt) -{ - if (opt) { - os << *opt; - } else { - os << "--"; - } - return os; -} - -#ifdef TCB_PRETTY_PRINT_HAVE_CPP17 -template -OStream& operator<<(OStream& os, const std::variant& var) -{ - const auto print_visitor = [&os](const auto& val) -> OStream& { - os << detail::quoted(val); - return os; - }; - return std::visit(print_visitor, var); -} - -#endif - -template -std::string to_string(const Container& cont) -{ - std::ostringstream ss; - ss << cont; - return ss.str(); -} - -} // namespace pretty_print -} // namespace tcb - -#endif \ No newline at end of file diff --git a/src/vendor/toml.hpp b/src/vendor/toml.hpp deleted file mode 100644 index 482a8393..00000000 --- a/src/vendor/toml.hpp +++ /dev/null @@ -1,17174 +0,0 @@ -//---------------------------------------------------------------------------------------------------------------------- -// -// toml++ v3.2.0 -// https://github.com/marzer/tomlplusplus -// SPDX-License-Identifier: MIT -// -//---------------------------------------------------------------------------------------------------------------------- -// -// - THIS FILE WAS ASSEMBLED FROM MULTIPLE HEADER FILES BY A SCRIPT - PLEASE DON'T EDIT IT DIRECTLY - -// -// If you wish to submit a contribution to toml++, hooray and thanks! Before you crack on, please be aware that this -// file was assembled from a number of smaller files by a python script, and code contributions should not be made -// against it directly. You should instead make your changes in the relevant source file(s). The file names of the files -// that contributed to this header can be found at the beginnings and ends of the corresponding sections of this file. -// -//---------------------------------------------------------------------------------------------------------------------- -// -// TOML Language Specifications: -// latest: https://github.com/toml-lang/toml/blob/master/README.md -// v1.0.0: https://toml.io/en/v1.0.0 -// v0.5.0: https://toml.io/en/v0.5.0 -// changelog: https://github.com/toml-lang/toml/blob/master/CHANGELOG.md -// -//---------------------------------------------------------------------------------------------------------------------- -// -// MIT License -// -// Copyright (c) Mark Gillard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the -// Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// -//---------------------------------------------------------------------------------------------------------------------- -#ifndef TOMLPLUSPLUS_H -#define TOMLPLUSPLUS_H - -#define INCLUDE_TOMLPLUSPLUS_H // old guard name used pre-v3 - -//******** impl/preprocessor.h *************************************************************************************** - -#ifndef __cplusplus -#error toml++ is a C++ library. -#endif -#ifdef _MSVC_LANG -#define TOML_CPP _MSVC_LANG -#else -#define TOML_CPP __cplusplus -#endif -#if TOML_CPP >= 202002L -#undef TOML_CPP -#define TOML_CPP 20 -#elif TOML_CPP >= 201703L -#undef TOML_CPP -#define TOML_CPP 17 -#else -#if TOML_CPP < 201103L -#error toml++ requires C++17 or higher. For a pre-C++11 TOML library see https://github.com/ToruNiina/Boost.toml -#elif TOML_CPP < 201703L -#error toml++ requires C++17 or higher. For a C++11 TOML library see https://github.com/ToruNiina/toml11 -#endif -#endif - -#ifdef __clang__ -#define TOML_CLANG __clang_major__ -#else -#define TOML_CLANG 0 -#endif -#ifdef __INTEL_COMPILER -#define TOML_ICC __INTEL_COMPILER -#ifdef __ICL -#define TOML_ICC_CL TOML_ICC -#else -#define TOML_ICC_CL 0 -#endif -#else -#define TOML_ICC 0 -#define TOML_ICC_CL 0 -#endif -#if defined(_MSC_VER) && !TOML_CLANG && !TOML_ICC -#define TOML_MSVC _MSC_VER -#else -#define TOML_MSVC 0 -#endif -#if defined(__GNUC__) && !TOML_CLANG && !TOML_ICC -#define TOML_GCC __GNUC__ -#else -#define TOML_GCC 0 -#endif -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || defined(__CYGWIN__) -#define TOML_WINDOWS 1 -#else -#define TOML_WINDOWS 0 -#endif -#if defined(DOXYGEN) || defined(__DOXYGEN__) || defined(__POXY__) || defined(__poxy__) -#define TOML_DOXYGEN 1 -#else -#define TOML_DOXYGEN 0 -#endif -#ifdef __INTELLISENSE__ -#define TOML_INTELLISENSE 1 -#else -#define TOML_INTELLISENSE 0 -#endif -#if defined(__aarch64__) || defined(__ARM_ARCH_ISA_A64) || defined(_M_ARM64) || defined(__ARM_64BIT_STATE) \ - || defined(__arm__) || defined(_M_ARM) || defined(__ARM_32BIT_STATE) -#define TOML_ARM 1 -#else -#define TOML_ARM 0 -#endif - -// TOML_HAS_INCLUDE -#ifdef __has_include -#define TOML_HAS_INCLUDE(header) __has_include(header) -#else -#define TOML_HAS_INCLUDE(header) 0 -#endif - -#ifdef __has_builtin -#define TOML_HAS_BUILTIN(name) __has_builtin(name) -#else -#define TOML_HAS_BUILTIN(name) 0 -#endif - -// TOML_HAS_FEATURE -#ifdef __has_feature -#define TOML_HAS_FEATURE(name) __has_feature(name) -#else -#define TOML_HAS_FEATURE(name) 0 -#endif - -// TOML_HAS_ATTR -#ifdef __has_attribute -#define TOML_HAS_ATTR(attr) __has_attribute(attr) -#else -#define TOML_HAS_ATTR(attr) 0 -#endif - -// TOML_HAS_CPP_ATTR -#ifdef __has_cpp_attribute -#define TOML_HAS_CPP_ATTR(attr) __has_cpp_attribute(attr) -#else -#define TOML_HAS_CPP_ATTR(attr) 0 -#endif - -// TOML_COMPILER_HAS_EXCEPTIONS -#if defined(__EXCEPTIONS) || defined(_CPPUNWIND) || defined(__cpp_exceptions) -#define TOML_COMPILER_HAS_EXCEPTIONS 1 -#else -#define TOML_COMPILER_HAS_EXCEPTIONS 0 -#endif - -// TOML_COMPILER_HAS_RTTI -#if defined(_CPPRTTI) || defined(__GXX_RTTI) || TOML_HAS_FEATURE(cxx_rtti) -#define TOML_COMPILER_HAS_RTTI 1 -#else -#define TOML_COMPILER_HAS_RTTI 0 -#endif - -// TOML_ATTR (gnu attributes) -#if TOML_CLANG || TOML_GCC || defined(__GNUC__) -#define TOML_ATTR(...) __attribute__((__VA_ARGS__)) -#else -#define TOML_ATTR(...) -#endif - -// TOML_DECLSPEC (msvc attributes) -#ifdef _MSC_VER -#define TOML_DECLSPEC(...) __declspec(__VA_ARGS__) -#else -#define TOML_DECLSPEC(...) -#endif - -// TOML_CONCAT -#define TOML_CONCAT_1(x, y) x##y -#define TOML_CONCAT(x, y) TOML_CONCAT_1(x, y) - -// TOML_MAKE_STRING -#define TOML_MAKE_STRING_1(s) #s -#define TOML_MAKE_STRING(s) TOML_MAKE_STRING_1(s) - -// TOML_PRAGMA_XXXX (compiler-specific pragmas) -#if TOML_CLANG -#define TOML_PRAGMA_CLANG(decl) _Pragma(TOML_MAKE_STRING(clang decl)) -#else -#define TOML_PRAGMA_CLANG(decl) -#endif -#if TOML_CLANG >= 9 -#define TOML_PRAGMA_CLANG_GE_9(decl) TOML_PRAGMA_CLANG(decl) -#else -#define TOML_PRAGMA_CLANG_GE_9(decl) -#endif -#if TOML_CLANG >= 10 -#define TOML_PRAGMA_CLANG_GE_10(decl) TOML_PRAGMA_CLANG(decl) -#else -#define TOML_PRAGMA_CLANG_GE_10(decl) -#endif -#if TOML_CLANG >= 11 -#define TOML_PRAGMA_CLANG_GE_11(decl) TOML_PRAGMA_CLANG(decl) -#else -#define TOML_PRAGMA_CLANG_GE_11(decl) -#endif -#if TOML_GCC -#define TOML_PRAGMA_GCC(decl) _Pragma(TOML_MAKE_STRING(GCC decl)) -#else -#define TOML_PRAGMA_GCC(decl) -#endif -#if TOML_MSVC -#define TOML_PRAGMA_MSVC(...) __pragma(__VA_ARGS__) -#else -#define TOML_PRAGMA_MSVC(...) -#endif -#if TOML_ICC -#define TOML_PRAGMA_ICC(...) __pragma(__VA_ARGS__) -#else -#define TOML_PRAGMA_ICC(...) -#endif - -// TOML_ALWAYS_INLINE -#ifdef _MSC_VER -#define TOML_ALWAYS_INLINE __forceinline -#elif TOML_GCC || TOML_CLANG || TOML_HAS_ATTR(__always_inline__) -#define TOML_ALWAYS_INLINE \ - TOML_ATTR(__always_inline__) \ - inline -#else -#define TOML_ALWAYS_INLINE inline -#endif - -// TOML_NEVER_INLINE -#ifdef _MSC_VER -#define TOML_NEVER_INLINE TOML_DECLSPEC(noinline) -#elif TOML_GCC || TOML_CLANG || TOML_HAS_ATTR(__noinline__) -#define TOML_NEVER_INLINE TOML_ATTR(__noinline__) -#else -#define TOML_NEVER_INLINE -#endif - -// MSVC attributes -#define TOML_ABSTRACT_INTERFACE TOML_DECLSPEC(novtable) -#define TOML_EMPTY_BASES TOML_DECLSPEC(empty_bases) - -// TOML_TRIVIAL_ABI -#if TOML_CLANG || TOML_HAS_ATTR(__trivial_abi__) -#define TOML_TRIVIAL_ABI TOML_ATTR(__trivial_abi__) -#else -#define TOML_TRIVIAL_ABI -#endif - -// TOML_NODISCARD -#if TOML_CPP >= 17 && TOML_HAS_CPP_ATTR(nodiscard) >= 201603 -#define TOML_NODISCARD [[nodiscard]] -#elif TOML_CLANG || TOML_GCC || TOML_HAS_ATTR(__warn_unused_result__) -#define TOML_NODISCARD TOML_ATTR(__warn_unused_result__) -#else -#define TOML_NODISCARD -#endif - -// TOML_NODISCARD_CTOR -#if TOML_CPP >= 17 && TOML_HAS_CPP_ATTR(nodiscard) >= 201907 -#define TOML_NODISCARD_CTOR [[nodiscard]] -#else -#define TOML_NODISCARD_CTOR -#endif - -// pure + const -// clang-format off -#ifdef NDEBUG - #define TOML_PURE TOML_DECLSPEC(noalias) TOML_ATTR(__pure__) - #define TOML_CONST TOML_DECLSPEC(noalias) TOML_ATTR(__const__) - #define TOML_PURE_GETTER TOML_NODISCARD TOML_PURE - #define TOML_CONST_GETTER TOML_NODISCARD TOML_CONST - #define TOML_PURE_INLINE_GETTER TOML_NODISCARD TOML_ALWAYS_INLINE TOML_PURE - #define TOML_CONST_INLINE_GETTER TOML_NODISCARD TOML_ALWAYS_INLINE TOML_CONST -#else - #define TOML_PURE - #define TOML_CONST - #define TOML_PURE_GETTER TOML_NODISCARD - #define TOML_CONST_GETTER TOML_NODISCARD - #define TOML_PURE_INLINE_GETTER TOML_NODISCARD TOML_ALWAYS_INLINE - #define TOML_CONST_INLINE_GETTER TOML_NODISCARD TOML_ALWAYS_INLINE -#endif -// clang-format on - -// TOML_ASSUME -#ifdef _MSC_VER -#define TOML_ASSUME(...) __assume(__VA_ARGS__) -#elif TOML_ICC || TOML_CLANG || TOML_HAS_BUILTIN(__builtin_assume) -#define TOML_ASSUME(...) __builtin_assume(__VA_ARGS__) -#else -#define TOML_ASSUME(...) static_assert(true) -#endif - -// TOML_UNREACHABLE -#ifdef _MSC_VER -#define TOML_UNREACHABLE __assume(0) -#elif TOML_ICC || TOML_CLANG || TOML_GCC || TOML_HAS_BUILTIN(__builtin_unreachable) -#define TOML_UNREACHABLE __builtin_unreachable() -#else -#define TOML_UNREACHABLE static_assert(true) -#endif - -// TOML_LIKELY -#if TOML_CPP >= 20 && TOML_HAS_CPP_ATTR(likely) >= 201803 -#define TOML_LIKELY(...) (__VA_ARGS__) [[likely]] -#define TOML_LIKELY_CASE [[likely]] -#elif TOML_GCC || TOML_CLANG || TOML_HAS_BUILTIN(__builtin_expect) -#define TOML_LIKELY(...) (__builtin_expect(!!(__VA_ARGS__), 1)) -#else -#define TOML_LIKELY(...) (__VA_ARGS__) -#endif -#ifndef TOML_LIKELY_CASE -#define TOML_LIKELY_CASE -#endif - -// TOML_UNLIKELY -#if TOML_CPP >= 20 && TOML_HAS_CPP_ATTR(unlikely) >= 201803 -#define TOML_UNLIKELY(...) (__VA_ARGS__) [[unlikely]] -#define TOML_UNLIKELY_CASE [[unlikely]] -#elif TOML_GCC || TOML_CLANG || TOML_HAS_BUILTIN(__builtin_expect) -#define TOML_UNLIKELY(...) (__builtin_expect(!!(__VA_ARGS__), 0)) -#else -#define TOML_UNLIKELY(...) (__VA_ARGS__) -#endif -#ifndef TOML_UNLIKELY_CASE -#define TOML_UNLIKELY_CASE -#endif - -// TOML_FLAGS_ENUM -#if TOML_CLANG || TOML_HAS_ATTR(flag_enum) -#define TOML_FLAGS_ENUM __attribute__((flag_enum)) -#else -#define TOML_FLAGS_ENUM -#endif - -// TOML_OPEN_ENUM + TOML_CLOSED_ENUM -#if TOML_CLANG || TOML_HAS_ATTR(enum_extensibility) -#define TOML_OPEN_ENUM __attribute__((enum_extensibility(open))) -#define TOML_CLOSED_ENUM __attribute__((enum_extensibility(closed))) -#else -#define TOML_OPEN_ENUM -#define TOML_CLOSED_ENUM -#endif - -// TOML_OPEN_FLAGS_ENUM + TOML_CLOSED_FLAGS_ENUM -#define TOML_OPEN_FLAGS_ENUM TOML_OPEN_ENUM TOML_FLAGS_ENUM -#define TOML_CLOSED_FLAGS_ENUM TOML_CLOSED_ENUM TOML_FLAGS_ENUM - -// TOML_MAKE_FLAGS -#define TOML_MAKE_FLAGS_2(T, op, linkage) \ - TOML_CONST_INLINE_GETTER \ - linkage constexpr T operator op(T lhs, T rhs) noexcept \ - { \ - using under = std::underlying_type_t; \ - return static_cast(static_cast(lhs) op static_cast(rhs)); \ - } \ - \ - linkage constexpr T& operator TOML_CONCAT(op, =)(T & lhs, T rhs) noexcept \ - { \ - return lhs = (lhs op rhs); \ - } \ - \ - static_assert(true) -#define TOML_MAKE_FLAGS_1(T, linkage) \ - static_assert(std::is_enum_v); \ - \ - TOML_MAKE_FLAGS_2(T, &, linkage); \ - TOML_MAKE_FLAGS_2(T, |, linkage); \ - TOML_MAKE_FLAGS_2(T, ^, linkage); \ - \ - TOML_CONST_INLINE_GETTER \ - linkage constexpr T operator~(T val) noexcept \ - { \ - using under = std::underlying_type_t; \ - return static_cast(~static_cast(val)); \ - } \ - \ - TOML_CONST_INLINE_GETTER \ - linkage constexpr bool operator!(T val) noexcept \ - { \ - using under = std::underlying_type_t; \ - return !static_cast(val); \ - } \ - \ - static_assert(true) -#define TOML_MAKE_FLAGS(T) TOML_MAKE_FLAGS_1(T, ) - -#define TOML_UNUSED(...) static_cast(__VA_ARGS__) - -#define TOML_DELETE_DEFAULTS(T) \ - T(const T&) = delete; \ - T(T&&) = delete; \ - T& operator=(const T&) = delete; \ - T& operator=(T&&) = delete - -#define TOML_ASYMMETRICAL_EQUALITY_OPS(LHS, RHS, ...) \ - __VA_ARGS__ TOML_NODISCARD \ - friend bool operator==(RHS rhs, LHS lhs) noexcept \ - { \ - return lhs == rhs; \ - } \ - __VA_ARGS__ TOML_NODISCARD \ - friend bool operator!=(LHS lhs, RHS rhs) noexcept \ - { \ - return !(lhs == rhs); \ - } \ - __VA_ARGS__ TOML_NODISCARD \ - friend bool operator!=(RHS rhs, LHS lhs) noexcept \ - { \ - return !(lhs == rhs); \ - } \ - static_assert(true) - -#define TOML_EVAL_BOOL_1(T, F) T -#define TOML_EVAL_BOOL_0(T, F) F - -#if !defined(__POXY__) && !defined(POXY_IMPLEMENTATION_DETAIL) -#define POXY_IMPLEMENTATION_DETAIL(...) __VA_ARGS__ -#endif - -// COMPILER-SPECIFIC WARNING MANAGEMENT - -#if TOML_CLANG - -#define TOML_PUSH_WARNINGS \ - TOML_PRAGMA_CLANG(diagnostic push) \ - static_assert(true) - -#define TOML_DISABLE_SWITCH_WARNINGS \ - TOML_PRAGMA_CLANG(diagnostic ignored "-Wswitch") \ - static_assert(true) - -#define TOML_DISABLE_ARITHMETIC_WARNINGS \ - TOML_PRAGMA_CLANG(diagnostic ignored "-Wfloat-equal") \ - TOML_PRAGMA_CLANG(diagnostic ignored "-Wdouble-promotion") \ - TOML_PRAGMA_CLANG(diagnostic ignored "-Wchar-subscripts") \ - TOML_PRAGMA_CLANG(diagnostic ignored "-Wshift-sign-overflow") \ - static_assert(true) - -#define TOML_DISABLE_SPAM_WARNINGS \ - TOML_PRAGMA_CLANG_GE_9(diagnostic ignored "-Wctad-maybe-unsupported") \ - TOML_PRAGMA_CLANG_GE_10(diagnostic ignored "-Wzero-as-null-pointer-constant") \ - TOML_PRAGMA_CLANG_GE_11(diagnostic ignored "-Wsuggest-destructor-override") \ - TOML_PRAGMA_CLANG(diagnostic ignored "-Wweak-vtables") \ - TOML_PRAGMA_CLANG(diagnostic ignored "-Wweak-template-vtables") \ - TOML_PRAGMA_CLANG(diagnostic ignored "-Wdouble-promotion") \ - TOML_PRAGMA_CLANG(diagnostic ignored "-Wchar-subscripts") \ - TOML_PRAGMA_CLANG(diagnostic ignored "-Wmissing-field-initializers") \ - TOML_PRAGMA_CLANG(diagnostic ignored "-Wpadded") \ - static_assert(true) - -#define TOML_POP_WARNINGS \ - TOML_PRAGMA_CLANG(diagnostic pop) \ - static_assert(true) - -#define TOML_DISABLE_WARNINGS \ - TOML_PRAGMA_CLANG(diagnostic push) \ - TOML_PRAGMA_CLANG(diagnostic ignored "-Weverything") \ - static_assert(true, "") - -#define TOML_ENABLE_WARNINGS \ - TOML_PRAGMA_CLANG(diagnostic pop) \ - static_assert(true) - -#define TOML_SIMPLE_STATIC_ASSERT_MESSAGES 1 - -#elif TOML_MSVC - -#define TOML_PUSH_WARNINGS \ - __pragma(warning(push)) \ - static_assert(true) - -#if TOML_HAS_INCLUDE() -#pragma warning(push, 0) -#include -#pragma warning(pop) -#define TOML_DISABLE_CODE_ANALYSIS_WARNINGS \ - __pragma(warning(disable : ALL_CODE_ANALYSIS_WARNINGS)) \ - static_assert(true) -#else -#define TOML_DISABLE_CODE_ANALYSIS_WARNINGS static_assert(true) -#endif - -#define TOML_DISABLE_SWITCH_WARNINGS \ - __pragma(warning(disable : 4061)) \ - __pragma(warning(disable : 4062)) \ - __pragma(warning(disable : 4063)) \ - __pragma(warning(disable : 26819)) /* cg: unannotated fallthrough */ \ - static_assert(true) - -#define TOML_DISABLE_SPAM_WARNINGS \ - __pragma(warning(disable : 4127)) /* conditional expr is constant */ \ - __pragma(warning(disable : 4324)) /* structure was padded due to alignment specifier */ \ - __pragma(warning(disable : 4348)) \ - __pragma(warning(disable : 4464)) /* relative include path contains '..' */ \ - __pragma(warning(disable : 4505)) /* unreferenced local function removed */ \ - __pragma(warning(disable : 4514)) /* unreferenced inline function has been removed */ \ - __pragma(warning(disable : 4582)) /* constructor is not implicitly called */ \ - __pragma(warning(disable : 4623)) /* default constructor was implicitly defined as deleted */ \ - __pragma(warning(disable : 4625)) /* copy constructor was implicitly defined as deleted */ \ - __pragma(warning(disable : 4626)) /* assignment operator was implicitly defined as deleted */ \ - __pragma(warning(disable : 4710)) /* function not inlined */ \ - __pragma(warning(disable : 4711)) /* function selected for automatic expansion */ \ - __pragma(warning(disable : 4820)) /* N bytes padding added */ \ - __pragma(warning(disable : 4946)) /* reinterpret_cast used between related classes */ \ - __pragma(warning(disable : 5026)) /* move constructor was implicitly defined as deleted */ \ - __pragma(warning(disable : 5027)) /* move assignment operator was implicitly defined as deleted */ \ - __pragma(warning(disable : 5039)) /* potentially throwing function passed to 'extern "C"' function */ \ - __pragma(warning(disable : 5045)) /* Compiler will insert Spectre mitigation */ \ - __pragma(warning(disable : 26451)) \ - __pragma(warning(disable : 26490)) \ - __pragma(warning(disable : 26495)) \ - __pragma(warning(disable : 26812)) \ - __pragma(warning(disable : 26819)) \ - static_assert(true) - -#define TOML_DISABLE_ARITHMETIC_WARNINGS \ - __pragma(warning(disable : 4365)) /* argument signed/unsigned mismatch */ \ - __pragma(warning(disable : 4738)) /* storing 32-bit float result in memory */ \ - __pragma(warning(disable : 5219)) /* implicit conversion from integral to float */ \ - static_assert(true) - -#define TOML_POP_WARNINGS \ - __pragma(warning(pop)) \ - static_assert(true) - -#define TOML_DISABLE_WARNINGS \ - __pragma(warning(push, 0)) \ - __pragma(warning(disable : 4348)) \ - __pragma(warning(disable : 4668)) \ - __pragma(warning(disable : 5105)) \ - TOML_DISABLE_CODE_ANALYSIS_WARNINGS; \ - TOML_DISABLE_SWITCH_WARNINGS; \ - TOML_DISABLE_SPAM_WARNINGS; \ - TOML_DISABLE_ARITHMETIC_WARNINGS; \ - static_assert(true) - -#define TOML_ENABLE_WARNINGS TOML_POP_WARNINGS - -#elif TOML_ICC - -#define TOML_PUSH_WARNINGS \ - __pragma(warning(push)) \ - static_assert(true) - -#define TOML_DISABLE_SPAM_WARNINGS \ - __pragma(warning(disable : 82)) /* storage class is not first */ \ - __pragma(warning(disable : 111)) /* statement unreachable (false-positive) */ \ - __pragma(warning(disable : 869)) /* unreferenced parameter */ \ - __pragma(warning(disable : 1011)) /* missing return (false-positive) */ \ - __pragma(warning(disable : 2261)) /* assume expr side-effects discarded */ \ - static_assert(true) - -#define TOML_POP_WARNINGS \ - __pragma(warning(pop)) \ - static_assert(true) - -#define TOML_DISABLE_WARNINGS \ - __pragma(warning(push, 0)) \ - TOML_DISABLE_SPAM_WARNINGS - -#define TOML_ENABLE_WARNINGS \ - __pragma(warning(pop)) \ - static_assert(true) - -#elif TOML_GCC - -#define TOML_PUSH_WARNINGS \ - TOML_PRAGMA_GCC(diagnostic push) \ - static_assert(true) - -#define TOML_DISABLE_SWITCH_WARNINGS \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wswitch") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wswitch-enum") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wswitch-default") \ - static_assert(true) - -#define TOML_DISABLE_ARITHMETIC_WARNINGS \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wfloat-equal") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wsign-conversion") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wchar-subscripts") \ - static_assert(true) - -#define TOML_DISABLE_SUGGEST_ATTR_WARNINGS \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wsuggest-attribute=const") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wsuggest-attribute=pure") \ - static_assert(true) - -#define TOML_DISABLE_SPAM_WARNINGS \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wpadded") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wcast-align") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wcomment") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wtype-limits") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wuseless-cast") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wchar-subscripts") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wsubobject-linkage") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wmissing-field-initializers") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wmaybe-uninitialized") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wnoexcept") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wnull-dereference") \ - static_assert(true) - -#define TOML_POP_WARNINGS \ - TOML_PRAGMA_GCC(diagnostic pop) \ - static_assert(true) - -#define TOML_DISABLE_WARNINGS \ - TOML_PRAGMA_GCC(diagnostic push) \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wall") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wextra") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wpedantic") \ - TOML_DISABLE_SWITCH_WARNINGS; \ - TOML_DISABLE_ARITHMETIC_WARNINGS; \ - TOML_DISABLE_SUGGEST_ATTR_WARNINGS; \ - TOML_DISABLE_SPAM_WARNINGS; \ - static_assert(true) - -#define TOML_ENABLE_WARNINGS \ - TOML_PRAGMA_GCC(diagnostic pop) \ - static_assert(true) - -#endif - -#ifndef TOML_PUSH_WARNINGS -#define TOML_PUSH_WARNINGS static_assert(true) -#endif -#ifndef TOML_DISABLE_CODE_ANALYSIS_WARNINGS -#define TOML_DISABLE_CODE_ANALYSIS_WARNINGS static_assert(true) -#endif -#ifndef TOML_DISABLE_SWITCH_WARNINGS -#define TOML_DISABLE_SWITCH_WARNINGS static_assert(true) -#endif -#ifndef TOML_DISABLE_SUGGEST_ATTR_WARNINGS -#define TOML_DISABLE_SUGGEST_ATTR_WARNINGS static_assert(true) -#endif -#ifndef TOML_DISABLE_SPAM_WARNINGS -#define TOML_DISABLE_SPAM_WARNINGS static_assert(true) -#endif -#ifndef TOML_DISABLE_ARITHMETIC_WARNINGS -#define TOML_DISABLE_ARITHMETIC_WARNINGS static_assert(true) -#endif -#ifndef TOML_POP_WARNINGS -#define TOML_POP_WARNINGS static_assert(true) -#endif -#ifndef TOML_DISABLE_WARNINGS -#define TOML_DISABLE_WARNINGS static_assert(true) -#endif -#ifndef TOML_ENABLE_WARNINGS -#define TOML_ENABLE_WARNINGS static_assert(true) -#endif -#ifndef TOML_SIMPLE_STATIC_ASSERT_MESSAGES -#define TOML_SIMPLE_STATIC_ASSERT_MESSAGES 0 -#endif - -#ifdef TOML_CONFIG_HEADER -#include TOML_CONFIG_HEADER -#endif - -// is the library being built as a shared lib/dll using meson and friends? -#ifndef TOML_SHARED_LIB -#define TOML_SHARED_LIB 0 -#endif - -// header-only mode -#if !defined(TOML_HEADER_ONLY) && defined(TOML_ALL_INLINE) // was TOML_ALL_INLINE pre-2.0 -#define TOML_HEADER_ONLY TOML_ALL_INLINE -#endif -#if !defined(TOML_HEADER_ONLY) || (defined(TOML_HEADER_ONLY) && TOML_HEADER_ONLY) || TOML_INTELLISENSE -#undef TOML_HEADER_ONLY -#define TOML_HEADER_ONLY 1 -#endif -#if TOML_DOXYGEN || TOML_SHARED_LIB -#undef TOML_HEADER_ONLY -#define TOML_HEADER_ONLY 0 -#endif - -// internal implementation switch -#if defined(TOML_IMPLEMENTATION) || TOML_HEADER_ONLY -#undef TOML_IMPLEMENTATION -#define TOML_IMPLEMENTATION 1 -#else -#define TOML_IMPLEMENTATION 0 -#endif - -// dll/shared lib function exports (legacy - TOML_API was the old name for this setting) -#if !defined(TOML_EXPORTED_MEMBER_FUNCTION) && !defined(TOML_EXPORTED_STATIC_FUNCTION) \ - && !defined(TOML_EXPORTED_FREE_FUNCTION) && !defined(TOML_EXPORTED_CLASS) && defined(TOML_API) -#define TOML_EXPORTED_MEMBER_FUNCTION TOML_API -#define TOML_EXPORTED_STATIC_FUNCTION TOML_API -#define TOML_EXPORTED_FREE_FUNCTION TOML_API -#endif - -// dll/shared lib exports -#if TOML_SHARED_LIB -#undef TOML_API -#undef TOML_EXPORTED_CLASS -#undef TOML_EXPORTED_MEMBER_FUNCTION -#undef TOML_EXPORTED_STATIC_FUNCTION -#undef TOML_EXPORTED_FREE_FUNCTION -#if TOML_WINDOWS -#if TOML_IMPLEMENTATION -#define TOML_EXPORTED_CLASS __declspec(dllexport) -#define TOML_EXPORTED_FREE_FUNCTION __declspec(dllexport) -#else -#define TOML_EXPORTED_CLASS __declspec(dllimport) -#define TOML_EXPORTED_FREE_FUNCTION __declspec(dllimport) -#endif -#ifndef TOML_CALLCONV -#define TOML_CALLCONV __cdecl -#endif -#elif defined(__GNUC__) && __GNUC__ >= 4 -#define TOML_EXPORTED_CLASS __attribute__((visibility("default"))) -#define TOML_EXPORTED_MEMBER_FUNCTION __attribute__((visibility("default"))) -#define TOML_EXPORTED_STATIC_FUNCTION __attribute__((visibility("default"))) -#define TOML_EXPORTED_FREE_FUNCTION __attribute__((visibility("default"))) -#endif -#endif -#ifndef TOML_EXPORTED_CLASS -#define TOML_EXPORTED_CLASS -#endif -#ifndef TOML_EXPORTED_MEMBER_FUNCTION -#define TOML_EXPORTED_MEMBER_FUNCTION -#endif -#ifndef TOML_EXPORTED_STATIC_FUNCTION -#define TOML_EXPORTED_STATIC_FUNCTION -#endif -#ifndef TOML_EXPORTED_FREE_FUNCTION -#define TOML_EXPORTED_FREE_FUNCTION -#endif - -// experimental language features -#if !defined(TOML_ENABLE_UNRELEASED_FEATURES) && defined(TOML_UNRELEASED_FEATURES) // was TOML_UNRELEASED_FEATURES - // pre-3.0 -#define TOML_ENABLE_UNRELEASED_FEATURES TOML_UNRELEASED_FEATURES -#endif -#if (defined(TOML_ENABLE_UNRELEASED_FEATURES) && TOML_ENABLE_UNRELEASED_FEATURES) || TOML_INTELLISENSE -#undef TOML_ENABLE_UNRELEASED_FEATURES -#define TOML_ENABLE_UNRELEASED_FEATURES 1 -#endif -#ifndef TOML_ENABLE_UNRELEASED_FEATURES -#define TOML_ENABLE_UNRELEASED_FEATURES 0 -#endif - -// parser -#if !defined(TOML_ENABLE_PARSER) && defined(TOML_PARSER) // was TOML_PARSER pre-3.0 -#define TOML_ENABLE_PARSER TOML_PARSER -#endif -#if !defined(TOML_ENABLE_PARSER) || (defined(TOML_ENABLE_PARSER) && TOML_ENABLE_PARSER) || TOML_INTELLISENSE -#undef TOML_ENABLE_PARSER -#define TOML_ENABLE_PARSER 1 -#endif - -// formatters -#if !defined(TOML_ENABLE_FORMATTERS) || (defined(TOML_ENABLE_FORMATTERS) && TOML_ENABLE_FORMATTERS) || TOML_INTELLISENSE -#undef TOML_ENABLE_FORMATTERS -#define TOML_ENABLE_FORMATTERS 1 -#endif - -// SIMD -#if !defined(TOML_ENABLE_SIMD) || (defined(TOML_ENABLE_SIMD) && TOML_ENABLE_SIMD) || TOML_INTELLISENSE -#undef TOML_ENABLE_SIMD -#define TOML_ENABLE_SIMD 1 -#endif - -// windows compat -#if !defined(TOML_ENABLE_WINDOWS_COMPAT) && defined(TOML_WINDOWS_COMPAT) // was TOML_WINDOWS_COMPAT pre-3.0 -#define TOML_ENABLE_WINDOWS_COMPAT TOML_WINDOWS_COMPAT -#endif -#if !defined(TOML_ENABLE_WINDOWS_COMPAT) || (defined(TOML_ENABLE_WINDOWS_COMPAT) && TOML_ENABLE_WINDOWS_COMPAT) \ - || TOML_INTELLISENSE -#undef TOML_ENABLE_WINDOWS_COMPAT -#define TOML_ENABLE_WINDOWS_COMPAT 1 -#endif - -#if !TOML_WINDOWS -#undef TOML_ENABLE_WINDOWS_COMPAT -#define TOML_ENABLE_WINDOWS_COMPAT 0 -#endif - -#ifndef TOML_INCLUDE_WINDOWS_H -#define TOML_INCLUDE_WINDOWS_H 0 -#endif - -// custom optional -#ifdef TOML_OPTIONAL_TYPE -#define TOML_HAS_CUSTOM_OPTIONAL_TYPE 1 -#else -#define TOML_HAS_CUSTOM_OPTIONAL_TYPE 0 -#endif - -// exceptions (library use) -#if TOML_COMPILER_HAS_EXCEPTIONS -#if !defined(TOML_EXCEPTIONS) || (defined(TOML_EXCEPTIONS) && TOML_EXCEPTIONS) -#undef TOML_EXCEPTIONS -#define TOML_EXCEPTIONS 1 -#endif -#else -#if defined(TOML_EXCEPTIONS) && TOML_EXCEPTIONS -#error TOML_EXCEPTIONS was explicitly enabled but exceptions are disabled/unsupported by the compiler. -#endif -#undef TOML_EXCEPTIONS -#define TOML_EXCEPTIONS 0 -#endif - -// calling convention for static/free/friend functions -#ifndef TOML_CALLCONV -#define TOML_CALLCONV -#endif - -#ifndef TOML_UNDEF_MACROS -#define TOML_UNDEF_MACROS 1 -#endif - -#ifndef TOML_MAX_NESTED_VALUES -#define TOML_MAX_NESTED_VALUES 256 -// this refers to the depth of nested values, e.g. inline tables and arrays. -// 256 is crazy high! if you're hitting this limit with real input, TOML is probably the wrong tool for the job... -#endif - -#ifdef TOML_CHAR_8_STRINGS -#if TOML_CHAR_8_STRINGS -#error TOML_CHAR_8_STRINGS was removed in toml++ 2.0.0; all value setters and getters now work with char8_t strings implicitly. -#endif -#endif - -#ifdef TOML_LARGE_FILES -#if !TOML_LARGE_FILES -#error Support for !TOML_LARGE_FILES (i.e. 'small files') was removed in toml++ 3.0.0. -#endif -#endif - -#ifndef TOML_LIFETIME_HOOKS -#define TOML_LIFETIME_HOOKS 0 -#endif - -#ifdef NDEBUG -#undef TOML_ASSERT -#define TOML_ASSERT(expr) static_assert(true) -#endif -#ifndef TOML_ASSERT -#ifndef assert -TOML_DISABLE_WARNINGS; -#include -TOML_ENABLE_WARNINGS; -#endif -#define TOML_ASSERT(expr) assert(expr) -#endif -#ifdef NDEBUG -#define TOML_ASSERT_ASSUME(expr) TOML_ASSUME(expr) -#else -#define TOML_ASSERT_ASSUME(expr) TOML_ASSERT(expr) -#endif - -#if !defined(TOML_FLOAT_CHARCONV) && (TOML_GCC || TOML_CLANG || (TOML_ICC && !TOML_ICC_CL)) -// not supported by any version of GCC or Clang as of 26/11/2020 -// not supported by any version of ICC on Linux as of 11/01/2021 -#define TOML_FLOAT_CHARCONV 0 -#endif -#if !defined(TOML_INT_CHARCONV) && (defined(__EMSCRIPTEN__) || defined(__APPLE__)) -// causes link errors on emscripten -// causes Mac OS SDK version errors on some versions of Apple Clang -#define TOML_INT_CHARCONV 0 -#endif -#ifndef TOML_INT_CHARCONV -#define TOML_INT_CHARCONV 1 -#endif -#ifndef TOML_FLOAT_CHARCONV -#define TOML_FLOAT_CHARCONV 1 -#endif -#if (TOML_INT_CHARCONV || TOML_FLOAT_CHARCONV) && !TOML_HAS_INCLUDE() -#undef TOML_INT_CHARCONV -#undef TOML_FLOAT_CHARCONV -#define TOML_INT_CHARCONV 0 -#define TOML_FLOAT_CHARCONV 0 -#endif - -#if defined(__cpp_concepts) && __cpp_concepts >= 201907 -#define TOML_REQUIRES(...) requires(__VA_ARGS__) -#else -#define TOML_REQUIRES(...) -#endif -#define TOML_ENABLE_IF(...) , typename std::enable_if<(__VA_ARGS__), int>::type = 0 -#define TOML_CONSTRAINED_TEMPLATE(condition, ...) \ - template <__VA_ARGS__ TOML_ENABLE_IF(condition)> \ - TOML_REQUIRES(condition) -#define TOML_HIDDEN_CONSTRAINT(condition, ...) TOML_CONSTRAINED_TEMPLATE(condition, __VA_ARGS__) - -// clang-format off - -#ifdef __FLT16_MANT_DIG__ - #if __FLT_RADIX__ == 2 \ - && __FLT16_MANT_DIG__ == 11 \ - && __FLT16_DIG__ == 3 \ - && __FLT16_MIN_EXP__ == -13 \ - && __FLT16_MIN_10_EXP__ == -4 \ - && __FLT16_MAX_EXP__ == 16 \ - && __FLT16_MAX_10_EXP__ == 4 - #if TOML_ARM && (TOML_GCC || TOML_CLANG) - #define TOML_FP16 __fp16 - #endif - #if TOML_ARM && TOML_CLANG // not present in g++ - #define TOML_FLOAT16 _Float16 - #endif - #endif -#endif - -#if defined(__SIZEOF_FLOAT128__) \ - && defined(__FLT128_MANT_DIG__) \ - && defined(__LDBL_MANT_DIG__) \ - && __FLT128_MANT_DIG__ > __LDBL_MANT_DIG__ - #define TOML_FLOAT128 __float128 -#endif - -#ifdef __SIZEOF_INT128__ - #define TOML_INT128 __int128_t - #define TOML_UINT128 __uint128_t -#endif - -// clang-format on - -// clang-format off - -//******** impl/version.h ******************************************************************************************** - -#define TOML_LIB_MAJOR 3 -#define TOML_LIB_MINOR 2 -#define TOML_LIB_PATCH 0 - -#define TOML_LANG_MAJOR 1 -#define TOML_LANG_MINOR 0 -#define TOML_LANG_PATCH 0 - -//******** impl/preprocessor.h *************************************************************************************** - -#define TOML_LIB_SINGLE_HEADER 1 - -#define TOML_MAKE_VERSION(major, minor, patch) \ - ((major) * 10000 + (minor) * 100 + (patch)) - -#if TOML_ENABLE_UNRELEASED_FEATURES - #define TOML_LANG_EFFECTIVE_VERSION \ - TOML_MAKE_VERSION(TOML_LANG_MAJOR, TOML_LANG_MINOR, TOML_LANG_PATCH+1) -#else - #define TOML_LANG_EFFECTIVE_VERSION \ - TOML_MAKE_VERSION(TOML_LANG_MAJOR, TOML_LANG_MINOR, TOML_LANG_PATCH) -#endif - -#define TOML_LANG_HIGHER_THAN(major, minor, patch) \ - (TOML_LANG_EFFECTIVE_VERSION > TOML_MAKE_VERSION(major, minor, patch)) - -#define TOML_LANG_AT_LEAST(major, minor, patch) \ - (TOML_LANG_EFFECTIVE_VERSION >= TOML_MAKE_VERSION(major, minor, patch)) - -#define TOML_LANG_UNRELEASED \ - TOML_LANG_HIGHER_THAN(TOML_LANG_MAJOR, TOML_LANG_MINOR, TOML_LANG_PATCH) - -#ifndef TOML_ABI_NAMESPACES - #if TOML_DOXYGEN - #define TOML_ABI_NAMESPACES 0 - #else - #define TOML_ABI_NAMESPACES 1 - #endif -#endif -#if TOML_ABI_NAMESPACES - #define TOML_NAMESPACE_START namespace toml { inline namespace TOML_CONCAT(v, TOML_LIB_MAJOR) - #define TOML_NAMESPACE_END } static_assert(true) - #define TOML_NAMESPACE ::toml::TOML_CONCAT(v, TOML_LIB_MAJOR) - #define TOML_ABI_NAMESPACE_START(name) inline namespace name { static_assert(true) - #define TOML_ABI_NAMESPACE_BOOL(cond, T, F) TOML_ABI_NAMESPACE_START(TOML_CONCAT(TOML_EVAL_BOOL_, cond)(T, F)) - #define TOML_ABI_NAMESPACE_END } static_assert(true) -#else - #define TOML_NAMESPACE_START namespace toml - #define TOML_NAMESPACE_END static_assert(true) - #define TOML_NAMESPACE toml - #define TOML_ABI_NAMESPACE_START(...) static_assert(true) - #define TOML_ABI_NAMESPACE_BOOL(...) static_assert(true) - #define TOML_ABI_NAMESPACE_END static_assert(true) -#endif -#define TOML_IMPL_NAMESPACE_START TOML_NAMESPACE_START { namespace impl -#define TOML_IMPL_NAMESPACE_END } TOML_NAMESPACE_END -#if TOML_HEADER_ONLY - #define TOML_ANON_NAMESPACE_START static_assert(TOML_IMPLEMENTATION); TOML_IMPL_NAMESPACE_START - #define TOML_ANON_NAMESPACE_END TOML_IMPL_NAMESPACE_END - #define TOML_ANON_NAMESPACE TOML_NAMESPACE::impl - #define TOML_EXTERNAL_LINKAGE inline - #define TOML_INTERNAL_LINKAGE inline -#else - #define TOML_ANON_NAMESPACE_START static_assert(TOML_IMPLEMENTATION); \ - using namespace toml; \ - namespace - #define TOML_ANON_NAMESPACE_END static_assert(true) - #define TOML_ANON_NAMESPACE - #define TOML_EXTERNAL_LINKAGE - #define TOML_INTERNAL_LINKAGE static -#endif - -// clang-format on - -// clang-format off - -#if TOML_SIMPLE_STATIC_ASSERT_MESSAGES - - #define TOML_SA_NEWLINE " " - #define TOML_SA_LIST_SEP ", " - #define TOML_SA_LIST_BEG " (" - #define TOML_SA_LIST_END ")" - #define TOML_SA_LIST_NEW " " - #define TOML_SA_LIST_NXT ", " - -#else - - #define TOML_SA_NEWLINE "\n| " - #define TOML_SA_LIST_SEP TOML_SA_NEWLINE " - " - #define TOML_SA_LIST_BEG TOML_SA_LIST_SEP - #define TOML_SA_LIST_END - #define TOML_SA_LIST_NEW TOML_SA_NEWLINE TOML_SA_NEWLINE - #define TOML_SA_LIST_NXT TOML_SA_LIST_NEW - -#endif - -#define TOML_SA_NATIVE_VALUE_TYPE_LIST \ - TOML_SA_LIST_BEG "std::string" \ - TOML_SA_LIST_SEP "int64_t" \ - TOML_SA_LIST_SEP "double" \ - TOML_SA_LIST_SEP "bool" \ - TOML_SA_LIST_SEP "toml::date" \ - TOML_SA_LIST_SEP "toml::time" \ - TOML_SA_LIST_SEP "toml::date_time" \ - TOML_SA_LIST_END - -#define TOML_SA_NODE_TYPE_LIST \ - TOML_SA_LIST_BEG "toml::table" \ - TOML_SA_LIST_SEP "toml::array" \ - TOML_SA_LIST_SEP "toml::value" \ - TOML_SA_LIST_SEP "toml::value" \ - TOML_SA_LIST_SEP "toml::value" \ - TOML_SA_LIST_SEP "toml::value" \ - TOML_SA_LIST_SEP "toml::value" \ - TOML_SA_LIST_SEP "toml::value" \ - TOML_SA_LIST_SEP "toml::value" \ - TOML_SA_LIST_END - -#define TOML_SA_UNWRAPPED_NODE_TYPE_LIST \ - TOML_SA_LIST_NEW "A native TOML value type" \ - TOML_SA_NATIVE_VALUE_TYPE_LIST \ - \ - TOML_SA_LIST_NXT "A TOML node type" \ - TOML_SA_NODE_TYPE_LIST - -// clang-format on - -TOML_PUSH_WARNINGS; -TOML_DISABLE_SPAM_WARNINGS; -TOML_DISABLE_SWITCH_WARNINGS; -TOML_DISABLE_SUGGEST_ATTR_WARNINGS; - -// misc warning false-positives -#if TOML_MSVC -#pragma warning(disable : 5031) // #pragma warning(pop): likely mismatch -#if TOML_SHARED_LIB -#pragma warning(disable : 4251) // dll exports for std lib types -#endif -#elif TOML_CLANG -#pragma clang diagnostic ignored "-Wheader-hygiene" -#if TOML_CLANG >= 12 -#pragma clang diagnostic ignored "-Wc++20-extensions" -#endif -#if (TOML_CLANG == 13) && !defined(__APPLE__) -#pragma clang diagnostic ignored "-Wreserved-identifier" -#endif -#endif - -//******** impl/std_new.h ******************************************************************************************** - -TOML_DISABLE_WARNINGS; -#include -TOML_ENABLE_WARNINGS; - -#if TOML_CLANG >= 8 || TOML_GCC >= 7 || TOML_ICC >= 1910 || TOML_MSVC >= 1914 -#define TOML_LAUNDER(x) __builtin_launder(x) -#elif defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606 -#define TOML_LAUNDER(x) std::launder(x) -#else -#define TOML_LAUNDER(x) x -#endif - -//******** impl/std_string.h ***************************************************************************************** - -TOML_DISABLE_WARNINGS; -#include -#include -TOML_ENABLE_WARNINGS; - -#if TOML_DOXYGEN \ - || (defined(__cpp_char8_t) && __cpp_char8_t >= 201811 && defined(__cpp_lib_char8_t) \ - && __cpp_lib_char8_t >= 201907) -#define TOML_HAS_CHAR8 1 -#else -#define TOML_HAS_CHAR8 0 -#endif - -namespace toml // non-abi namespace; this is not an error -{ - using namespace std::string_literals; - using namespace std::string_view_literals; -} - -#if TOML_ENABLE_WINDOWS_COMPAT - -TOML_IMPL_NAMESPACE_START -{ - TOML_NODISCARD - TOML_EXPORTED_FREE_FUNCTION - std::string narrow(std::wstring_view); - - TOML_NODISCARD - TOML_EXPORTED_FREE_FUNCTION - std::wstring widen(std::string_view); - -#if TOML_HAS_CHAR8 - - TOML_NODISCARD - TOML_EXPORTED_FREE_FUNCTION - std::wstring widen(std::u8string_view); - -#endif -} -TOML_IMPL_NAMESPACE_END; - -#endif // TOML_ENABLE_WINDOWS_COMPAT - -//******** impl/std_optional.h *************************************************************************************** - -TOML_DISABLE_WARNINGS; -#if !TOML_HAS_CUSTOM_OPTIONAL_TYPE -#include -#endif -TOML_ENABLE_WARNINGS; - -TOML_NAMESPACE_START -{ -#if TOML_HAS_CUSTOM_OPTIONAL_TYPE - - template - using optional = TOML_OPTIONAL_TYPE; - -#else - - template - using optional = std::optional; - -#endif -} -TOML_NAMESPACE_END; - -//******** impl/forward_declarations.h ******************************************************************************* - -TOML_DISABLE_WARNINGS; -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -TOML_ENABLE_WARNINGS; -TOML_PUSH_WARNINGS; -#ifdef _MSC_VER -#pragma inline_recursion(on) -#pragma push_macro("min") -#pragma push_macro("max") -#undef min -#undef max -#endif - -#ifndef TOML_DISABLE_ENVIRONMENT_CHECKS -#define TOML_ENV_MESSAGE \ - "If you're seeing this error it's because you're building toml++ for an environment that doesn't conform to " \ - "one of the 'ground truths' assumed by the library. Essentially this just means that I don't have the " \ - "resources to test on more platforms, but I wish I did! You can try disabling the checks by defining " \ - "TOML_DISABLE_ENVIRONMENT_CHECKS, but your mileage may vary. Please consider filing an issue at " \ - "https://github.com/marzer/tomlplusplus/issues to help me improve support for your target environment. " \ - "Thanks!" - -static_assert(CHAR_BIT == 8, TOML_ENV_MESSAGE); -static_assert(FLT_RADIX == 2, TOML_ENV_MESSAGE); -static_assert('A' == 65, TOML_ENV_MESSAGE); -static_assert(sizeof(double) == 8, TOML_ENV_MESSAGE); -static_assert(std::numeric_limits::is_iec559, TOML_ENV_MESSAGE); -static_assert(std::numeric_limits::digits == 53, TOML_ENV_MESSAGE); -static_assert(std::numeric_limits::digits10 == 15, TOML_ENV_MESSAGE); - -#undef TOML_ENV_MESSAGE -#endif // !TOML_DISABLE_ENVIRONMENT_CHECKS - -// undocumented forward declarations are hidden from doxygen because they fuck it up =/ - -namespace toml // non-abi namespace; this is not an error -{ - using ::std::size_t; - using ::std::intptr_t; - using ::std::uintptr_t; - using ::std::ptrdiff_t; - using ::std::nullptr_t; - using ::std::int8_t; - using ::std::int16_t; - using ::std::int32_t; - using ::std::int64_t; - using ::std::uint8_t; - using ::std::uint16_t; - using ::std::uint32_t; - using ::std::uint64_t; - using ::std::uint_least32_t; - using ::std::uint_least64_t; -} - -TOML_NAMESPACE_START -{ - struct date; - struct time; - struct time_offset; - - TOML_ABI_NAMESPACE_BOOL(TOML_HAS_CUSTOM_OPTIONAL_TYPE, custopt, stdopt); - struct date_time; - TOML_ABI_NAMESPACE_END; - - struct source_position; - struct source_region; - - class node; - template - class node_view; - - class key; - class array; - class table; - template - class value; - - class path; - - class toml_formatter; - class json_formatter; - class yaml_formatter; - - TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, ex, noex); -#if TOML_EXCEPTIONS - using parse_result = table; -#else - class parse_result; -#endif - TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS -} -TOML_NAMESPACE_END; - -TOML_IMPL_NAMESPACE_START -{ - using node_ptr = std::unique_ptr; - - TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, impl_ex, impl_noex); - class parser; - TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS - - // clang-format off - - inline constexpr std::string_view control_char_escapes[] = - { - "\\u0000"sv, - "\\u0001"sv, - "\\u0002"sv, - "\\u0003"sv, - "\\u0004"sv, - "\\u0005"sv, - "\\u0006"sv, - "\\u0007"sv, - "\\b"sv, - "\\t"sv, - "\\n"sv, - "\\u000B"sv, - "\\f"sv, - "\\r"sv, - "\\u000E"sv, - "\\u000F"sv, - "\\u0010"sv, - "\\u0011"sv, - "\\u0012"sv, - "\\u0013"sv, - "\\u0014"sv, - "\\u0015"sv, - "\\u0016"sv, - "\\u0017"sv, - "\\u0018"sv, - "\\u0019"sv, - "\\u001A"sv, - "\\u001B"sv, - "\\u001C"sv, - "\\u001D"sv, - "\\u001E"sv, - "\\u001F"sv, - }; - - inline constexpr std::string_view node_type_friendly_names[] = - { - "none"sv, - "table"sv, - "array"sv, - "string"sv, - "integer"sv, - "floating-point"sv, - "boolean"sv, - "date"sv, - "time"sv, - "date-time"sv - }; - - // clang-format on -} -TOML_IMPL_NAMESPACE_END; - -#if TOML_ABI_NAMESPACES -#if TOML_EXCEPTIONS -#define TOML_PARSER_TYPENAME TOML_NAMESPACE::impl::impl_ex::parser -#else -#define TOML_PARSER_TYPENAME TOML_NAMESPACE::impl::impl_noex::parser -#endif -#else -#define TOML_PARSER_TYPENAME TOML_NAMESPACE::impl::parser -#endif - -namespace toml -{ -} - -TOML_NAMESPACE_START // abi namespace -{ - inline namespace literals - { - } - - enum class TOML_CLOSED_ENUM node_type : uint8_t - { - none, - table, - array, - string, - integer, - floating_point, - boolean, - date, - time, - date_time - }; - - template - inline std::basic_ostream& operator<<(std::basic_ostream& lhs, node_type rhs) - { - const auto str = impl::node_type_friendly_names[static_cast>(rhs)]; - using str_char_t = decltype(str)::value_type; - if constexpr (std::is_same_v) - return lhs << str; - else - { - if constexpr (sizeof(Char) == sizeof(str_char_t)) - return lhs << std::basic_string_view{ reinterpret_cast(str.data()), str.length() }; - else - return lhs << str.data(); - } - } - - enum class TOML_OPEN_FLAGS_ENUM value_flags : uint16_t // being an "OPEN" flags enum is not an error - { - none, - format_as_binary = 1, - format_as_octal = 2, - format_as_hexadecimal = 3, - }; - TOML_MAKE_FLAGS(value_flags); - - inline constexpr value_flags preserve_source_value_flags = - POXY_IMPLEMENTATION_DETAIL(value_flags{ static_cast>(-1) }); - - enum class TOML_CLOSED_FLAGS_ENUM format_flags : uint64_t - { - none, - quote_dates_and_times = (1ull << 0), - quote_infinities_and_nans = (1ull << 1), - allow_literal_strings = (1ull << 2), - allow_multi_line_strings = (1ull << 3), - allow_real_tabs_in_strings = (1ull << 4), - allow_unicode_strings = (1ull << 5), - allow_binary_integers = (1ull << 6), - allow_octal_integers = (1ull << 7), - allow_hexadecimal_integers = (1ull << 8), - indent_sub_tables = (1ull << 9), - indent_array_elements = (1ull << 10), - indentation = indent_sub_tables | indent_array_elements, - relaxed_float_precision = (1ull << 11), - }; - TOML_MAKE_FLAGS(format_flags); - - template - struct TOML_TRIVIAL_ABI inserter - { - static_assert(std::is_reference_v); - - T value; - }; - template - inserter(T &&) -> inserter; - template - inserter(T&) -> inserter; - - using default_formatter = toml_formatter; -} -TOML_NAMESPACE_END; - -TOML_IMPL_NAMESPACE_START -{ - template - using remove_cvref = std::remove_cv_t>; - - template - using common_signed_type = std::common_type_t...>; - - template - inline constexpr bool is_one_of = (false || ... || std::is_same_v); - - template - inline constexpr bool all_integral = (std::is_integral_v && ...); - - template - inline constexpr bool is_cvref = std::is_reference_v || std::is_const_v || std::is_volatile_v; - - template - inline constexpr bool is_wide_string = - is_one_of, const wchar_t*, wchar_t*, std::wstring_view, std::wstring>; - - template - inline constexpr bool value_retrieval_is_nothrow = !std::is_same_v, std::string> -#if TOML_HAS_CHAR8 - && !std::is_same_v, std::u8string> -#endif - - && !is_wide_string; - - template - struct copy_ref_; - template - using copy_ref = typename copy_ref_::type; - - template - struct copy_ref_ - { - using type = Dest; - }; - - template - struct copy_ref_ - { - using type = std::add_lvalue_reference_t; - }; - - template - struct copy_ref_ - { - using type = std::add_rvalue_reference_t; - }; - - template - struct copy_cv_; - template - using copy_cv = typename copy_cv_::type; - - template - struct copy_cv_ - { - using type = Dest; - }; - - template - struct copy_cv_ - { - using type = std::add_const_t; - }; - - template - struct copy_cv_ - { - using type = std::add_volatile_t; - }; - - template - struct copy_cv_ - { - using type = std::add_cv_t; - }; - - template - using copy_cvref = - copy_ref, std::remove_reference_t>, Dest>, Src>; - - template - inline constexpr bool dependent_false = false; - - template - inline constexpr bool first_is_same = false; - template - inline constexpr bool first_is_same = true; - - // general value traits - // (as they relate to their equivalent native TOML type) - template - struct value_traits - { - using native_type = void; - static constexpr bool is_native = false; - static constexpr bool is_losslessly_convertible_to_native = false; - static constexpr bool can_represent_native = false; - static constexpr bool can_partially_represent_native = false; - static constexpr auto type = node_type::none; - }; - - template - struct value_traits : value_traits - {}; - template - struct value_traits : value_traits - {}; - template - struct value_traits : value_traits - {}; - template - struct value_traits : value_traits - {}; - template - struct value_traits : value_traits - {}; - - // integer value_traits specializations - standard types - template - struct integer_limits - { - static constexpr auto min = (std::numeric_limits::min)(); - static constexpr auto max = (std::numeric_limits::max)(); - }; - template - struct integer_traits_base : integer_limits - { - using native_type = int64_t; - static constexpr bool is_native = std::is_same_v; - static constexpr bool is_signed = static_cast(-1) < T{}; // for impls not specializing std::is_signed - static constexpr auto type = node_type::integer; - static constexpr bool can_partially_represent_native = true; - }; - template - struct unsigned_integer_traits : integer_traits_base - { - static constexpr bool is_losslessly_convertible_to_native = integer_limits::max <= 9223372036854775807ULL; - static constexpr bool can_represent_native = false; - }; - template - struct signed_integer_traits : integer_traits_base - { - using native_type = int64_t; - static constexpr bool is_losslessly_convertible_to_native = - integer_limits::min >= (-9223372036854775807LL - 1LL) && integer_limits::max <= 9223372036854775807LL; - static constexpr bool can_represent_native = - integer_limits::min <= (-9223372036854775807LL - 1LL) && integer_limits::max >= 9223372036854775807LL; - }; - template ::is_signed> - struct integer_traits : signed_integer_traits - {}; - template - struct integer_traits : unsigned_integer_traits - {}; - template <> - struct value_traits : integer_traits - {}; - template <> - struct value_traits : integer_traits - {}; - template <> - struct value_traits : integer_traits - {}; - template <> - struct value_traits : integer_traits - {}; - template <> - struct value_traits : integer_traits - {}; - template <> - struct value_traits : integer_traits - {}; - template <> - struct value_traits : integer_traits - {}; - template <> - struct value_traits : integer_traits - {}; - template <> - struct value_traits : integer_traits - {}; - template <> - struct value_traits : integer_traits - {}; - static_assert(value_traits::is_native); - static_assert(value_traits::is_signed); - static_assert(value_traits::is_losslessly_convertible_to_native); - static_assert(value_traits::can_represent_native); - static_assert(value_traits::can_partially_represent_native); - - // integer value_traits specializations - non-standard types -#ifdef TOML_INT128 - template <> - struct integer_limits - { - static constexpr TOML_INT128 max = - static_cast((TOML_UINT128{ 1u } << ((__SIZEOF_INT128__ * CHAR_BIT) - 1)) - 1); - static constexpr TOML_INT128 min = -max - TOML_INT128{ 1 }; - }; - template <> - struct integer_limits - { - static constexpr TOML_UINT128 min = TOML_UINT128{}; - static constexpr TOML_UINT128 max = (2u * static_cast(integer_limits::max)) + 1u; - }; - template <> - struct value_traits : integer_traits - {}; - template <> - struct value_traits : integer_traits - {}; -#endif -#ifdef TOML_SMALL_INT_TYPE - template <> - struct value_traits : signed_integer_traits - {}; -#endif - - // floating-point traits base - template - struct float_traits_base - { - static constexpr auto type = node_type::floating_point; - using native_type = double; - static constexpr bool is_native = std::is_same_v; - static constexpr bool is_signed = true; - - static constexpr int bits = static_cast(sizeof(T) * CHAR_BIT); - static constexpr int digits = MantissaDigits; - static constexpr int digits10 = DecimalDigits; - - static constexpr bool is_losslessly_convertible_to_native = bits <= 64 // - && digits <= 53 // DBL_MANT_DIG - && digits10 <= 15; // DBL_DIG - - static constexpr bool can_represent_native = digits >= 53 // DBL_MANT_DIG - && digits10 >= 15; // DBL_DIG - - static constexpr bool can_partially_represent_native = digits > 0 && digits10 > 0; - }; - template - struct float_traits : float_traits_base::digits, std::numeric_limits::digits10> - {}; -#ifdef TOML_FP16 - template <> - struct float_traits : float_traits_base - {}; -#endif -#ifdef TOML_FLOAT16 - template <> - struct float_traits : float_traits_base - {}; -#endif -#ifdef TOML_FLOAT128 - template <> - struct float_traits : float_traits_base - {}; -#endif - - // floating-point traits - template <> - struct value_traits : float_traits - {}; - template <> - struct value_traits : float_traits - {}; - template <> - struct value_traits : float_traits - {}; -#ifdef TOML_FP16 - template <> - struct value_traits : float_traits - {}; -#endif -#ifdef TOML_FLOAT16 - template <> - struct value_traits : float_traits - {}; -#endif -#ifdef TOML_FLOAT128 - template <> - struct value_traits : float_traits - {}; -#endif -#ifdef TOML_SMALL_FLOAT_TYPE - template <> - struct value_traits : float_traits - {}; -#endif - static_assert(value_traits::is_native); - static_assert(value_traits::is_losslessly_convertible_to_native); - static_assert(value_traits::can_represent_native); - static_assert(value_traits::can_partially_represent_native); - - // string value_traits specializations - char-based strings - template - struct string_traits - { - using native_type = std::string; - static constexpr bool is_native = std::is_same_v; - static constexpr bool is_losslessly_convertible_to_native = true; - static constexpr bool can_represent_native = - !std::is_array_v && (!std::is_pointer_v || std::is_const_v>); - static constexpr bool can_partially_represent_native = can_represent_native; - static constexpr auto type = node_type::string; - }; - template <> - struct value_traits : string_traits - {}; - template <> - struct value_traits : string_traits - {}; - template <> - struct value_traits : string_traits - {}; - template - struct value_traits : string_traits - {}; - template <> - struct value_traits : string_traits - {}; - template - struct value_traits : string_traits - {}; - - // string value_traits specializations - char8_t-based strings -#if TOML_HAS_CHAR8 - template <> - struct value_traits : string_traits - {}; - template <> - struct value_traits : string_traits - {}; - template <> - struct value_traits : string_traits - {}; - template - struct value_traits : string_traits - {}; - template <> - struct value_traits : string_traits - {}; - template - struct value_traits : string_traits - {}; -#endif - - // string value_traits specializations - wchar_t-based strings on Windows -#if TOML_ENABLE_WINDOWS_COMPAT - template - struct wstring_traits - { - using native_type = std::string; - static constexpr bool is_native = false; - static constexpr bool is_losslessly_convertible_to_native = true; // narrow - static constexpr bool can_represent_native = std::is_same_v; // widen - static constexpr bool can_partially_represent_native = can_represent_native; - static constexpr auto type = node_type::string; - }; - template <> - struct value_traits : wstring_traits - {}; - template <> - struct value_traits : wstring_traits - {}; - template <> - struct value_traits : wstring_traits - {}; - template - struct value_traits : wstring_traits - {}; - template <> - struct value_traits : wstring_traits - {}; - template - struct value_traits : wstring_traits - {}; -#endif - - // other 'native' value_traits specializations - template - struct native_value_traits - { - using native_type = T; - static constexpr bool is_native = true; - static constexpr bool is_losslessly_convertible_to_native = true; - static constexpr bool can_represent_native = true; - static constexpr bool can_partially_represent_native = true; - static constexpr auto type = NodeType; - }; - template <> - struct value_traits : native_value_traits - {}; - template <> - struct value_traits : native_value_traits - {}; - template <> - struct value_traits