diff --git a/.github/workflows/ci-cpp.yml b/.github/workflows/ci-cpp.yml index 736318e06..ce010d652 100644 --- a/.github/workflows/ci-cpp.yml +++ b/.github/workflows/ci-cpp.yml @@ -11,7 +11,7 @@ on: jobs: build-linux: - name: C++ CI - Linux + name: C++ CI runs-on: ubuntu-22.04 steps: @@ -46,7 +46,7 @@ jobs: uses: actions/cache@v3 with: path: /home/runner/work/spice/llvm - key: llvm-15.0.2-linux-x64 + key: llvm-15.0.2 - name: Setup LLVM if: steps.cache-llvm.outputs.cache-hit != 'true' @@ -101,76 +101,4 @@ jobs: run: | curl -Os https://uploader.codecov.io/latest/linux/codecov chmod +x codecov - ./codecov -t ${{ secrets.CODECOV_TOKEN }} - - build-windows: - name: C++ CI - Windows - runs-on: windows-2022 - - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Setup Java - uses: actions/setup-java@v3 - with: - distribution: zulu - java-version: 11 - - - name: Setup latest GCC - shell: pwsh - run: | - choco uninstall mingw --all-versions - choco uninstall llvm --all-versions - Remove-Item -Recurse -Force C:/Strawberry - echo "Uninstalling done." - Invoke-WebRequest https://chillibits.com/files/gh/mingw64_12_2_0.7z -OutFile mingw64.7z - echo "Downloading done." - 7z x mingw64.7z -oC:\mingw64 - echo "Unpacking done." - Copy-Item -Path C:\mingw64\mingw64\bin\mingw32-make.exe -Destination C:\mingw64\mingw64\bin\make.exe - echo "All done." - - - name: Setup Ninja - uses: seanmiddleditch/gha-setup-ninja@master - - - name: Cache LLVM - id: cache-llvm - uses: actions/cache@v3 - with: - path: D:/a/spice/spice/llvm - key: llvm-15.0.2-win-x86 - - - name: Setup LLVM - if: steps.cache-llvm.outputs.cache-hit != 'true' - run: | - git clone --depth 1 --branch llvmorg-15.0.2 https://github.com/llvm/llvm-project.git llvm - setx /M PATH "%PATH%;C:\mingw64\mingw64\bin" - $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") - echo "Adding MinGW to path done." - mkdir ./llvm/build - cd ./llvm/build - cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_CXX_FLAGS_RELEASE="-O2" -GNinja -Wno-dev -Wattributes ../llvm - cmake --build . -j 4 - - - name: Download Libs - run: .\setup-libs.bat - - - name: Build Test target - env: - LLVM_DIR: D:/a/spice/spice/llvm/build/lib/cmake/llvm - run: | - setx /M PATH "%PATH%;C:\mingw64\mingw64\bin" - $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") - echo "Adding MinGW to path done." - mkdir ./bin - cd ./bin - cmake -GNinja -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DSPICE_LINK_STATIC=ON -DSPICE_VERSION="${{ steps.get_version.outputs.version }}" -DSPICE_BUILT_BY="ghactions" -DCMAKE_CXX_FLAGS_RELEASE="-O2" .. - cmake --build . --target spice -j 4 - - - name: Run Test target - env: - SPICE_STD_DIR: C:\Users\runneradmin\spice\spice\std - run: | - cd .\bin\test - .\spicetest false \ No newline at end of file + ./codecov -t ${{ secrets.CODECOV_TOKEN }} \ No newline at end of file diff --git a/media/test-project/os-test.spice b/media/test-project/os-test.spice index 847424e49..23c17d62d 100644 --- a/media/test-project/os-test.spice +++ b/media/test-project/os-test.spice @@ -1,8 +1,5 @@ f main() { - string test = "Tested"; - printf("%s\n", test.getRaw()); - printf("%d\n", test.getLength()); - printf("%d\n", test.getCapacity()); + int test = "string"; } /*f main() { diff --git a/src/analyzer/AnalyzerVisitor.cpp b/src/analyzer/AnalyzerVisitor.cpp index 58a51ec3e..9888d76fd 100644 --- a/src/analyzer/AnalyzerVisitor.cpp +++ b/src/analyzer/AnalyzerVisitor.cpp @@ -53,7 +53,7 @@ std::any AnalyzerVisitor::visitEntry(EntryNode *node) { // Check if the visitor got a main function if (requiresMainFct && !hasMainFunction) - throw SemanticError(node->codeLoc, MISSING_MAIN_FUNCTION, "No main function found"); + throw SemanticError(node, MISSING_MAIN_FUNCTION, "No main function found"); // Print compiler warnings once the whole ast is present, but not for std files if (requiresMainFct && !isStdFile && !reAnalyze) @@ -72,7 +72,7 @@ std::any AnalyzerVisitor::visitMainFctDef(MainFctDefNode *node) { if (runNumber == 1) { // First run // Check if the function is already defined if (currentScope->lookup(mainSignature)) - throw SemanticError(node->codeLoc, FUNCTION_DECLARED_TWICE, "Main function is declared twice"); + throw SemanticError(node, FUNCTION_DECLARED_TWICE, "Main function is declared twice"); // Insert function name into the root symbol table SymbolType symbolType = SymbolType(TY_FUNCTION); @@ -106,7 +106,7 @@ std::any AnalyzerVisitor::visitMainFctDef(MainFctDefNode *node) { // Call destructors for variables, that are going out of scope std::vector varsToDestruct = node->fctScope->getVarsGoingOutOfScope(true); for (SymbolTableEntry *varEntry : varsToDestruct) - insertDestructorCall(varEntry->getDeclCodeLoc(), varEntry); + insertDestructorCall(varEntry->getDeclNode(), varEntry); // Return to root scope currentScope = node->fctScope->parent; @@ -121,12 +121,12 @@ std::any AnalyzerVisitor::visitFctDef(FctDefNode *node) { // Change to the struct scope node->structScope = currentScope = currentScope->lookupTable(STRUCT_SCOPE_PREFIX + node->structName); if (!node->structScope) - throw SemanticError(node->codeLoc, REFERENCED_UNDEFINED_STRUCT, "Struct '" + node->structName + "' could not be found"); + throw SemanticError(node, REFERENCED_UNDEFINED_STRUCT, "Struct '" + node->structName + "' could not be found"); } // Check if name is dtor if (node->functionName == "dtor") - throw SemanticError(node->codeLoc, DTOR_MUST_BE_PROCEDURE, "Destructors are not allowed to be of type function"); + throw SemanticError(node, DTOR_MUST_BE_PROCEDURE, "Destructors are not allowed to be of type function"); // Create a new scope node->fctScope = currentScope = currentScope->createChildBlock(node->getScopeId(), SCOPE_FUNC_PROC_BODY); @@ -139,7 +139,7 @@ std::any AnalyzerVisitor::visitFctDef(FctDefNode *node) { SymbolTableEntry *structEntry = node->structScope->lookup(node->structName); assert(structEntry != nullptr); thisType = structEntry->type; - thisPtrType = thisType.toPointer(node->codeLoc); + thisPtrType = thisType.toPointer(node); for (const auto &templateType : thisType.getTemplateTypes()) templateTypes.emplace_back(templateType); } @@ -149,7 +149,7 @@ std::any AnalyzerVisitor::visitFctDef(FctDefNode *node) { for (const auto &dataType : node->templateTypeLst()->dataTypes()) { auto templateType = any_cast(visit(dataType)); if (!templateType.is(TY_GENERIC)) - throw SemanticError(dataType->codeLoc, EXPECTED_GENERIC_TYPE, "A template list can only contain generic types"); + throw SemanticError(dataType, EXPECTED_GENERIC_TYPE, "A template list can only contain generic types"); GenericType *genericType = node->fctScope->lookupGenericType(templateType.getSubType()); assert(genericType != nullptr); templateTypes.push_back(*genericType); @@ -169,7 +169,7 @@ std::any AnalyzerVisitor::visitFctDef(FctDefNode *node) { // Check if the type is present in the template for generic types if (paramType.is(TY_GENERIC)) { if (std::none_of(templateTypes.begin(), templateTypes.end(), [&](const GenericType &t) { return t == paramType; })) - throw SemanticError(node->paramLst()->codeLoc, GENERIC_TYPE_NOT_IN_TEMPLATE, + throw SemanticError(node->paramLst(), GENERIC_TYPE_NOT_IN_TEMPLATE, "Generic arg type not included in function template"); } @@ -188,9 +188,9 @@ std::any AnalyzerVisitor::visitFctDef(FctDefNode *node) { // Declare variable for the return value in the function scope auto returnType = any_cast(visit(node->returnType())); if (returnType.is(TY_DYN)) - throw SemanticError(node->codeLoc, UNEXPECTED_DYN_TYPE_SA, "Dyn return types are not allowed"); + throw SemanticError(node, UNEXPECTED_DYN_TYPE_SA, "Dyn return types are not allowed"); if (returnType.isPointer()) - throw SemanticError(node->codeLoc, COMING_SOON_SA, + throw SemanticError(node, COMING_SOON_SA, "Spice currently not supports pointer return types due to not handling pointer escaping."); node->fctScope->insert(RETURN_VARIABLE_NAME, returnType, SymbolSpecifiers(returnType), DECLARED, node); @@ -206,8 +206,7 @@ std::any AnalyzerVisitor::visitFctDef(FctDefNode *node) { else if (specifier->type == SpecifierNode::TY_PUBLIC) fctSymbolSpecifiers.setPublic(true); else - throw SemanticError(specifier->codeLoc, SPECIFIER_AT_ILLEGAL_CONTEXT, - "Cannot use this specifier on a function definition"); + throw SemanticError(specifier, SPECIFIER_AT_ILLEGAL_CONTEXT, "Cannot use this specifier on a function definition"); } } @@ -265,7 +264,7 @@ std::any AnalyzerVisitor::visitFctDef(FctDefNode *node) { if (returnVarEntry->type.is(TY_GENERIC)) { SymbolType returnType = spiceFunc.getReturnType(); if (returnType.isPointer()) - throw SemanticError(node->codeLoc, COMING_SOON_SA, + throw SemanticError(node, COMING_SOON_SA, "Spice currently not supports pointer return types due to not handling pointer escaping."); returnVarEntry->updateType(returnType, true); } @@ -293,7 +292,7 @@ std::any AnalyzerVisitor::visitFctDef(FctDefNode *node) { // Call destructors for variables, that are going out of scope std::vector varsToDestruct = currentScope->getVarsGoingOutOfScope(true); for (SymbolTableEntry *varEntry : varsToDestruct) - insertDestructorCall(varEntry->getDeclCodeLoc(), varEntry); + insertDestructorCall(varEntry->getDeclNode(), varEntry); // Reset generic types for (const auto &arg : args) { @@ -304,7 +303,7 @@ std::any AnalyzerVisitor::visitFctDef(FctDefNode *node) { // Check if return variable is now initialized if (currentScope->lookup(RETURN_VARIABLE_NAME)->state == DECLARED) - throw SemanticError(node->codeLoc, FUNCTION_WITHOUT_RETURN_STMT, "Function without return statement"); + throw SemanticError(node, FUNCTION_WITHOUT_RETURN_STMT, "Function without return statement"); // Leave the function scope currentScope = currentScope->parent; @@ -330,7 +329,7 @@ std::any AnalyzerVisitor::visitProcDef(ProcDefNode *node) { if (node->isMethod) { node->structScope = currentScope = currentScope->lookupTable(STRUCT_SCOPE_PREFIX + node->structName); if (!currentScope) - throw SemanticError(node->codeLoc, REFERENCED_UNDEFINED_STRUCT, "Struct '" + node->structName + "' could not be found"); + throw SemanticError(node, REFERENCED_UNDEFINED_STRUCT, "Struct '" + node->structName + "' could not be found"); } // Create a new scope @@ -343,7 +342,7 @@ std::any AnalyzerVisitor::visitProcDef(ProcDefNode *node) { if (node->isMethod) { SymbolTableEntry *structEntry = node->structScope->lookup(node->structName); thisType = structEntry->type; - thisPtrType = thisType.toPointer(node->codeLoc); + thisPtrType = thisType.toPointer(node); for (const auto &templateType : thisType.getTemplateTypes()) templateTypes.emplace_back(templateType); } @@ -353,7 +352,7 @@ std::any AnalyzerVisitor::visitProcDef(ProcDefNode *node) { for (const auto &dataType : node->templateTypeLst()->dataTypes()) { auto templateType = any_cast(visit(dataType)); if (!templateType.is(TY_GENERIC)) - throw SemanticError(dataType->codeLoc, EXPECTED_GENERIC_TYPE, "A template list can only contain generic types"); + throw SemanticError(dataType, EXPECTED_GENERIC_TYPE, "A template list can only contain generic types"); GenericType *genericType = node->procScope->lookupGenericType(templateType.getSubType()); assert(genericType != nullptr); templateTypes.push_back(*genericType); @@ -361,7 +360,7 @@ std::any AnalyzerVisitor::visitProcDef(ProcDefNode *node) { } if (node->hasParams && node->procedureName == "dtor") - throw SemanticError(node->codeLoc, DTOR_WITH_PARAMS, "It is not allowed to specify parameters for destructors"); + throw SemanticError(node, DTOR_WITH_PARAMS, "It is not allowed to specify parameters for destructors"); // Visit parameters in new scope std::vector paramNames; @@ -376,7 +375,7 @@ std::any AnalyzerVisitor::visitProcDef(ProcDefNode *node) { // Check if the type is present in the template for generic types if (paramType.is(TY_GENERIC)) { if (std::none_of(templateTypes.begin(), templateTypes.end(), [&](const GenericType &t) { return t == paramType; })) - throw SemanticError(node->paramLst()->codeLoc, GENERIC_TYPE_NOT_IN_TEMPLATE, + throw SemanticError(node->paramLst(), GENERIC_TYPE_NOT_IN_TEMPLATE, "Generic arg type not included in procedure template"); } @@ -404,8 +403,7 @@ std::any AnalyzerVisitor::visitProcDef(ProcDefNode *node) { else if (specifier->type == SpecifierNode::TY_PUBLIC) procSymbolSpecifiers.setPublic(true); else - throw SemanticError(specifier->codeLoc, SPECIFIER_AT_ILLEGAL_CONTEXT, - "Cannot use this specifier on a function definition"); + throw SemanticError(specifier, SPECIFIER_AT_ILLEGAL_CONTEXT, "Cannot use this specifier on a function definition"); } } @@ -481,7 +479,7 @@ std::any AnalyzerVisitor::visitProcDef(ProcDefNode *node) { // Call destructors for variables, that are going out of scope std::vector varsToDestruct = currentScope->getVarsGoingOutOfScope(true); for (SymbolTableEntry *varEntry : varsToDestruct) - insertDestructorCall(varEntry->getDeclCodeLoc(), varEntry); + insertDestructorCall(varEntry->getDeclNode(), varEntry); // Reset generic types for (const auto &arg : params) { @@ -514,7 +512,7 @@ std::any AnalyzerVisitor::visitStructDef(StructDefNode *node) { // Check if struct already exists in this scope if (currentScope->lookup(node->structName)) - throw SemanticError(node->codeLoc, STRUCT_DECLARED_TWICE, "Duplicate struct '" + node->structName + "'"); + throw SemanticError(node, STRUCT_DECLARED_TWICE, "Duplicate struct '" + node->structName + "'"); // Get template types std::vector genericTemplateTypes; @@ -523,7 +521,7 @@ std::any AnalyzerVisitor::visitStructDef(StructDefNode *node) { for (const auto &dataType : node->templateTypeLst()->dataTypes()) { auto templateType = any_cast(visit(dataType)); if (!templateType.is(TY_GENERIC)) - throw SemanticError(dataType->codeLoc, EXPECTED_GENERIC_TYPE, "A template list can only contain generic types"); + throw SemanticError(dataType, EXPECTED_GENERIC_TYPE, "A template list can only contain generic types"); GenericType *genericType = currentScope->lookupGenericType(templateType.getSubType()); assert(genericType != nullptr); genericTemplateTypes.push_back(*genericType); @@ -539,8 +537,7 @@ std::any AnalyzerVisitor::visitStructDef(StructDefNode *node) { if (specifier->type == SpecifierNode::TY_PUBLIC) structSymbolSpecifiers.setPublic(true); else - throw SemanticError(specifier->codeLoc, SPECIFIER_AT_ILLEGAL_CONTEXT, - "Cannot use this specifier on a function definition"); + throw SemanticError(specifier, SPECIFIER_AT_ILLEGAL_CONTEXT, "Cannot use this specifier on a function definition"); } } @@ -558,7 +555,7 @@ std::any AnalyzerVisitor::visitStructDef(StructDefNode *node) { if (fieldType.isBaseType(TY_GENERIC)) { // Check if the type is present in the template for generic types if (std::none_of(genericTemplateTypes.begin(), genericTemplateTypes.end(), [&](const GenericType &t) { return t == fieldType.getBaseType(); })) - throw SemanticError(field->dataType()->codeLoc, GENERIC_TYPE_NOT_IN_TEMPLATE, + throw SemanticError(field->dataType(), GENERIC_TYPE_NOT_IN_TEMPLATE, "Generic field type not included in struct template"); } @@ -566,8 +563,7 @@ std::any AnalyzerVisitor::visitStructDef(StructDefNode *node) { if (SpecifierLstNode *specifierLst = field->specifierLst(); specifierLst) { for (const auto &specifier : specifierLst->specifiers()) { if (specifier->type == SpecifierNode::TY_CONST) - throw SemanticError(specifier->codeLoc, SPECIFIER_AT_ILLEGAL_CONTEXT, - "Struct fields cannot have the const specifier attached"); + throw SemanticError(specifier, SPECIFIER_AT_ILLEGAL_CONTEXT, "Struct fields cannot have the const specifier attached"); else if (specifier->type == SpecifierNode::TY_SIGNED) fieldSymbolSpecifiers.setSigned(true); else if (specifier->type == SpecifierNode::TY_UNSIGNED) @@ -575,8 +571,7 @@ std::any AnalyzerVisitor::visitStructDef(StructDefNode *node) { else if (specifier->type == SpecifierNode::TY_PUBLIC) fieldSymbolSpecifiers.setPublic(true); else - throw SemanticError(specifier->codeLoc, SPECIFIER_AT_ILLEGAL_CONTEXT, - "Cannot use this specifier on a function definition"); + throw SemanticError(specifier, SPECIFIER_AT_ILLEGAL_CONTEXT, "Cannot use this specifier on a function definition"); } } @@ -603,7 +598,7 @@ std::any AnalyzerVisitor::visitEnumDef(EnumDefNode *node) { // Check if enum already exists in this scope if (currentScope->lookup(node->enumName)) - throw SemanticError(node->codeLoc, ENUM_DECLARED_TWICE, "Duplicate symbol name '" + node->enumName + "'"); + throw SemanticError(node, ENUM_DECLARED_TWICE, "Duplicate symbol name '" + node->enumName + "'"); // Build symbol specifiers auto enumSymbolSpecifiers = SymbolSpecifiers(SymbolType(TY_ENUM, node->enumName)); @@ -612,7 +607,7 @@ std::any AnalyzerVisitor::visitEnumDef(EnumDefNode *node) { if (specifier->type == SpecifierNode::TY_PUBLIC) enumSymbolSpecifiers.setPublic(true); else - throw SemanticError(specifier->codeLoc, SPECIFIER_AT_ILLEGAL_CONTEXT, "Cannot use this specifier on an enum definition"); + throw SemanticError(specifier, SPECIFIER_AT_ILLEGAL_CONTEXT, "Cannot use this specifier on an enum definition"); } } @@ -626,12 +621,12 @@ std::any AnalyzerVisitor::visitEnumDef(EnumDefNode *node) { for (auto enumItem : node->itemLst()->items()) { // Check if the name does exist already if (std::find(names.begin(), names.end(), enumItem->itemName) != names.end()) - throw SemanticError(enumItem->codeLoc, DUPLICATE_ENUM_ITEM_NAME, "Duplicate enum item name, please use another"); + throw SemanticError(enumItem, DUPLICATE_ENUM_ITEM_NAME, "Duplicate enum item name, please use another"); names.push_back(enumItem->itemName); if (enumItem->hasValue) { if (std::find(values.begin(), values.end(), enumItem->itemValue) != values.end()) - throw SemanticError(enumItem->codeLoc, DUPLICATE_ENUM_ITEM_VALUE, "Duplicate enum item value, please use another"); + throw SemanticError(enumItem, DUPLICATE_ENUM_ITEM_VALUE, "Duplicate enum item value, please use another"); values.push_back(enumItem->itemValue); } } @@ -659,7 +654,7 @@ std::any AnalyzerVisitor::visitGenericTypeDef(GenericTypeDefNode *node) { // Check if type already exists in this scope if (currentScope->lookup(node->typeName)) - throw SemanticError(node->codeLoc, GENERIC_TYPE_DECLARED_TWICE, "Duplicate symbol name '" + node->typeName + "'"); + throw SemanticError(node, GENERIC_TYPE_DECLARED_TWICE, "Duplicate symbol name '" + node->typeName + "'"); // Get type conditions std::vector typeConditions; @@ -676,7 +671,7 @@ std::any AnalyzerVisitor::visitGenericTypeDef(GenericTypeDefNode *node) { if (specifier->type == SpecifierNode::TY_PUBLIC) structSymbolSpecifiers.setPublic(true); else - throw SemanticError(specifier->codeLoc, SPECIFIER_AT_ILLEGAL_CONTEXT, "Cannot use this specifier on a struct definition"); + throw SemanticError(specifier, SPECIFIER_AT_ILLEGAL_CONTEXT, "Cannot use this specifier on a struct definition"); } } @@ -692,12 +687,11 @@ std::any AnalyzerVisitor::visitGlobalVarDef(GlobalVarDefNode *node) { // Check if symbol already exists in the symbol table if (currentScope->lookup(node->varName)) - throw SemanticError(node->codeLoc, VARIABLE_DECLARED_TWICE, - "The global variable '" + node->varName + "' was declared more than once"); + throw SemanticError(node, VARIABLE_DECLARED_TWICE, "The global variable '" + node->varName + "' was declared more than once"); // Check if symbol already exists in any imported module scope if (currentScope->lookupGlobal(node->varName, true)) - throw SemanticError(node->codeLoc, VARIABLE_DECLARED_TWICE, + throw SemanticError(node, VARIABLE_DECLARED_TWICE, "A global variable named '" + node->varName + "' is already declared in another module. Please use a different name."); @@ -711,7 +705,7 @@ std::any AnalyzerVisitor::visitGlobalVarDef(GlobalVarDefNode *node) { if (symbolType.is(TY_DYN)) { symbolType = valueType; } else if (symbolType != valueType) { - throw SemanticError(node->value()->codeLoc, OPERATOR_WRONG_DATA_TYPE, + throw SemanticError(node->value(), OPERATOR_WRONG_DATA_TYPE, "Cannot apply the assign operator on different data types. You provided " + symbolType.getName(false) + " and " + valueType.getName(false)); } @@ -720,11 +714,11 @@ std::any AnalyzerVisitor::visitGlobalVarDef(GlobalVarDefNode *node) { // Check if the type is missing if (symbolType.is(TY_DYN)) - throw SemanticError(node->dataType()->codeLoc, GLOBAL_OF_TYPE_DYN, "Global variables must have an explicit data type"); + throw SemanticError(node->dataType(), GLOBAL_OF_TYPE_DYN, "Global variables must have an explicit data type"); // Check if we would need to insert instructions in the global scope if (!symbolType.isPrimitive()) - throw SemanticError(node->dataType()->codeLoc, GLOBAL_OF_INVALID_TYPE, "Spice does not allow global variables of this type"); + throw SemanticError(node->dataType(), GLOBAL_OF_INVALID_TYPE, "Spice does not allow global variables of this type"); // Create symbol specifiers auto symbolTypeSpecifiers = SymbolSpecifiers(symbolType); @@ -733,8 +727,7 @@ std::any AnalyzerVisitor::visitGlobalVarDef(GlobalVarDefNode *node) { if (specifier->type == SpecifierNode::TY_CONST) { // Check if a value is attached if (!node->value()) - throw SemanticError(node->codeLoc, GLOBAL_CONST_WITHOUT_VALUE, - "You must specify a value for constant global variables"); + throw SemanticError(node, GLOBAL_CONST_WITHOUT_VALUE, "You must specify a value for constant global variables"); symbolTypeSpecifiers.setConst(true); } else if (specifier->type == SpecifierNode::TY_SIGNED) { symbolTypeSpecifiers.setSigned(true); @@ -743,8 +736,7 @@ std::any AnalyzerVisitor::visitGlobalVarDef(GlobalVarDefNode *node) { } else if (specifier->type == SpecifierNode::TY_PUBLIC) { symbolTypeSpecifiers.setPublic(true); } else { - throw SemanticError(specifier->codeLoc, SPECIFIER_AT_ILLEGAL_CONTEXT, - "Cannot use this specifier on a global variable definition"); + throw SemanticError(specifier, SPECIFIER_AT_ILLEGAL_CONTEXT, "Cannot use this specifier on a global variable definition"); } } } @@ -765,8 +757,7 @@ std::any AnalyzerVisitor::visitExtDecl(ExtDeclNode *node) { for (const auto &arg : node->argTypeLst()->dataTypes()) { auto argType = any_cast(visit(arg)); if (argType.is(TY_DYN)) - throw SemanticError(arg->codeLoc, UNEXPECTED_DYN_TYPE_SA, - "Dyn data type is not allowed as arg type for external functions"); + throw SemanticError(arg, UNEXPECTED_DYN_TYPE_SA, "Dyn data type is not allowed as arg type for external functions"); argTypes.emplace_back(argType, false); } } @@ -775,7 +766,7 @@ std::any AnalyzerVisitor::visitExtDecl(ExtDeclNode *node) { // Check if return type is dyn auto returnType = any_cast(visit(node->returnType())); if (returnType.is(TY_DYN)) - throw SemanticError(node->returnType()->codeLoc, UNEXPECTED_DYN_TYPE_SA, + throw SemanticError(node->returnType(), UNEXPECTED_DYN_TYPE_SA, "Dyn data type is not allowed as return type for external functions"); // Insert function into symbol table @@ -811,7 +802,7 @@ std::any AnalyzerVisitor::visitThreadDef(ThreadDefNode *node) { // Return to old scope currentScope = currentScope->parent; - return node->setEvaluatedSymbolType(SymbolType(TY_BYTE).toPointer(node->codeLoc)); + return node->setEvaluatedSymbolType(SymbolType(TY_BYTE).toPointer(node)); } std::any AnalyzerVisitor::visitUnsafeBlockDef(UnsafeBlockDefNode *node) { @@ -843,7 +834,7 @@ std::any AnalyzerVisitor::visitForLoop(ForLoopNode *node) { // Visit condition in new scope auto conditionType = any_cast(visit(node->condAssign())); if (!conditionType.is(TY_BOOL)) - throw SemanticError(node->condAssign()->codeLoc, CONDITION_MUST_BE_BOOL, "For loop condition must be of type bool"); + throw SemanticError(node->condAssign(), CONDITION_MUST_BE_BOOL, "For loop condition must be of type bool"); // Visit incrementer in new scope visit(node->incAssign()); @@ -866,11 +857,11 @@ std::any AnalyzerVisitor::visitForeachLoop(ForeachLoopNode *node) { expectedType = SymbolType(TY_DYN); auto arrayType = any_cast(visit(node->arrayAssign())); if (!arrayType.isArray() && !arrayType.is(TY_STRING)) - throw SemanticError(node->arrayAssign()->codeLoc, OPERATOR_WRONG_DATA_TYPE, + throw SemanticError(node->arrayAssign(), OPERATOR_WRONG_DATA_TYPE, "Can only apply foreach loop on an array type. You provided " + arrayType.getName(false)); if (arrayType.getArraySize() == 0) - throw SemanticError(node->arrayAssign()->codeLoc, OPERATOR_WRONG_DATA_TYPE, + throw SemanticError(node->arrayAssign(), OPERATOR_WRONG_DATA_TYPE, "Can only apply foreach loop on an array type of which the size is known at compile time"); // Check index assignment or declaration @@ -883,12 +874,12 @@ std::any AnalyzerVisitor::visitForeachLoop(ForeachLoopNode *node) { std::string varName = node->idxVarDecl()->varName; SymbolTableEntry *entry = currentScope->lookup(varName); assert(entry != nullptr); - entry->updateState(INITIALIZED, node->idxVarDecl()->codeLoc); + entry->updateState(INITIALIZED, node->idxVarDecl()); } // Check if index type is int if (!indexType.is(TY_INT)) - throw SemanticError(node->idxVarDecl()->codeLoc, ARRAY_INDEX_NOT_INT_OR_LONG, + throw SemanticError(node->idxVarDecl(), ARRAY_INDEX_NOT_INT_OR_LONG, "Index in foreach loop must be of type int. You provided " + indexType.getName(false)); } else { // Declare the variable with the default index variable name @@ -910,11 +901,11 @@ std::any AnalyzerVisitor::visitForeachLoop(ForeachLoopNode *node) { node->itemDecl()->dataType()->setEvaluatedSymbolType(itemType); } else { if (itemType != arrayType.getContainedTy()) - throw SemanticError(node->itemDecl()->codeLoc, OPERATOR_WRONG_DATA_TYPE, + throw SemanticError(node->itemDecl(), OPERATOR_WRONG_DATA_TYPE, "Foreach loop item type does not match array type. Expected " + arrayType.getName(false) + ", provided " + itemType.getName(false)); } - itemVarSymbol->updateState(INITIALIZED, node->itemDecl()->codeLoc); + itemVarSymbol->updateState(INITIALIZED, node->itemDecl()); // Visit statement list in new scope nestedLoopCounter++; @@ -934,7 +925,7 @@ std::any AnalyzerVisitor::visitWhileLoop(WhileLoopNode *node) { // Visit condition auto conditionType = any_cast(visit(node->condition())); if (!conditionType.is(TY_BOOL)) - throw SemanticError(node->condition()->codeLoc, CONDITION_MUST_BE_BOOL, "While loop condition must be of type bool"); + throw SemanticError(node->condition(), CONDITION_MUST_BE_BOOL, "While loop condition must be of type bool"); // Visit statement list in new scope nestedLoopCounter++; @@ -954,7 +945,7 @@ std::any AnalyzerVisitor::visitIfStmt(IfStmtNode *node) { // Visit condition auto conditionType = any_cast(visit(node->condition())); if (!conditionType.is(TY_BOOL)) - throw SemanticError(node->condition()->codeLoc, CONDITION_MUST_BE_BOOL, "If condition must be of type bool"); + throw SemanticError(node->condition(), CONDITION_MUST_BE_BOOL, "If condition must be of type bool"); // Visit statement list in new scope visit(node->stmtLst()); @@ -990,7 +981,7 @@ std::any AnalyzerVisitor::visitAssertStmt(AssertStmtNode *node) { // Check if assertStmt evaluates to bool if (!assertConditionType.is(TY_BOOL)) - throw SemanticError(node->assignExpr()->codeLoc, ASSERTION_CONDITION_BOOL, "The asserted condition must be of type bool"); + throw SemanticError(node->assignExpr(), ASSERTION_CONDITION_BOOL, "The asserted condition must be of type bool"); return nullptr; } @@ -1004,13 +995,13 @@ std::any AnalyzerVisitor::visitParamLst(ParamLstNode *node) { // Check if the type could be inferred. Dyn without a default value is forbidden if (paramType.is(TY_DYN)) - throw SemanticError(node->codeLoc, FCT_PARAM_IS_TYPE_DYN, "Type of parameter '" + param->varName + "' is invalid"); + throw SemanticError(node, FCT_PARAM_IS_TYPE_DYN, "Type of parameter '" + param->varName + "' is invalid"); // Ensure that no optional param comes after a mandatory param if (param->hasAssignment) { metOptional = true; } else if (metOptional) { - throw SemanticError(param->codeLoc, INVALID_PARAM_ORDER, "Mandatory parameters must go before any optional parameters"); + throw SemanticError(param, INVALID_PARAM_ORDER, "Mandatory parameters must go before any optional parameters"); } namedParamList.emplace_back(param->varName, paramType, metOptional); @@ -1021,8 +1012,7 @@ std::any AnalyzerVisitor::visitParamLst(ParamLstNode *node) { std::any AnalyzerVisitor::visitDeclStmt(DeclStmtNode *node) { // Check if symbol already exists in the symbol table if (currentScope->lookupStrict(node->varName)) - throw SemanticError(node->codeLoc, VARIABLE_DECLARED_TWICE, - "The variable '" + node->varName + "' was declared more than once"); + throw SemanticError(node, VARIABLE_DECLARED_TWICE, "The variable '" + node->varName + "' was declared more than once"); // Get the type of the symbol SymbolType symbolType = expectedType = any_cast(visit(node->dataType())); @@ -1032,7 +1022,7 @@ std::any AnalyzerVisitor::visitDeclStmt(DeclStmtNode *node) { if (node->hasAssignment) { auto rhsTy = any_cast(visit(node->assignExpr())); // Check if type has to be inferred or both types are fixed - symbolType = opRuleManager->getAssignResultType(node->codeLoc, symbolType, rhsTy); + symbolType = opRuleManager->getAssignResultType(node, symbolType, rhsTy); initialState = INITIALIZED; // Push symbolType to the declaration data type @@ -1040,8 +1030,7 @@ std::any AnalyzerVisitor::visitDeclStmt(DeclStmtNode *node) { // If the rhs is of type array and was the array initialization, there must be a size attached if (symbolType.isArray() && symbolType.getArraySize() == 0 && currentVarName.empty()) - throw SemanticError(node->dataType()->codeLoc, ARRAY_SIZE_INVALID, - "The declaration of an array type must have a size attached"); + throw SemanticError(node->dataType(), ARRAY_SIZE_INVALID, "The declaration of an array type must have a size attached"); } // Build symbol specifiers @@ -1057,8 +1046,7 @@ std::any AnalyzerVisitor::visitDeclStmt(DeclStmtNode *node) { symbolTypeSpecifiers.setSigned(false); symbolType.isBaseTypeSigned = false; } else { - throw SemanticError(specifier->codeLoc, SPECIFIER_AT_ILLEGAL_CONTEXT, - "Cannot use this specifier on a local variable declaration"); + throw SemanticError(specifier, SPECIFIER_AT_ILLEGAL_CONTEXT, "Cannot use this specifier on a local variable declaration"); } } } @@ -1092,33 +1080,32 @@ std::any AnalyzerVisitor::visitReturnStmt(ReturnStmtNode *node) { } else { // Check if return type matches with function definition if (returnType != returnVariable->type) - throw SemanticError(node->assignExpr()->codeLoc, OPERATOR_WRONG_DATA_TYPE, + throw SemanticError(node->assignExpr(), OPERATOR_WRONG_DATA_TYPE, "Passed wrong data type to return statement. Expected " + returnVariable->type.getName(false) + " but got " + returnType.getName(false)); } // Set the return variable to initialized - returnVariable->updateState(INITIALIZED, node->codeLoc); + returnVariable->updateState(INITIALIZED, node); } else { returnType = returnVariable->type; } // Check if result variable is initialized if (returnVariable->state != INITIALIZED) - throw SemanticError(node->codeLoc, RETURN_WITHOUT_VALUE_RESULT, - "Return without value, but result variable is not initialized yet"); + throw SemanticError(node, RETURN_WITHOUT_VALUE_RESULT, "Return without value, but result variable is not initialized yet"); returnVariable->isUsed = true; } else { // No return variable => procedure if (node->assignExpr()) - throw SemanticError(node->assignExpr()->codeLoc, RETURN_WITH_VALUE_IN_PROCEDURE, + throw SemanticError(node->assignExpr(), RETURN_WITH_VALUE_IN_PROCEDURE, "Return statements in procedures may not have a value attached"); } // Call destructors for variables, that are going out of scope std::vector varsToDestruct = currentScope->getVarsGoingOutOfScope(true); for (SymbolTableEntry *varEntry : varsToDestruct) - insertDestructorCall(varEntry->getDeclCodeLoc(), varEntry); + insertDestructorCall(varEntry->getDeclNode(), varEntry); return nullptr; } @@ -1127,13 +1114,12 @@ std::any AnalyzerVisitor::visitBreakStmt(BreakStmtNode *node) { if (node->breakTimes != 1) { // Check if the stated number is valid if (node->breakTimes < 1) - throw SemanticError(node->codeLoc, INVALID_BREAK_NUMBER, + throw SemanticError(node, INVALID_BREAK_NUMBER, "Break count must be >= 1, you provided " + std::to_string(node->breakTimes)); } // Check if we can break this often if (node->breakTimes > nestedLoopCounter) - throw SemanticError(node->codeLoc, INVALID_BREAK_NUMBER, - "We can only break " + std::to_string(nestedLoopCounter) + " time(s) here"); + throw SemanticError(node, INVALID_BREAK_NUMBER, "We can only break " + std::to_string(nestedLoopCounter) + " time(s) here"); return nullptr; } @@ -1141,12 +1127,12 @@ std::any AnalyzerVisitor::visitContinueStmt(ContinueStmtNode *node) { if (node->continueTimes != 1) { // Check if the stated number is valid if (node->continueTimes < 1) - throw SemanticError(node->codeLoc, INVALID_CONTINUE_NUMBER, + throw SemanticError(node, INVALID_CONTINUE_NUMBER, "Continue count must be >= 1, you provided " + std::to_string(node->continueTimes)); } // Check if we can continue this often if (node->continueTimes > nestedLoopCounter) - throw SemanticError(node->codeLoc, INVALID_CONTINUE_NUMBER, + throw SemanticError(node, INVALID_CONTINUE_NUMBER, "We can only continue " + std::to_string(nestedLoopCounter) + " time(s) here"); return nullptr; } @@ -1158,7 +1144,7 @@ std::any AnalyzerVisitor::visitPrintfCall(PrintfCallNode *node) { while (index != std::string::npos) { // Check if there is another assignExpr if (node->assignExpr().size() <= placeholderCount) - throw SemanticError(node->codeLoc, PRINTF_ARG_COUNT_ERROR, + throw SemanticError(node, PRINTF_ARG_COUNT_ERROR, "The placeholder string contains more placeholders that arguments were passed"); auto assignment = node->assignExpr()[placeholderCount]; @@ -1166,7 +1152,7 @@ std::any AnalyzerVisitor::visitPrintfCall(PrintfCallNode *node) { switch (node->templatedString[index + 1]) { case 'c': { if (!assignmentType.is(TY_CHAR)) - throw SemanticError(assignment->codeLoc, PRINTF_TYPE_ERROR, + throw SemanticError(assignment, PRINTF_TYPE_ERROR, "Template string expects char, but got " + assignmentType.getName(false)); placeholderCount++; break; @@ -1179,7 +1165,7 @@ std::any AnalyzerVisitor::visitPrintfCall(PrintfCallNode *node) { case 'x': case 'X': { if (!assignmentType.isOneOf({TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_BOOL})) - throw SemanticError(assignment->codeLoc, PRINTF_TYPE_ERROR, + throw SemanticError(assignment, PRINTF_TYPE_ERROR, "Template string expects int, byte or bool, but got " + assignmentType.getName(false)); placeholderCount++; break; @@ -1193,21 +1179,21 @@ std::any AnalyzerVisitor::visitPrintfCall(PrintfCallNode *node) { case 'g': case 'G': { if (!assignmentType.is(TY_DOUBLE)) - throw SemanticError(assignment->codeLoc, PRINTF_TYPE_ERROR, + throw SemanticError(assignment, PRINTF_TYPE_ERROR, "Template string expects double, but got " + assignmentType.getName(false)); placeholderCount++; break; } case 's': { if (!assignmentType.is(TY_STRING) && !assignmentType.isPointerOf(TY_CHAR) && !assignmentType.isArrayOf(TY_CHAR)) - throw SemanticError(assignment->codeLoc, PRINTF_TYPE_ERROR, + throw SemanticError(assignment, PRINTF_TYPE_ERROR, "Template string expects string, but got " + assignmentType.getName(false)); placeholderCount++; break; } case 'p': { if (!assignmentType.isPointer() && !assignmentType.isArray()) - throw SemanticError(assignment->codeLoc, PRINTF_TYPE_ERROR, + throw SemanticError(assignment, PRINTF_TYPE_ERROR, "Template string expects pointer, but got " + assignmentType.getName(false)); placeholderCount++; break; @@ -1218,7 +1204,7 @@ std::any AnalyzerVisitor::visitPrintfCall(PrintfCallNode *node) { // Check if the number of placeholders matches the number of args if (placeholderCount < node->assignExpr().size()) - throw SemanticError(node->codeLoc, PRINTF_ARG_COUNT_ERROR, + throw SemanticError(node, PRINTF_ARG_COUNT_ERROR, "The placeholder string contains less placeholders that arguments were passed"); return node->setEvaluatedSymbolType(SymbolType(TY_BOOL)); @@ -1234,7 +1220,7 @@ std::any AnalyzerVisitor::visitSizeofCall(SizeofCallNode *node) { // Check if symbol type is dynamically sized array if (symbolType.is(TY_ARRAY) && symbolType.getArraySize() == -1) - throw SemanticError(node->codeLoc, SIZEOF_DYNAMIC_SIZED_ARRAY, "Cannot get sizeof dynamically sized array at compile time"); + throw SemanticError(node, SIZEOF_DYNAMIC_SIZED_ARRAY, "Cannot get sizeof dynamically sized array at compile time"); return node->setEvaluatedSymbolType(SymbolType(TY_INT)); } @@ -1244,7 +1230,7 @@ std::any AnalyzerVisitor::visitLenCall(LenCallNode *node) { // Check if arg is of type array if (!argType.isArray()) - throw SemanticError(node->assignExpr()->codeLoc, EXPECTED_ARRAY_TYPE, "The len builtin can only work on arrays"); + throw SemanticError(node->assignExpr(), EXPECTED_ARRAY_TYPE, "The len builtin can only work on arrays"); return node->setEvaluatedSymbolType(SymbolType(TY_INT)); } @@ -1255,11 +1241,11 @@ std::any AnalyzerVisitor::visitTidCall(TidCallNode *node) { } std::any AnalyzerVisitor::visitJoinCall(JoinCallNode *node) { - SymbolType bytePtr = SymbolType(TY_BYTE).toPointer(node->codeLoc); + SymbolType bytePtr = SymbolType(TY_BYTE).toPointer(node); for (const auto &assignExpr : node->assignExpressions()) { auto argSymbolType = any_cast(visit(assignExpr)); if (argSymbolType == bytePtr && argSymbolType.isArrayOf(bytePtr)) - throw SemanticError(assignExpr->codeLoc, JOIN_ARG_MUST_BE_TID, + throw SemanticError(assignExpr, JOIN_ARG_MUST_BE_TID, "You have to pass a thread id (byte*) or a array of thread ids (byte*[]) to to join builtin"); } @@ -1281,33 +1267,33 @@ std::any AnalyzerVisitor::visitAssignExpr(AssignExprNode *node) { // Take a look at the operator if (node->op == AssignExprNode::OP_ASSIGN) { - rhsTy = opRuleManager->getAssignResultType(node->codeLoc, lhsTy, rhsTy); + rhsTy = opRuleManager->getAssignResultType(node, lhsTy, rhsTy); } else if (node->op == AssignExprNode::OP_PLUS_EQUAL) { rhsTy = opRuleManager->getPlusEqualResultType(node, lhsTy, rhsTy); } else if (node->op == AssignExprNode::OP_MINUS_EQUAL) { - rhsTy = opRuleManager->getMinusEqualResultType(node->codeLoc, lhsTy, rhsTy); + rhsTy = opRuleManager->getMinusEqualResultType(node, lhsTy, rhsTy); } else if (node->op == AssignExprNode::OP_MUL_EQUAL) { rhsTy = opRuleManager->getMulEqualResultType(node, lhsTy, rhsTy); } else if (node->op == AssignExprNode::OP_DIV_EQUAL) { - rhsTy = opRuleManager->getDivEqualResultType(node->codeLoc, lhsTy, rhsTy); + rhsTy = opRuleManager->getDivEqualResultType(node, lhsTy, rhsTy); } else if (node->op == AssignExprNode::OP_REM_EQUAL) { - rhsTy = opRuleManager->getRemEqualResultType(node->codeLoc, lhsTy, rhsTy); + rhsTy = opRuleManager->getRemEqualResultType(node, lhsTy, rhsTy); } else if (node->op == AssignExprNode::OP_SHL_EQUAL) { - rhsTy = opRuleManager->getSHLEqualResultType(node->codeLoc, lhsTy, rhsTy); + rhsTy = opRuleManager->getSHLEqualResultType(node, lhsTy, rhsTy); } else if (node->op == AssignExprNode::OP_SHR_EQUAL) { - rhsTy = opRuleManager->getSHREqualResultType(node->codeLoc, lhsTy, rhsTy); + rhsTy = opRuleManager->getSHREqualResultType(node, lhsTy, rhsTy); } else if (node->op == AssignExprNode::OP_AND_EQUAL) { - rhsTy = opRuleManager->getAndEqualResultType(node->codeLoc, lhsTy, rhsTy); + rhsTy = opRuleManager->getAndEqualResultType(node, lhsTy, rhsTy); } else if (node->op == AssignExprNode::OP_OR_EQUAL) { - rhsTy = opRuleManager->getOrEqualResultType(node->codeLoc, lhsTy, rhsTy); + rhsTy = opRuleManager->getOrEqualResultType(node, lhsTy, rhsTy); } else if (node->op == AssignExprNode::OP_XOR_EQUAL) { - rhsTy = opRuleManager->getXorEqualResultType(node->codeLoc, lhsTy, rhsTy); + rhsTy = opRuleManager->getXorEqualResultType(node, lhsTy, rhsTy); } if (!variableName.empty()) { // Variable is involved on the left side // Check if the symbol exists if (!currentEntry) - throw SemanticError(node->lhs()->codeLoc, REFERENCED_UNDEFINED_VARIABLE, + throw SemanticError(node->lhs(), REFERENCED_UNDEFINED_VARIABLE, "The variable '" + variableName + "' was referenced before defined"); // Perform type inference @@ -1316,7 +1302,7 @@ std::any AnalyzerVisitor::visitAssignExpr(AssignExprNode *node) { // Update state in symbol table if (!currentEntry->type.isOneOf({TY_FUNCTION, TY_PROCEDURE})) - currentEntry->updateState(INITIALIZED, node->lhs()->codeLoc); + currentEntry->updateState(INITIALIZED, node->lhs()); // In case the lhs variable is captured, notify the capture about the write access Capture *lhsCapture = currentScope->lookupCapture(variableName); @@ -1358,11 +1344,10 @@ std::any AnalyzerVisitor::visitTernaryExpr(TernaryExprNode *node) { } // Check if the condition evaluates to boolean if (!conditionType.is(TY_BOOL)) - throw SemanticError(condition->codeLoc, OPERATOR_WRONG_DATA_TYPE, "Condition operand in ternary must be a bool"); + throw SemanticError(condition, OPERATOR_WRONG_DATA_TYPE, "Condition operand in ternary must be a bool"); // Check if trueType and falseType are matching if (trueType != falseType) - throw SemanticError(node->codeLoc, OPERATOR_WRONG_DATA_TYPE, - "True and false operands in ternary must be of same data type"); + throw SemanticError(node, OPERATOR_WRONG_DATA_TYPE, "True and false operands in ternary must be of same data type"); return node->setEvaluatedSymbolType(trueType); } return visit(node->operands().front()); @@ -1374,7 +1359,7 @@ std::any AnalyzerVisitor::visitLogicalOrExpr(LogicalOrExprNode *node) { auto lhsTy = any_cast(visit(node->operands()[0])); for (int i = 1; i < node->operands().size(); i++) { auto rhsTy = any_cast(visit(node->operands()[i])); - lhsTy = opRuleManager->getLogicalOrResultType(node->codeLoc, lhsTy, rhsTy); + lhsTy = opRuleManager->getLogicalOrResultType(node, lhsTy, rhsTy); } return node->setEvaluatedSymbolType(lhsTy); } @@ -1387,7 +1372,7 @@ std::any AnalyzerVisitor::visitLogicalAndExpr(LogicalAndExprNode *node) { auto lhsTy = any_cast(visit(node->operands()[0])); for (int i = 1; i < node->operands().size(); i++) { auto rhsTy = any_cast(visit(node->operands()[i])); - lhsTy = opRuleManager->getLogicalAndResultType(node->codeLoc, lhsTy, rhsTy); + lhsTy = opRuleManager->getLogicalAndResultType(node, lhsTy, rhsTy); } return node->setEvaluatedSymbolType(lhsTy); } @@ -1400,7 +1385,7 @@ std::any AnalyzerVisitor::visitBitwiseOrExpr(BitwiseOrExprNode *node) { auto lhsTy = any_cast(visit(node->operands()[0])); for (int i = 1; i < node->operands().size(); i++) { auto rhsTy = any_cast(visit(node->operands()[i])); - lhsTy = opRuleManager->getBitwiseOrResultType(node->codeLoc, lhsTy, rhsTy); + lhsTy = opRuleManager->getBitwiseOrResultType(node, lhsTy, rhsTy); } return node->setEvaluatedSymbolType(lhsTy); } @@ -1413,7 +1398,7 @@ std::any AnalyzerVisitor::visitBitwiseXorExpr(BitwiseXorExprNode *node) { auto lhsTy = any_cast(visit(node->operands()[0])); for (int i = 1; i < node->operands().size(); i++) { auto rhsTy = any_cast(visit(node->operands()[i])); - lhsTy = opRuleManager->getBitwiseXorResultType(node->codeLoc, lhsTy, rhsTy); + lhsTy = opRuleManager->getBitwiseXorResultType(node, lhsTy, rhsTy); } return node->setEvaluatedSymbolType(lhsTy); } @@ -1426,7 +1411,7 @@ std::any AnalyzerVisitor::visitBitwiseAndExpr(BitwiseAndExprNode *node) { auto lhsTy = any_cast(visit(node->operands()[0])); for (int i = 1; i < node->operands().size(); i++) { auto rhsTy = any_cast(visit(node->operands()[i])); - lhsTy = opRuleManager->getBitwiseAndResultType(node->codeLoc, lhsTy, rhsTy); + lhsTy = opRuleManager->getBitwiseAndResultType(node, lhsTy, rhsTy); } return node->setEvaluatedSymbolType(lhsTy); } @@ -1440,9 +1425,9 @@ std::any AnalyzerVisitor::visitEqualityExpr(EqualityExprNode *node) { auto rhsTy = any_cast(visit(node->operands()[1])); if (node->op == EqualityExprNode::OP_EQUAL) // Operator was equal - return node->setEvaluatedSymbolType(opRuleManager->getEqualResultType(node->codeLoc, lhsTy, rhsTy)); + return node->setEvaluatedSymbolType(opRuleManager->getEqualResultType(node, lhsTy, rhsTy)); else if (node->op == EqualityExprNode::OP_NOT_EQUAL) // Operator was not equal - return node->setEvaluatedSymbolType(opRuleManager->getNotEqualResultType(node->codeLoc, lhsTy, rhsTy)); + return node->setEvaluatedSymbolType(opRuleManager->getNotEqualResultType(node, lhsTy, rhsTy)); } return visit(node->operands().front()); } @@ -1454,13 +1439,13 @@ std::any AnalyzerVisitor::visitRelationalExpr(RelationalExprNode *node) { auto rhsTy = any_cast(visit(node->operands()[1])); if (node->op == RelationalExprNode::OP_LESS) // Operator was less - return node->setEvaluatedSymbolType(opRuleManager->getLessResultType(node->codeLoc, lhsTy, rhsTy)); + return node->setEvaluatedSymbolType(opRuleManager->getLessResultType(node, lhsTy, rhsTy)); else if (node->op == RelationalExprNode::OP_GREATER) // Operator was greater - return node->setEvaluatedSymbolType(opRuleManager->getGreaterResultType(node->codeLoc, lhsTy, rhsTy)); + return node->setEvaluatedSymbolType(opRuleManager->getGreaterResultType(node, lhsTy, rhsTy)); else if (node->op == RelationalExprNode::OP_LESS_EQUAL) // Operator was less equal - return node->setEvaluatedSymbolType(opRuleManager->getLessEqualResultType(node->codeLoc, lhsTy, rhsTy)); + return node->setEvaluatedSymbolType(opRuleManager->getLessEqualResultType(node, lhsTy, rhsTy)); else if (node->op == RelationalExprNode::OP_GREATER_EQUAL) // Operator was greater equal - return node->setEvaluatedSymbolType(opRuleManager->getGreaterEqualResultType(node->codeLoc, lhsTy, rhsTy)); + return node->setEvaluatedSymbolType(opRuleManager->getGreaterEqualResultType(node, lhsTy, rhsTy)); } return visit(node->operands().front()); } @@ -1472,9 +1457,9 @@ std::any AnalyzerVisitor::visitShiftExpr(ShiftExprNode *node) { auto rhsTy = any_cast(visit(node->operands()[1])); if (node->op == ShiftExprNode::OP_SHIFT_LEFT) // Operator was shl - return node->setEvaluatedSymbolType(opRuleManager->getShiftLeftResultType(node->codeLoc, lhsTy, rhsTy)); + return node->setEvaluatedSymbolType(opRuleManager->getShiftLeftResultType(node, lhsTy, rhsTy)); else if (node->op == ShiftExprNode::OP_SHIFT_RIGHT) // Operator was shr - return node->setEvaluatedSymbolType(opRuleManager->getShiftRightResultType(node->codeLoc, lhsTy, rhsTy)); + return node->setEvaluatedSymbolType(opRuleManager->getShiftRightResultType(node, lhsTy, rhsTy)); } return visit(node->operands().front()); } @@ -1497,7 +1482,7 @@ std::any AnalyzerVisitor::visitAdditiveExpr(AdditiveExprNode *node) { currentType = opRuleManager->getPlusResultType(operand, currentType, operandType); break; case AdditiveExprNode::OP_MINUS: - currentType = opRuleManager->getMinusResultType(operand->codeLoc, currentType, operandType); + currentType = opRuleManager->getMinusResultType(operand, currentType, operandType); break; default: throw std::runtime_error("Additive expr fall-through"); @@ -1531,10 +1516,10 @@ std::any AnalyzerVisitor::visitMultiplicativeExpr(MultiplicativeExprNode *node) currentType = opRuleManager->getMulResultType(operand, currentType, operandType); break; case MultiplicativeExprNode::OP_DIV: - currentType = opRuleManager->getDivResultType(operand->codeLoc, currentType, operandType); + currentType = opRuleManager->getDivResultType(operand, currentType, operandType); break; case MultiplicativeExprNode::OP_REM: - currentType = opRuleManager->getRemResultType(operand->codeLoc, currentType, operandType); + currentType = opRuleManager->getRemResultType(operand, currentType, operandType); break; default: throw std::runtime_error("Multiplicative expr fall-through"); @@ -1556,7 +1541,7 @@ std::any AnalyzerVisitor::visitCastExpr(CastExprNode *node) { if (node->isCasted) { // Cast is applied auto srcType = any_cast(rhs); auto dstType = any_cast(visit(node->dataType())); - SymbolType symbolType = opRuleManager->getCastResultType(node->codeLoc, dstType, any_cast(rhs)); + SymbolType symbolType = opRuleManager->getCastResultType(node, dstType, any_cast(rhs)); return node->setEvaluatedSymbolType(symbolType); } @@ -1575,41 +1560,41 @@ std::any AnalyzerVisitor::visitPrefixUnaryExpr(PrefixUnaryExprNode *node) { while (!opStack.empty()) { switch (opStack.top().first) { case PrefixUnaryExprNode::OP_MINUS: - rhs = opRuleManager->getPrefixMinusResultType(node->postfixUnaryExpr()->codeLoc, rhs); + rhs = opRuleManager->getPrefixMinusResultType(node->postfixUnaryExpr(), rhs); break; case PrefixUnaryExprNode::OP_PLUS_PLUS: - rhs = opRuleManager->getPrefixPlusPlusResultType(node->postfixUnaryExpr()->codeLoc, rhs); + rhs = opRuleManager->getPrefixPlusPlusResultType(node->postfixUnaryExpr(), rhs); // Update state in symbol table if (currentEntry != nullptr) - currentEntry->updateState(INITIALIZED, node->codeLoc); + currentEntry->updateState(INITIALIZED, node); // In case the lhs is captured, notify the capture about the write access if (Capture *lhsCapture = currentScope->lookupCapture(currentVarName); lhsCapture) lhsCapture->setCaptureMode(READ_WRITE); break; case PrefixUnaryExprNode::OP_MINUS_MINUS: - rhs = opRuleManager->getPrefixMinusMinusResultType(node->postfixUnaryExpr()->codeLoc, rhs); + rhs = opRuleManager->getPrefixMinusMinusResultType(node->postfixUnaryExpr(), rhs); // Update state in symbol table if (currentEntry != nullptr) - currentEntry->updateState(INITIALIZED, node->codeLoc); + currentEntry->updateState(INITIALIZED, node); // In case the lhs is captured, notify the capture about the write access if (Capture *lhsCapture = currentScope->lookupCapture(currentVarName); lhsCapture) lhsCapture->setCaptureMode(READ_WRITE); break; case PrefixUnaryExprNode::OP_NOT: - rhs = opRuleManager->getPrefixNotResultType(node->postfixUnaryExpr()->codeLoc, rhs); + rhs = opRuleManager->getPrefixNotResultType(node->postfixUnaryExpr(), rhs); break; case PrefixUnaryExprNode::OP_BITWISE_NOT: - rhs = opRuleManager->getPrefixBitwiseNotResultType(node->postfixUnaryExpr()->codeLoc, rhs); + rhs = opRuleManager->getPrefixBitwiseNotResultType(node->postfixUnaryExpr(), rhs); break; case PrefixUnaryExprNode::OP_INDIRECTION: - rhs = opRuleManager->getPrefixMulResultType(node->postfixUnaryExpr()->codeLoc, rhs); + rhs = opRuleManager->getPrefixMulResultType(node->postfixUnaryExpr(), rhs); break; case PrefixUnaryExprNode::OP_ADDRESS_OF: - rhs = opRuleManager->getPrefixBitwiseAndResultType(node->postfixUnaryExpr()->codeLoc, rhs); + rhs = opRuleManager->getPrefixBitwiseAndResultType(node->postfixUnaryExpr(), rhs); break; default: throw std::runtime_error("Prefix unary fall-through"); @@ -1626,7 +1611,7 @@ std::any AnalyzerVisitor::visitPrefixUnaryExpr(PrefixUnaryExprNode *node) { std::any AnalyzerVisitor::visitPostfixUnaryExpr(PostfixUnaryExprNode *node) { auto lhs = any_cast(visit(node->atomicExpr())); if (lhs.is(TY_INVALID)) - throw SemanticError(node->codeLoc, REFERENCED_UNDEFINED_VARIABLE, + throw SemanticError(node, REFERENCED_UNDEFINED_VARIABLE, "Variable '" + node->atomicExpr()->identifier + "' was referenced before declared"); size_t subscriptCounter = 0; @@ -1645,20 +1630,20 @@ std::any AnalyzerVisitor::visitPostfixUnaryExpr(PostfixUnaryExprNode *node) { auto indexType = any_cast(visit(indexExpr)); if (!indexType.isOneOf({TY_INT, TY_LONG})) - throw SemanticError(node->codeLoc, ARRAY_INDEX_NOT_INT_OR_LONG, "Array index must be of type int or long"); + throw SemanticError(node, ARRAY_INDEX_NOT_INT_OR_LONG, "Array index must be of type int or long"); if (!lhs.isOneOf({TY_ARRAY, TY_STRING, TY_PTR})) - throw SemanticError(node->codeLoc, OPERATOR_WRONG_DATA_TYPE, + throw SemanticError(node, OPERATOR_WRONG_DATA_TYPE, "Can only apply subscript operator on array type, got " + lhs.getName(true)); if (lhs.is(TY_PTR) && !allowUnsafeOperations) { throw SemanticError( - node->codeLoc, UNSAFE_OPERATION_IN_SAFE_CONTEXT, + node, UNSAFE_OPERATION_IN_SAFE_CONTEXT, "The subscript operator on pointers is an unsafe operation. Use unsafe blocks if you know what you are doing."); } else if (lhs.is(TY_ARRAY) && lhs.getArraySize() > 0 && indexExpr->hasCompileTimeValue()) { std::int32_t constIndex = indexExpr->getCompileTimeValue().intValue; size_t constSize = lhs.getArraySize(); if (constIndex >= constSize) - throw SemanticError(node->codeLoc, ARRAY_INDEX_OUT_OF_BOUNDS, + throw SemanticError(node, ARRAY_INDEX_OUT_OF_BOUNDS, "You are trying to access element with index " + std::to_string(constIndex) + " of an array with size " + std::to_string(constSize)); } @@ -1687,7 +1672,7 @@ std::any AnalyzerVisitor::visitPostfixUnaryExpr(PostfixUnaryExprNode *node) { case PostfixUnaryExprNode::OP_MEMBER_ACCESS: { // Check if lhs is struct if (!lhs.isBaseType(TY_STRUCT) && !lhs.isOneOf({TY_ENUM, TY_STRING})) - throw SemanticError(node->codeLoc, MEMBER_ACCESS_ONLY_STRUCTS, "Cannot apply member access operator on " + lhs.getName()); + throw SemanticError(node, MEMBER_ACCESS_ONLY_STRUCTS, "Cannot apply member access operator on " + lhs.getName()); PostfixUnaryExprNode *rhs = node->postfixUnaryExpr()[memberAccessCounter++]; @@ -1709,18 +1694,18 @@ std::any AnalyzerVisitor::visitPostfixUnaryExpr(PostfixUnaryExprNode *node) { case PostfixUnaryExprNode::OP_SCOPE_ACCESS: { // Check if lhs is import if (!lhs.is(TY_IMPORT)) - throw SemanticError(node->codeLoc, SCOPE_ACCESS_ONLY_IMPORTS, "Cannot apply scope access operator on " + lhs.getName()); + throw SemanticError(node, SCOPE_ACCESS_ONLY_IMPORTS, "Cannot apply scope access operator on " + lhs.getName()); PostfixUnaryExprNode *rhs = node->postfixUnaryExpr()[memberAccessCounter++]; lhs = any_cast(visit(rhs)); // Visit rhs break; } case PostfixUnaryExprNode::OP_PLUS_PLUS: { - lhs = opRuleManager->getPostfixPlusPlusResultType(node->atomicExpr()->codeLoc, lhs); + lhs = opRuleManager->getPostfixPlusPlusResultType(node->atomicExpr(), lhs); // Update state in symbol table if (currentEntry != nullptr) - currentEntry->updateState(INITIALIZED, node->codeLoc); + currentEntry->updateState(INITIALIZED, node); // In case the lhs is captured, notify the capture about the write access if (Capture *lhsCapture = currentScope->lookupCapture(currentVarName); lhsCapture) @@ -1728,11 +1713,11 @@ std::any AnalyzerVisitor::visitPostfixUnaryExpr(PostfixUnaryExprNode *node) { break; } case PostfixUnaryExprNode::OP_MINUS_MINUS: { - lhs = opRuleManager->getPostfixMinusMinusResultType(node->atomicExpr()->codeLoc, lhs); + lhs = opRuleManager->getPostfixMinusMinusResultType(node->atomicExpr(), lhs); // Update state in symbol table if (currentEntry != nullptr) - currentEntry->updateState(INITIALIZED, node->codeLoc); + currentEntry->updateState(INITIALIZED, node); // In case the lhs is captured, notify the capture about the write access if (Capture *lhsCapture = currentScope->lookupCapture(currentVarName); lhsCapture) @@ -1749,8 +1734,7 @@ std::any AnalyzerVisitor::visitPostfixUnaryExpr(PostfixUnaryExprNode *node) { node->opQueue = newOpQueue; if (lhs.is(TY_INVALID)) - throw SemanticError(node->codeLoc, REFERENCED_UNDEFINED_VARIABLE, - "Variable '" + currentVarName + "' was referenced before declared"); + throw SemanticError(node, REFERENCED_UNDEFINED_VARIABLE, "Variable '" + currentVarName + "' was referenced before declared"); return node->setEvaluatedSymbolType(lhs); } @@ -1765,7 +1749,7 @@ std::any AnalyzerVisitor::visitAtomicExpr(AtomicExprNode *node) { // Check if this is a reserved keyword if (std::find(RESERVED_KEYWORDS.begin(), RESERVED_KEYWORDS.end(), currentVarName) != RESERVED_KEYWORDS.end()) throw SemanticError( - node->codeLoc, RESERVED_KEYWORD, + node, RESERVED_KEYWORD, "'" + currentVarName + "' is a reserved keyword for future development of the language. Please use another identifier instead"); @@ -1784,12 +1768,12 @@ std::any AnalyzerVisitor::visitAtomicExpr(AtomicExprNode *node) { if (accessScope->isImported(currentScope)) { // Check if the entry is public if it is imported if (!entry->specifiers.isPublic()) - throw SemanticError(node->codeLoc, INSUFFICIENT_VISIBILITY, + throw SemanticError(node, INSUFFICIENT_VISIBILITY, "Cannot access '" + currentVarName + "' due to its private visibility"); // Check if the entry is an external global variable and needs to be imported if (entry->isGlobal && !entry->type.isOneOf({TY_FUNCTION, TY_PROCEDURE, TY_IMPORT})) - initExtGlobal(accessScope, scopePath.getScopePrefix(true), entry->name, node->codeLoc); + initExtGlobal(accessScope, scopePath.getScopePrefix(true), entry->name, node); } // Set symbol to used @@ -1812,7 +1796,7 @@ std::any AnalyzerVisitor::visitAtomicExpr(AtomicExprNode *node) { // Check if the entry is public if it is imported if (structCapture && !structCapture->capturedEntry->specifiers.isPublic() && accessScope->parent->isImported(currentScope)) - throw SemanticError(node->codeLoc, INSUFFICIENT_VISIBILITY, + throw SemanticError(node, INSUFFICIENT_VISIBILITY, "Cannot access '" + structSignature + "' due to its private visibility"); // If the return type is an external struct, initialize it @@ -1821,7 +1805,7 @@ std::any AnalyzerVisitor::visitAtomicExpr(AtomicExprNode *node) { assert(parentStruct != nullptr); std::string scopePrefix = CommonUtil::getPrefix(parentStruct->type.getSubType(), "."); SymbolType symbolType = initExtStruct(accessScope, scopePrefix, entry->type.getBaseType().getSubType(), - currentThisType.getTemplateTypes(), node->codeLoc); + currentThisType.getTemplateTypes(), node); return node->setEvaluatedSymbolType(symbolType); } } else if (entry->type.isBaseType(TY_ENUM)) { // Enum @@ -1830,7 +1814,7 @@ std::any AnalyzerVisitor::visitAtomicExpr(AtomicExprNode *node) { } else { // Check if we have seen a 'this.' prefix, because the generator needs that if (entry->scope->scopeType == SCOPE_STRUCT && currentThisType.is(TY_DYN)) - throw SemanticError(node->codeLoc, REFERENCED_UNDEFINED_VARIABLE, + throw SemanticError(node, REFERENCED_UNDEFINED_VARIABLE, "The symbol '" + currentVarName + "' could not be found. Missing 'this.' prefix?"); } assert(accessScope != nullptr); @@ -1880,7 +1864,7 @@ std::any AnalyzerVisitor::visitValue(ValueNode *node) { if (node->isNil) { auto nilType = any_cast(visit(node->nilType())); if (nilType.is(TY_DYN)) - throw SemanticError(node->nilType()->codeLoc, UNEXPECTED_DYN_TYPE_SA, "Nil must have an explicit type"); + throw SemanticError(node->nilType(), UNEXPECTED_DYN_TYPE_SA, "Nil must have an explicit type"); return node->setEvaluatedSymbolType(nilType); } @@ -1934,7 +1918,7 @@ std::any AnalyzerVisitor::visitFunctionCall(FunctionCallNode *node) { if (i < node->functionNameFragments.size() - 1) { if (!symbolEntry) - throw SemanticError(node->codeLoc, REFERENCED_UNDEFINED_FUNCTION, + throw SemanticError(node, REFERENCED_UNDEFINED_FUNCTION, "Symbol '" + scopePath.getScopePrefix() + identifier + "' was used before defined"); thisType = symbolBaseType; } else if (symbolEntry != nullptr && symbolBaseType.is(TY_STRUCT)) { @@ -1947,9 +1931,9 @@ std::any AnalyzerVisitor::visitFunctionCall(FunctionCallNode *node) { std::string structSignature = Struct::getSignature(identifier, concreteTemplateTypes); // Get the struct instance - Struct *spiceStruct = accessScope->matchStruct(currentScope, identifier, concreteTemplateTypes, node->codeLoc); + Struct *spiceStruct = accessScope->matchStruct(currentScope, identifier, concreteTemplateTypes, node); if (!spiceStruct) - throw SemanticError(node->codeLoc, REFERENCED_UNDEFINED_STRUCT, "Struct '" + structSignature + "' could not be found"); + throw SemanticError(node, REFERENCED_UNDEFINED_STRUCT, "Struct '" + structSignature + "' could not be found"); spiceStruct->isUsed = true; symbolEntry = accessScope->lookup(structSignature); @@ -1957,7 +1941,7 @@ std::any AnalyzerVisitor::visitFunctionCall(FunctionCallNode *node) { // Import struct if necessary if (accessScope->isImported(currentScope)) - thisType = initExtStruct(accessScope, scopePath.getScopePrefix(true), identifier, concreteTemplateTypes, node->codeLoc); + thisType = initExtStruct(accessScope, scopePath.getScopePrefix(true), identifier, concreteTemplateTypes, node); else thisType = symbolBaseType; @@ -1972,7 +1956,7 @@ std::any AnalyzerVisitor::visitFunctionCall(FunctionCallNode *node) { accessScope = accessScope->lookupTable(tableName); if (!accessScope) - throw SemanticError(node->codeLoc, REFERENCED_UNDEFINED_FUNCTION, "Cannot call a function on '" + identifier + "'"); + throw SemanticError(node, REFERENCED_UNDEFINED_FUNCTION, "Cannot call a function on '" + identifier + "'"); scopePath.pushFragment(identifier, accessScope); } @@ -1999,7 +1983,7 @@ std::any AnalyzerVisitor::visitFunctionCall(FunctionCallNode *node) { // Get the function/procedure instance SymbolType origThisType = thisType.replaceBaseSubType(CommonUtil::getLastFragment(thisType.getBaseType().getSubType(), ".")); - Function *spiceFunc = accessScope->matchFunction(currentScope, functionName, origThisType, argTypes, node->codeLoc); + Function *spiceFunc = accessScope->matchFunction(currentScope, functionName, origThisType, argTypes, node); if (!spiceFunc) { // Build dummy function to get a better error message SymbolSpecifiers specifiers = SymbolSpecifiers(SymbolType(TY_FUNCTION)); @@ -2010,8 +1994,7 @@ std::any AnalyzerVisitor::visitFunctionCall(FunctionCallNode *node) { Function f(functionName, specifiers, thisType, SymbolType(TY_DYN), errArgTypes, {}, node); - throw SemanticError(node->codeLoc, REFERENCED_UNDEFINED_FUNCTION, - "Function/Procedure '" + f.getSignature() + "' could not be found"); + throw SemanticError(node, REFERENCED_UNDEFINED_FUNCTION, "Function/Procedure '" + f.getSignature() + "' could not be found"); } spiceFunc->isUsed = true; @@ -2022,7 +2005,7 @@ std::any AnalyzerVisitor::visitFunctionCall(FunctionCallNode *node) { // Check if the function entry has sufficient visibility if (accessScope->isImported(currentScope) && !functionEntry->specifiers.isPublic()) - throw SemanticError(node->codeLoc, INSUFFICIENT_VISIBILITY, + throw SemanticError(node, INSUFFICIENT_VISIBILITY, "Cannot access function/procedure '" + spiceFunc->getSignature() + "' due to its private visibility"); // Analyze the function if not done yet. This is only necessary if we call a function in the same source file, which was @@ -2054,7 +2037,7 @@ std::any AnalyzerVisitor::visitFunctionCall(FunctionCallNode *node) { if (!scopePathBackup.isEmpty() && scopePathBackup.getCurrentScope()->isImported(currentScope)) { std::string scopePrefix = scopePathBackup.getScopePrefix(!spiceFunc->isGenericSubstantiation); SymbolType symbolType = - initExtStruct(currentScope, scopePrefix, returnType.getSubType(), returnType.getTemplateTypes(), node->codeLoc); + initExtStruct(currentScope, scopePrefix, returnType.getSubType(), returnType.getTemplateTypes(), node); return node->setEvaluatedSymbolType(symbolType); } } @@ -2076,7 +2059,7 @@ std::any AnalyzerVisitor::visitArrayInitialization(ArrayInitializationNode *node if (actualItemType.is(TY_DYN)) { actualItemType = itemType; } else if (itemType != actualItemType) { - throw SemanticError(arg->codeLoc, ARRAY_ITEM_TYPE_NOT_MATCHING, + throw SemanticError(arg, ARRAY_ITEM_TYPE_NOT_MATCHING, "All provided values have to be of the same data type. You provided " + actualItemType.getName(false) + " and " + itemType.getName(false)); } @@ -2093,14 +2076,13 @@ std::any AnalyzerVisitor::visitArrayInitialization(ArrayInitializationNode *node // Check if actual item type is known now if (actualItemType.is(TY_DYN)) { // Not enough info to perform type inference, because of empty array {} if (expectedType.is(TY_DYN)) - throw SemanticError(node->codeLoc, UNEXPECTED_DYN_TYPE_SA, "Not enough information to perform type inference"); + throw SemanticError(node, UNEXPECTED_DYN_TYPE_SA, "Not enough information to perform type inference"); if (!expectedType.isArray()) - throw SemanticError(node->codeLoc, ARRAY_ITEM_TYPE_NOT_MATCHING, - "Cannot initialize array for type " + expectedType.getName() + ""); + throw SemanticError(node, ARRAY_ITEM_TYPE_NOT_MATCHING, "Cannot initialize array for type " + expectedType.getName() + ""); actualItemType = expectedType.getContainedTy(); } - return node->setEvaluatedSymbolType(actualItemType.toArray(node->codeLoc, actualSize)); + return node->setEvaluatedSymbolType(actualItemType.toArray(node, actualSize)); } std::any AnalyzerVisitor::visitStructInstantiation(StructInstantiationNode *node) { @@ -2116,7 +2098,7 @@ std::any AnalyzerVisitor::visitStructInstantiation(StructInstantiationNode *node if (i < node->structNameFragments.size() - 1) { SymbolTableEntry *symbolEntry = accessScope->lookup(structName); if (!symbolEntry) - throw SemanticError(node->codeLoc, REFERENCED_UNDEFINED_STRUCT, + throw SemanticError(node, REFERENCED_UNDEFINED_STRUCT, "Symbol '" + accessScopePrefix + structName + "' was used before defined"); accessScopePrefix += structName + "."; std::string tableName = symbolEntry->type.is(TY_IMPORT) ? structName : STRUCT_SCOPE_PREFIX + structName; @@ -2135,23 +2117,21 @@ std::any AnalyzerVisitor::visitStructInstantiation(StructInstantiationNode *node } // Get the struct instance - Struct *spiceStruct = accessScope->matchStruct(currentScope, structName, concreteTemplateTypes, node->codeLoc); + Struct *spiceStruct = accessScope->matchStruct(currentScope, structName, concreteTemplateTypes, node); if (!spiceStruct) { std::string structSignature = Struct::getSignature(structName, concreteTemplateTypes); - throw SemanticError(node->codeLoc, REFERENCED_UNDEFINED_STRUCT, "Struct '" + structSignature + "' could not be found"); + throw SemanticError(node, REFERENCED_UNDEFINED_STRUCT, "Struct '" + structSignature + "' could not be found"); } spiceStruct->isUsed = true; SymbolType structType; if (structIsImported) { // Imported struct - structType = - initExtStruct(accessScope, accessScopePrefix, node->structNameFragments.back(), concreteTemplateTypes, node->codeLoc); + structType = initExtStruct(accessScope, accessScopePrefix, node->structNameFragments.back(), concreteTemplateTypes, node); } else { // Not imported SymbolTableEntry *structSymbol = currentScope->lookup(accessScopePrefix + Struct::getSignature(structName, concreteTemplateTypes)); if (!structSymbol) - throw SemanticError(node->codeLoc, REFERENCED_UNDEFINED_STRUCT, - "Could not find struct '" + accessScopePrefix + structName + "'"); + throw SemanticError(node, REFERENCED_UNDEFINED_STRUCT, "Could not find struct '" + accessScopePrefix + structName + "'"); structType = structSymbol->type; } @@ -2167,7 +2147,7 @@ std::any AnalyzerVisitor::visitStructInstantiation(StructInstantiationNode *node std::vector fieldTypes; if (node->fieldLst()) { // Check if any fields are passed. Empty braces are also allowed if (spiceStruct->getFieldTypes().size() != node->fieldLst()->args().size()) - throw SemanticError(node->fieldLst()->codeLoc, NUMBER_OF_FIELDS_NOT_MATCHING, + throw SemanticError(node->fieldLst(), NUMBER_OF_FIELDS_NOT_MATCHING, "You've passed too less/many field values. Pass either none or all of them"); // Check if the field types are matching @@ -2185,7 +2165,7 @@ std::any AnalyzerVisitor::visitStructInstantiation(StructInstantiationNode *node expectedSymbolType.replaceBaseSubType(accessScopePrefix + expectedSymbolType.getBaseType().getSubType()); // Check if type matches declaration if (actualType != expectedSymbolType) - throw SemanticError(assignExpr->codeLoc, FIELD_TYPE_NOT_MATCHING, + throw SemanticError(assignExpr, FIELD_TYPE_NOT_MATCHING, "Expected type " + expectedSymbolType.getName(false) + " for the field '" + expectedField->name + "', but got " + actualType.getName(false)); } @@ -2207,25 +2187,25 @@ std::any AnalyzerVisitor::visitDataType(DataTypeNode *node) { DataTypeNode::TypeModifier typeModifier = tmQueue.front(); switch (typeModifier.modifierType) { case DataTypeNode::TYPE_PTR: { - type = type.toPointer(node->codeLoc); + type = type.toPointer(node); break; } case DataTypeNode::TYPE_ARRAY: { if (typeModifier.hasSize) { if (typeModifier.isSizeHardcoded) { if (typeModifier.hardcodedSize <= 1) - throw SemanticError(node->codeLoc, ARRAY_SIZE_INVALID, "The size of an array must be > 1 and explicitly stated"); + throw SemanticError(node, ARRAY_SIZE_INVALID, "The size of an array must be > 1 and explicitly stated"); } else { // Do not allow dynamic sized types in parameter lists if (node->isParamType()) - throw SemanticError(node->codeLoc, ARRAY_SIZE_INVALID, "Types in parameter lists may not be dynamically sized"); + throw SemanticError(node, ARRAY_SIZE_INVALID, "Types in parameter lists may not be dynamically sized"); auto sizeType = any_cast(visit(arraySizeExpr[assignExprCounter++])); if (!sizeType.isOneOf({TY_INT, TY_LONG, TY_SHORT})) - throw SemanticError(node->codeLoc, ARRAY_SIZE_INVALID, "The array size must be of type int, long or short"); + throw SemanticError(node, ARRAY_SIZE_INVALID, "The array size must be of type int, long or short"); } } - type = type.toArray(node->codeLoc, typeModifier.hardcodedSize); + type = type.toArray(node, typeModifier.hardcodedSize); break; } default: @@ -2284,9 +2264,9 @@ std::any AnalyzerVisitor::visitCustomDataType(CustomDataTypeNode *node) { accessScopePrefix += identifier + "."; entry = accessScope->lookup(identifier); if (!entry) - throw SemanticError(node->codeLoc, UNKNOWN_DATATYPE, "Unknown symbol '" + identifier + "'"); + throw SemanticError(node, UNKNOWN_DATATYPE, "Unknown symbol '" + identifier + "'"); if (!entry->type.isOneOf({TY_STRUCT, TY_ENUM, TY_IMPORT})) - throw SemanticError(node->codeLoc, EXPECTED_TYPE, "Expected type, but got " + entry->type.getName()); + throw SemanticError(node, EXPECTED_TYPE, "Expected type, but got " + entry->type.getName()); std::string tableName = identifier; if (entry->type.is(TY_STRUCT)) { @@ -2312,19 +2292,19 @@ std::any AnalyzerVisitor::visitCustomDataType(CustomDataTypeNode *node) { } // Set the struct instance to used - Struct *spiceStruct = accessScope->matchStruct(nullptr, identifier, concreteTemplateTypes, node->codeLoc); + Struct *spiceStruct = accessScope->matchStruct(nullptr, identifier, concreteTemplateTypes, node); if (spiceStruct) spiceStruct->isUsed = true; if (structIsImported) { // Imported struct - SymbolType symbolType = initExtStruct(accessScope, accessScopePrefix, identifier, concreteTemplateTypes, node->codeLoc); + SymbolType symbolType = initExtStruct(accessScope, accessScopePrefix, identifier, concreteTemplateTypes, node); return node->setEvaluatedSymbolType(symbolType); } // Check if struct was declared SymbolTableEntry *structSymbol = accessScope->lookup(identifier); if (!structSymbol) - throw SemanticError(node->codeLoc, UNKNOWN_DATATYPE, "Unknown datatype '" + identifier + "'"); + throw SemanticError(node, UNKNOWN_DATATYPE, "Unknown datatype '" + identifier + "'"); structSymbol->isUsed = true; return node->setEvaluatedSymbolType(SymbolType(TY_STRUCT, identifier, {.arraySize = 0}, concreteTemplateTypes)); @@ -2341,7 +2321,7 @@ SymbolType AnalyzerVisitor::insertAnonStringStructSymbol(const AstNode *declNode return stringStructType; } -void AnalyzerVisitor::insertDestructorCall(const CodeLoc &codeLoc, SymbolTableEntry *varEntry) { +void AnalyzerVisitor::insertDestructorCall(const AstNode *node, SymbolTableEntry *varEntry) { assert(varEntry != nullptr); SymbolType varEntryType = varEntry->type; if (varEntryType.isStringStruct()) @@ -2355,14 +2335,14 @@ void AnalyzerVisitor::insertDestructorCall(const CodeLoc &codeLoc, SymbolTableEn accessScope = accessScope->getChild(STRUCT_SCOPE_PREFIX + structEntry->name); assert(accessScope != nullptr); SymbolType thisType = varEntry->type; - Function *spiceFunc = accessScope->matchFunction(currentScope, DTOR_VARIABLE_NAME, thisType, {}, codeLoc); + Function *spiceFunc = accessScope->matchFunction(currentScope, DTOR_VARIABLE_NAME, thisType, {}, node); if (spiceFunc) spiceFunc->isUsed = true; } SymbolType AnalyzerVisitor::initExtStruct(SymbolTable *sourceScope, const std::string &structScopePrefix, const std::string &structName, const std::vector &templateTypes, - const CodeLoc &codeLoc) { + const AstNode *node) { // Get external struct name std::string newStructName = structScopePrefix + structName; @@ -2380,7 +2360,7 @@ SymbolType AnalyzerVisitor::initExtStruct(SymbolTable *sourceScope, const std::s std::string structSignature = Struct::getSignature(structName, templateTypes); SymbolTableEntry *externalStructSymbol = sourceScope->lookup(structSignature); if (!externalStructSymbol) - throw SemanticError(codeLoc, REFERENCED_UNDEFINED_STRUCT, "Could not find struct '" + newStructName + "'"); + throw SemanticError(node, REFERENCED_UNDEFINED_STRUCT, "Could not find struct '" + newStructName + "'"); // Get the associated symbolTable of the external struct symbol SymbolTable *externalStructTable = sourceScope->lookupTable(STRUCT_SCOPE_PREFIX + structSignature); @@ -2391,7 +2371,7 @@ SymbolType AnalyzerVisitor::initExtStruct(SymbolTable *sourceScope, const std::s std::string nestedStructName = CommonUtil::getLastFragment(entry.type.getBaseType().getSubType(), "."); std::string nestedStructPrefix = CommonUtil::getPrefix(entry.type.getBaseType().getSubType(), "."); // Initialize nested struct - initExtStruct(sourceScope, nestedStructPrefix, nestedStructName, entry.type.getBaseType().getTemplateTypes(), codeLoc); + initExtStruct(sourceScope, nestedStructPrefix, nestedStructName, entry.type.getBaseType().getTemplateTypes(), node); } } @@ -2401,7 +2381,7 @@ SymbolType AnalyzerVisitor::initExtStruct(SymbolTable *sourceScope, const std::s externalStructSymbol->isUsed = true; // Set the struct instance to used - Struct *externalSpiceStruct = sourceScope->matchStruct(nullptr, structName, templateTypes, codeLoc); + Struct *externalSpiceStruct = sourceScope->matchStruct(nullptr, structName, templateTypes, node); assert(externalSpiceStruct); externalSpiceStruct->isUsed = true; @@ -2413,7 +2393,7 @@ SymbolType AnalyzerVisitor::initExtStruct(SymbolTable *sourceScope, const std::s } SymbolType AnalyzerVisitor::initExtGlobal(SymbolTable *sourceScope, const std::string &globalScopePrefix, - const std::string &globalName, const CodeLoc &codeLoc) { + const std::string &globalName, const AstNode *node) { // Get external global var name std::string newGlobalName = globalScopePrefix + globalName; @@ -2425,7 +2405,7 @@ SymbolType AnalyzerVisitor::initExtGlobal(SymbolTable *sourceScope, const std::s // Check if external global var is declared SymbolTableEntry *externalGlobalSymbol = sourceScope->lookup(globalName); if (!externalGlobalSymbol) - throw SemanticError(codeLoc, REFERENCED_UNDEFINED_VARIABLE, "Could not find global variable '" + newGlobalName + "'"); + throw SemanticError(node, REFERENCED_UNDEFINED_VARIABLE, "Could not find global variable '" + newGlobalName + "'"); // Set to DECLARED, so that the generator can set it to DEFINED as soon as the LLVM struct type was generated once Capture newGlobalCapture = Capture(externalGlobalSymbol, newGlobalName, DECLARED); diff --git a/src/analyzer/AnalyzerVisitor.h b/src/analyzer/AnalyzerVisitor.h index 8963b4f5b..7163e32cf 100644 --- a/src/analyzer/AnalyzerVisitor.h +++ b/src/analyzer/AnalyzerVisitor.h @@ -131,9 +131,9 @@ class AnalyzerVisitor : public AstVisitor { // Private methods SymbolType insertAnonStringStructSymbol(const AstNode *declNode); - void insertDestructorCall(const CodeLoc &codeLoc, SymbolTableEntry *varEntry); + void insertDestructorCall(const AstNode *node, SymbolTableEntry *varEntry); SymbolType initExtStruct(SymbolTable *sourceScope, const std::string &structScopePrefix, const std::string &structName, - const std::vector &templateTypes, const CodeLoc &codeLoc); + const std::vector &templateTypes, const AstNode *node); SymbolType initExtGlobal(SymbolTable *sourceScope, const std::string &globalScopePrefix, const std::string &globalName, - const CodeLoc &codeLoc); + const AstNode *node); }; \ No newline at end of file diff --git a/src/analyzer/OpRuleManager.cpp b/src/analyzer/OpRuleManager.cpp index 4031aaec1..c921c3905 100644 --- a/src/analyzer/OpRuleManager.cpp +++ b/src/analyzer/OpRuleManager.cpp @@ -5,7 +5,7 @@ #include #include -SymbolType OpRuleManager::getAssignResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs) { +SymbolType OpRuleManager::getAssignResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { // Skip type compatibility check if the lhs is of type dyn -> perform type inference if (lhs.is(TY_DYN)) return rhs; @@ -22,101 +22,101 @@ SymbolType OpRuleManager::getAssignResultType(const CodeLoc &codeLoc, const Symb if (lhs.is(TY_STRING) && rhs.is(TY_STRING)) return rhs; // Check primitive type combinations - return validateBinaryOperation(codeLoc, ASSIGN_OP_RULES, "=", lhs, rhs); + return validateBinaryOperation(node, ASSIGN_OP_RULES, "=", lhs, rhs); } -SymbolType OpRuleManager::getPlusEqualResultType(const AstNode *declNode, const SymbolType &lhs, const SymbolType &rhs) { +SymbolType OpRuleManager::getPlusEqualResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { if (lhs.isPointer() && rhs.isOneOf({TY_INT, TY_LONG, TY_SHORT})) { if (analyzer->allowUnsafeOperations) return lhs; else - throw printErrorMessageUnsafe(declNode->codeLoc, "+=", lhs, rhs); + throw printErrorMessageUnsafe(node, "+=", lhs, rhs); } // Allow string += char if (lhs.is(TY_STRING) && rhs.is(TY_CHAR)) - return analyzer->insertAnonStringStructSymbol(declNode); + return analyzer->insertAnonStringStructSymbol(node); // Allow string += string if (lhs.is(TY_STRING) && rhs.is(TY_STRING)) - return analyzer->insertAnonStringStructSymbol(declNode); + return analyzer->insertAnonStringStructSymbol(node); - return validateBinaryOperation(declNode->codeLoc, PLUS_EQUAL_OP_RULES, "+=", lhs, rhs); + return validateBinaryOperation(node, PLUS_EQUAL_OP_RULES, "+=", lhs, rhs); } -SymbolType OpRuleManager::getMinusEqualResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs) { +SymbolType OpRuleManager::getMinusEqualResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { if (lhs.isPointer() && rhs.isOneOf({TY_INT, TY_LONG, TY_SHORT})) { if (analyzer->allowUnsafeOperations) return lhs; else - throw printErrorMessageUnsafe(codeLoc, "-=", lhs, rhs); + throw printErrorMessageUnsafe(node, "-=", lhs, rhs); } - return validateBinaryOperation(codeLoc, MINUS_EQUAL_OP_RULES, "-=", lhs, rhs); + return validateBinaryOperation(node, MINUS_EQUAL_OP_RULES, "-=", lhs, rhs); } -SymbolType OpRuleManager::getMulEqualResultType(const AstNode *declNode, const SymbolType &lhs, const SymbolType &rhs) { +SymbolType OpRuleManager::getMulEqualResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { // Allow string *= int if (lhs.is(TY_STRING) && rhs.is(TY_INT)) - return analyzer->insertAnonStringStructSymbol(declNode); + return analyzer->insertAnonStringStructSymbol(node); // Allow string *= long if (lhs.is(TY_STRING) && rhs.is(TY_LONG)) - return analyzer->insertAnonStringStructSymbol(declNode); + return analyzer->insertAnonStringStructSymbol(node); // Allow string *= short if (lhs.is(TY_STRING) && rhs.is(TY_SHORT)) - return analyzer->insertAnonStringStructSymbol(declNode); + return analyzer->insertAnonStringStructSymbol(node); - return validateBinaryOperation(declNode->codeLoc, MUL_EQUAL_OP_RULES, "*=", lhs, rhs); + return validateBinaryOperation(node, MUL_EQUAL_OP_RULES, "*=", lhs, rhs); } -SymbolType OpRuleManager::getDivEqualResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs) { - return validateBinaryOperation(codeLoc, DIV_EQUAL_OP_RULES, "/=", lhs, rhs); +SymbolType OpRuleManager::getDivEqualResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { + return validateBinaryOperation(node, DIV_EQUAL_OP_RULES, "/=", lhs, rhs); } -SymbolType OpRuleManager::getRemEqualResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs) { - return validateBinaryOperation(codeLoc, REM_EQUAL_OP_RULES, "%=", lhs, rhs); +SymbolType OpRuleManager::getRemEqualResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { + return validateBinaryOperation(node, REM_EQUAL_OP_RULES, "%=", lhs, rhs); } -SymbolType OpRuleManager::getSHLEqualResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs) { - return validateBinaryOperation(codeLoc, SHL_EQUAL_OP_RULES, "<<=", lhs, rhs); +SymbolType OpRuleManager::getSHLEqualResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { + return validateBinaryOperation(node, SHL_EQUAL_OP_RULES, "<<=", lhs, rhs); } -SymbolType OpRuleManager::getSHREqualResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs) { - return validateBinaryOperation(codeLoc, SHR_EQUAL_OP_RULES, ">>=", lhs, rhs); +SymbolType OpRuleManager::getSHREqualResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { + return validateBinaryOperation(node, SHR_EQUAL_OP_RULES, ">>=", lhs, rhs); } -SymbolType OpRuleManager::getAndEqualResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs) { - return validateBinaryOperation(codeLoc, AND_EQUAL_OP_RULES, "&=", lhs, rhs); +SymbolType OpRuleManager::getAndEqualResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { + return validateBinaryOperation(node, AND_EQUAL_OP_RULES, "&=", lhs, rhs); } -SymbolType OpRuleManager::getOrEqualResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs) { - return validateBinaryOperation(codeLoc, OR_EQUAL_OP_RULES, "|=", lhs, rhs); +SymbolType OpRuleManager::getOrEqualResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { + return validateBinaryOperation(node, OR_EQUAL_OP_RULES, "|=", lhs, rhs); } -SymbolType OpRuleManager::getXorEqualResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs) { - return validateBinaryOperation(codeLoc, XOR_EQUAL_OP_RULES, "^=", lhs, rhs); +SymbolType OpRuleManager::getXorEqualResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { + return validateBinaryOperation(node, XOR_EQUAL_OP_RULES, "^=", lhs, rhs); } -SymbolType OpRuleManager::getLogicalAndResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs) { - return validateBinaryOperation(codeLoc, LOGICAL_AND_OP_RULES, "&&", lhs, rhs); +SymbolType OpRuleManager::getLogicalAndResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { + return validateBinaryOperation(node, LOGICAL_AND_OP_RULES, "&&", lhs, rhs); } -SymbolType OpRuleManager::getLogicalOrResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs) { - return validateBinaryOperation(codeLoc, LOGICAL_OR_OP_RULES, "||", lhs, rhs); +SymbolType OpRuleManager::getLogicalOrResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { + return validateBinaryOperation(node, LOGICAL_OR_OP_RULES, "||", lhs, rhs); } -SymbolType OpRuleManager::getBitwiseAndResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs) { - return validateBinaryOperation(codeLoc, BITWISE_AND_OP_RULES, "&", lhs, rhs); +SymbolType OpRuleManager::getBitwiseAndResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { + return validateBinaryOperation(node, BITWISE_AND_OP_RULES, "&", lhs, rhs); } -SymbolType OpRuleManager::getBitwiseOrResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs) { - return validateBinaryOperation(codeLoc, BITWISE_OR_OP_RULES, "|", lhs, rhs); +SymbolType OpRuleManager::getBitwiseOrResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { + return validateBinaryOperation(node, BITWISE_OR_OP_RULES, "|", lhs, rhs); } -SymbolType OpRuleManager::getBitwiseXorResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs) { - return validateBinaryOperation(codeLoc, BITWISE_XOR_OP_RULES, "^", lhs, rhs); +SymbolType OpRuleManager::getBitwiseXorResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { + return validateBinaryOperation(node, BITWISE_XOR_OP_RULES, "^", lhs, rhs); } -SymbolType OpRuleManager::getEqualResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs) { +SymbolType OpRuleManager::getEqualResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { // Allow 'pointer == pointer' straight away if (lhs.isPointer() && rhs.isPointer()) return SymbolType(TY_BOOL); @@ -124,10 +124,10 @@ SymbolType OpRuleManager::getEqualResultType(const CodeLoc &codeLoc, const Symbo if (lhs.isPointer() && rhs.is(TY_INT)) return SymbolType(TY_BOOL); // Check primitive type combinations - return validateBinaryOperation(codeLoc, EQUAL_OP_RULES, "==", lhs, rhs); + return validateBinaryOperation(node, EQUAL_OP_RULES, "==", lhs, rhs); } -SymbolType OpRuleManager::getNotEqualResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs) { +SymbolType OpRuleManager::getNotEqualResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { // Allow 'pointer != pointer' straight away if (lhs.isPointer() && rhs.isPointer()) return SymbolType(TY_BOOL); @@ -135,80 +135,80 @@ SymbolType OpRuleManager::getNotEqualResultType(const CodeLoc &codeLoc, const Sy if (lhs.isPointer() && rhs.is(TY_INT)) return SymbolType(TY_BOOL); // Check primitive type combinations - return validateBinaryOperation(codeLoc, NOT_EQUAL_OP_RULES, "!=", lhs, rhs); + return validateBinaryOperation(node, NOT_EQUAL_OP_RULES, "!=", lhs, rhs); } -SymbolType OpRuleManager::getLessResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs) { - return validateBinaryOperation(codeLoc, LESS_OP_RULES, "<", lhs, rhs); +SymbolType OpRuleManager::getLessResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { + return validateBinaryOperation(node, LESS_OP_RULES, "<", lhs, rhs); } -SymbolType OpRuleManager::getGreaterResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs) { - return validateBinaryOperation(codeLoc, GREATER_OP_RULES, ">", lhs, rhs); +SymbolType OpRuleManager::getGreaterResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { + return validateBinaryOperation(node, GREATER_OP_RULES, ">", lhs, rhs); } -SymbolType OpRuleManager::getLessEqualResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs) { - return validateBinaryOperation(codeLoc, LESS_EQUAL_OP_RULES, "<=", lhs, rhs); +SymbolType OpRuleManager::getLessEqualResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { + return validateBinaryOperation(node, LESS_EQUAL_OP_RULES, "<=", lhs, rhs); } -SymbolType OpRuleManager::getGreaterEqualResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs) { - return validateBinaryOperation(codeLoc, GREATER_EQUAL_OP_RULES, ">=", lhs, rhs); +SymbolType OpRuleManager::getGreaterEqualResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { + return validateBinaryOperation(node, GREATER_EQUAL_OP_RULES, ">=", lhs, rhs); } -SymbolType OpRuleManager::getShiftLeftResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs) { - return validateBinaryOperation(codeLoc, SHIFT_LEFT_OP_RULES, "<<", lhs, rhs); +SymbolType OpRuleManager::getShiftLeftResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { + return validateBinaryOperation(node, SHIFT_LEFT_OP_RULES, "<<", lhs, rhs); } -SymbolType OpRuleManager::getShiftRightResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs) { - return validateBinaryOperation(codeLoc, SHIFT_RIGHT_OP_RULES, ">>", lhs, rhs); +SymbolType OpRuleManager::getShiftRightResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { + return validateBinaryOperation(node, SHIFT_RIGHT_OP_RULES, ">>", lhs, rhs); } -SymbolType OpRuleManager::getPlusResultType(const AstNode *declNode, const SymbolType &lhs, const SymbolType &rhs) { +SymbolType OpRuleManager::getPlusResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { // Allow any* + if (lhs.isPointer() && rhs.isOneOf({TY_INT, TY_LONG, TY_SHORT})) { if (analyzer->allowUnsafeOperations) return lhs; else - throw printErrorMessageUnsafe(declNode->codeLoc, "+", lhs, rhs); + throw printErrorMessageUnsafe(node, "+", lhs, rhs); } // Allow + any* if (lhs.isOneOf({TY_INT, TY_LONG, TY_SHORT}) && rhs.isPointer()) { if (analyzer->allowUnsafeOperations) return rhs; else - throw printErrorMessageUnsafe(declNode->codeLoc, "+", lhs, rhs); + throw printErrorMessageUnsafe(node, "+", lhs, rhs); } // Allow string + string if (lhs.is(TY_STRING) && rhs.is(TY_STRING)) - return analyzer->insertAnonStringStructSymbol(declNode); + return analyzer->insertAnonStringStructSymbol(node); - return validateBinaryOperation(declNode->codeLoc, PLUS_OP_RULES, "+", lhs, rhs); + return validateBinaryOperation(node, PLUS_OP_RULES, "+", lhs, rhs); } -SymbolType OpRuleManager::getMinusResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs) { +SymbolType OpRuleManager::getMinusResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { // Allow any* - if (lhs.isPointer() && rhs.isOneOf({TY_INT, TY_LONG, TY_SHORT})) { if (analyzer->allowUnsafeOperations) return lhs; else - throw printErrorMessageUnsafe(codeLoc, "-", lhs, rhs); + throw printErrorMessageUnsafe(node, "-", lhs, rhs); } // Allow - any* if (lhs.isOneOf({TY_INT, TY_LONG, TY_SHORT}) && rhs.isPointer()) { if (analyzer->allowUnsafeOperations) return rhs; else - throw printErrorMessageUnsafe(codeLoc, "-", lhs, rhs); + throw printErrorMessageUnsafe(node, "-", lhs, rhs); } - return validateBinaryOperation(codeLoc, MINUS_OP_RULES, "-", lhs, rhs); + return validateBinaryOperation(node, MINUS_OP_RULES, "-", lhs, rhs); } -SymbolType OpRuleManager::getMulResultType(const AstNode *declNode, const SymbolType &lhs, const SymbolType &rhs) { +SymbolType OpRuleManager::getMulResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { // Allow * if (lhs.isOneOf({TY_STRING, TY_CHAR}) && rhs.isOneOf({TY_INT, TY_SHORT, TY_LONG})) { if (!lhs.isStringStruct()) { // If lhs is a raw string -> insert anon symbol - return analyzer->insertAnonStringStructSymbol(declNode); + return analyzer->insertAnonStringStructSymbol(node); } else { // Otherwise just return the type return SymbolType(TY_STRING, "", {.isStringStruct = true}, {}); } @@ -217,62 +217,62 @@ SymbolType OpRuleManager::getMulResultType(const AstNode *declNode, const Symbol // Allow * if (lhs.isOneOf({TY_INT, TY_SHORT, TY_LONG}) && rhs.isOneOf({TY_STRING, TY_CHAR})) { if (!rhs.isStringStruct()) { // If rhs is a raw string -> insert anon symbol - return analyzer->insertAnonStringStructSymbol(declNode); + return analyzer->insertAnonStringStructSymbol(node); } else { // Otherwise just return the type return SymbolType(TY_STRING, "", {.isStringStruct = true}, {}); } } - return validateBinaryOperation(declNode->codeLoc, MUL_OP_RULES, "*", lhs, rhs); + return validateBinaryOperation(node, MUL_OP_RULES, "*", lhs, rhs); } -SymbolType OpRuleManager::getDivResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs) { - return validateBinaryOperation(codeLoc, DIV_OP_RULES, "/", lhs, rhs); +SymbolType OpRuleManager::getDivResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { + return validateBinaryOperation(node, DIV_OP_RULES, "/", lhs, rhs); } -SymbolType OpRuleManager::getRemResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs) { - return validateBinaryOperation(codeLoc, REM_OP_RULES, "%", lhs, rhs); +SymbolType OpRuleManager::getRemResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { + return validateBinaryOperation(node, REM_OP_RULES, "%", lhs, rhs); } -SymbolType OpRuleManager::getPrefixMinusResultType(const CodeLoc &codeLoc, const SymbolType &lhs) { - return validateUnaryOperation(codeLoc, PREFIX_MINUS_OP_RULES, "-", lhs); +SymbolType OpRuleManager::getPrefixMinusResultType(const AstNode *node, const SymbolType &lhs) { + return validateUnaryOperation(node, PREFIX_MINUS_OP_RULES, "-", lhs); } -SymbolType OpRuleManager::getPrefixPlusPlusResultType(const CodeLoc &codeLoc, const SymbolType &lhs) { - return validateUnaryOperation(codeLoc, PREFIX_PLUS_PLUS_OP_RULES, "++", lhs); +SymbolType OpRuleManager::getPrefixPlusPlusResultType(const AstNode *node, const SymbolType &lhs) { + return validateUnaryOperation(node, PREFIX_PLUS_PLUS_OP_RULES, "++", lhs); } -SymbolType OpRuleManager::getPrefixMinusMinusResultType(const CodeLoc &codeLoc, const SymbolType &lhs) { - return validateUnaryOperation(codeLoc, PREFIX_MINUS_MINUS_OP_RULES, "--", lhs); +SymbolType OpRuleManager::getPrefixMinusMinusResultType(const AstNode *node, const SymbolType &lhs) { + return validateUnaryOperation(node, PREFIX_MINUS_MINUS_OP_RULES, "--", lhs); } -SymbolType OpRuleManager::getPrefixNotResultType(const CodeLoc &codeLoc, const SymbolType &lhs) { - return validateUnaryOperation(codeLoc, PREFIX_NOT_OP_RULES, "!", lhs); +SymbolType OpRuleManager::getPrefixNotResultType(const AstNode *node, const SymbolType &lhs) { + return validateUnaryOperation(node, PREFIX_NOT_OP_RULES, "!", lhs); } -SymbolType OpRuleManager::getPrefixBitwiseNotResultType(const CodeLoc &codeLoc, const SymbolType &lhs) { - return validateUnaryOperation(codeLoc, PREFIX_BITWISE_NOT_OP_RULES, "~", lhs); +SymbolType OpRuleManager::getPrefixBitwiseNotResultType(const AstNode *node, const SymbolType &lhs) { + return validateUnaryOperation(node, PREFIX_BITWISE_NOT_OP_RULES, "~", lhs); } -SymbolType OpRuleManager::getPrefixMulResultType(const CodeLoc &codeLoc, const SymbolType &lhs) { +SymbolType OpRuleManager::getPrefixMulResultType(const AstNode *node, const SymbolType &lhs) { if (!lhs.isPointer()) - throw SemanticError(codeLoc, OPERATOR_WRONG_DATA_TYPE, "Cannot apply de-referencing operator on type " + lhs.getName(true)); + throw SemanticError(node, OPERATOR_WRONG_DATA_TYPE, "Cannot apply de-referencing operator on type " + lhs.getName(true)); return lhs.getContainedTy(); } -SymbolType OpRuleManager::getPrefixBitwiseAndResultType(const CodeLoc &codeLoc, const SymbolType &lhs) { - return lhs.toPointer(codeLoc); +SymbolType OpRuleManager::getPrefixBitwiseAndResultType(const AstNode *node, const SymbolType &lhs) { + return lhs.toPointer(node); } -SymbolType OpRuleManager::getPostfixPlusPlusResultType(const CodeLoc &codeLoc, const SymbolType &lhs) { - return validateUnaryOperation(codeLoc, POSTFIX_PLUS_PLUS_OP_RULES, "++", lhs); +SymbolType OpRuleManager::getPostfixPlusPlusResultType(const AstNode *node, const SymbolType &lhs) { + return validateUnaryOperation(node, POSTFIX_PLUS_PLUS_OP_RULES, "++", lhs); } -SymbolType OpRuleManager::getPostfixMinusMinusResultType(const CodeLoc &codeLoc, const SymbolType &lhs) { - return validateUnaryOperation(codeLoc, POSTFIX_MINUS_MINUS_OP_RULES, "--", lhs); +SymbolType OpRuleManager::getPostfixMinusMinusResultType(const AstNode *node, const SymbolType &lhs) { + return validateUnaryOperation(node, POSTFIX_MINUS_MINUS_OP_RULES, "--", lhs); } -SymbolType OpRuleManager::getCastResultType(const CodeLoc &codeLoc, const SymbolType &lhs, +SymbolType OpRuleManager::getCastResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs) { // double dbl = (double) 10; // Allow casts string -> char* and string -> char[] if (lhs.isOneOf({TY_PTR, TY_ARRAY}) && lhs.getContainedTy().is(TY_CHAR) && rhs.is(TY_STRING)) @@ -285,47 +285,43 @@ SymbolType OpRuleManager::getCastResultType(const CodeLoc &codeLoc, const Symbol if (analyzer->allowUnsafeOperations) return lhs; else - throw printErrorMessageUnsafe(codeLoc, "(cast)", lhs, rhs); + throw printErrorMessageUnsafe(node, "(cast)", lhs, rhs); } // Check primitive type combinations - return validateBinaryOperation(codeLoc, CAST_OP_RULES, "(cast)", lhs, rhs); + return validateBinaryOperation(node, CAST_OP_RULES, "(cast)", lhs, rhs); } -SymbolType OpRuleManager::validateBinaryOperation(const CodeLoc &codeLoc, const std::vector &opRules, - const std::string &opName, const SymbolType &lhs, const SymbolType &rhs) { +SymbolType OpRuleManager::validateBinaryOperation(const AstNode *node, const std::vector &opRules, + const std::string &name, const SymbolType &lhs, const SymbolType &rhs) { for (const auto &rule : opRules) { if (std::get<0>(rule) == lhs && std::get<1>(rule) == rhs) return std::get<2>(rule); } - throw printErrorMessageBinary(codeLoc, opName, lhs, rhs); + throw printErrorMessageBinary(node, name, lhs, rhs); } -SymbolType OpRuleManager::validateUnaryOperation(const CodeLoc &codeLoc, const std::vector &opRules, - const std::string &opName, const SymbolType &lhs) { +SymbolType OpRuleManager::validateUnaryOperation(const AstNode *node, const std::vector &opRules, + const std::string &name, const SymbolType &lhs) { for (const auto &rule : opRules) { if (std::get<0>(rule) == lhs) return std::get<1>(rule); } - throw printErrorMessageUnary(codeLoc, opName, lhs); + throw printErrorMessageUnary(node, name, lhs); } -SemanticError OpRuleManager::printErrorMessageBinary(const CodeLoc &codeLoc, const std::string &operatorName, - const SymbolType &lhs, const SymbolType &rhs) { - return SemanticError(codeLoc, OPERATOR_WRONG_DATA_TYPE, - "Cannot apply '" + operatorName + "' operator on types " + lhs.getName(true) + " and " + - rhs.getName(true)); +SemanticError OpRuleManager::printErrorMessageBinary(const AstNode *node, const std::string &name, const SymbolType &lhs, + const SymbolType &rhs) { + return SemanticError(node, OPERATOR_WRONG_DATA_TYPE, + "Cannot apply '" + name + "' operator on types " + lhs.getName(true) + " and " + rhs.getName(true)); } -SemanticError OpRuleManager::printErrorMessageUnary(const CodeLoc &codeLoc, const std::string &operatorName, - const SymbolType &lhs) { - return SemanticError(codeLoc, OPERATOR_WRONG_DATA_TYPE, - "Cannot apply '" + operatorName + "' operator on type " + lhs.getName(true)); +SemanticError OpRuleManager::printErrorMessageUnary(const AstNode *node, const std::string &name, const SymbolType &lhs) { + return SemanticError(node, OPERATOR_WRONG_DATA_TYPE, "Cannot apply '" + name + "' operator on type " + lhs.getName(true)); } -SemanticError OpRuleManager::printErrorMessageUnsafe(const CodeLoc &codeLoc, const std::string &operatorName, - const SymbolType &lhs, const SymbolType &rhs) { - return SemanticError(codeLoc, UNSAFE_OPERATION_IN_SAFE_CONTEXT, - "Cannot apply '" + operatorName + "' operator on types " + lhs.getName(true) + " and " + - rhs.getName(true) + +SemanticError OpRuleManager::printErrorMessageUnsafe(const AstNode *node, const std::string &name, const SymbolType &lhs, + const SymbolType &rhs) { + return SemanticError(node, UNSAFE_OPERATION_IN_SAFE_CONTEXT, + "Cannot apply '" + name + "' operator on types " + lhs.getName(true) + " and " + rhs.getName(true) + " as this is an unsafe operation. Please use unsafe blocks if you know what you are doing."); } \ No newline at end of file diff --git a/src/analyzer/OpRuleManager.h b/src/analyzer/OpRuleManager.h index 30ead1f67..9edadd812 100644 --- a/src/analyzer/OpRuleManager.h +++ b/src/analyzer/OpRuleManager.h @@ -572,58 +572,58 @@ class OpRuleManager { explicit OpRuleManager(AnalyzerVisitor *analyzer) : analyzer(analyzer) {} // Public methods - SymbolType getAssignResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getPlusEqualResultType(const AstNode *declNode, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getMinusEqualResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getMulEqualResultType(const AstNode *declNode, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getDivEqualResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getRemEqualResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getSHLEqualResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getSHREqualResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getAndEqualResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getOrEqualResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getXorEqualResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getLogicalAndResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getLogicalOrResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getBitwiseAndResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getBitwiseOrResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getBitwiseXorResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getEqualResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getNotEqualResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getLessResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getGreaterResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getLessEqualResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getGreaterEqualResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getShiftLeftResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getShiftRightResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getPlusResultType(const AstNode *declNode, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getMinusResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getMulResultType(const AstNode *declNode, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getDivResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getRemResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &rhs); - SymbolType getPrefixMinusResultType(const CodeLoc &codeLoc, const SymbolType &lhs); - SymbolType getPrefixPlusPlusResultType(const CodeLoc &codeLoc, const SymbolType &lhs); - SymbolType getPrefixMinusMinusResultType(const CodeLoc &codeLoc, const SymbolType &lhs); - SymbolType getPrefixNotResultType(const CodeLoc &codeLoc, const SymbolType &lhs); - SymbolType getPrefixBitwiseNotResultType(const CodeLoc &codeLoc, const SymbolType &lhs); - SymbolType getPrefixMulResultType(const CodeLoc &codeLoc, const SymbolType &lhs); - SymbolType getPrefixBitwiseAndResultType(const CodeLoc &codeLoc, const SymbolType &lhs); - SymbolType getPostfixPlusPlusResultType(const CodeLoc &codeLoc, const SymbolType &lhs); - SymbolType getPostfixMinusMinusResultType(const CodeLoc &codeLoc, const SymbolType &lhs); - SymbolType getCastResultType(const CodeLoc &codeLoc, const SymbolType &lhs, const SymbolType &); + static SymbolType getAssignResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs); + SymbolType getPlusEqualResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs); + SymbolType getMinusEqualResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs); + SymbolType getMulEqualResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs); + static SymbolType getDivEqualResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &hs); + static SymbolType getRemEqualResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs); + static SymbolType getSHLEqualResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs); + static SymbolType getSHREqualResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs); + static SymbolType getAndEqualResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs); + static SymbolType getOrEqualResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs); + static SymbolType getXorEqualResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs); + static SymbolType getLogicalAndResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs); + static SymbolType getLogicalOrResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs); + static SymbolType getBitwiseAndResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs); + static SymbolType getBitwiseOrResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs); + static SymbolType getBitwiseXorResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs); + static SymbolType getEqualResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs); + static SymbolType getNotEqualResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs); + static SymbolType getLessResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs); + static SymbolType getGreaterResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs); + static SymbolType getLessEqualResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs); + static SymbolType getGreaterEqualResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs); + static SymbolType getShiftLeftResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs); + static SymbolType getShiftRightResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs); + SymbolType getPlusResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs); + SymbolType getMinusResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs); + SymbolType getMulResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs); + static SymbolType getDivResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs); + static SymbolType getRemResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &rhs); + static SymbolType getPrefixMinusResultType(const AstNode *node, const SymbolType &lhs); + static SymbolType getPrefixPlusPlusResultType(const AstNode *node, const SymbolType &lhs); + static SymbolType getPrefixMinusMinusResultType(const AstNode *node, const SymbolType &lhs); + static SymbolType getPrefixNotResultType(const AstNode *node, const SymbolType &lhs); + static SymbolType getPrefixBitwiseNotResultType(const AstNode *node, const SymbolType &lhs); + static SymbolType getPrefixMulResultType(const AstNode *node, const SymbolType &lhs); + static SymbolType getPrefixBitwiseAndResultType(const AstNode *node, const SymbolType &lhs); + static SymbolType getPostfixPlusPlusResultType(const AstNode *node, const SymbolType &lhs); + static SymbolType getPostfixMinusMinusResultType(const AstNode *node, const SymbolType &lhs); + SymbolType getCastResultType(const AstNode *node, const SymbolType &lhs, const SymbolType &); private: // Members AnalyzerVisitor *analyzer; // Private methods - SymbolType validateBinaryOperation(const CodeLoc &codeLoc, const std::vector &opRules, const std::string &opName, - const SymbolType &lhs, const SymbolType &rhs); - SymbolType validateUnaryOperation(const CodeLoc &codeLoc, const std::vector &opRules, const std::string &opName, - const SymbolType &lhs); - SemanticError printErrorMessageBinary(const CodeLoc &codeLoc, const std::string &operatorName, const SymbolType &lhs, - const SymbolType &rhs); - SemanticError printErrorMessageUnary(const CodeLoc &codeLoc, const std::string &operatorName, const SymbolType &lhs); - SemanticError printErrorMessageUnsafe(const CodeLoc &codeLoc, const std::string &operatorName, const SymbolType &lhs, - const SymbolType &rhs); + static SymbolType validateBinaryOperation(const AstNode *node, const std::vector &opRules, + const std::string &name, const SymbolType &lhs, const SymbolType &rhs); + static SymbolType validateUnaryOperation(const AstNode *node, const std::vector &opRules, const std::string &name, + const SymbolType &lhs); + static SemanticError printErrorMessageBinary(const AstNode *node, const std::string &name, const SymbolType &lhs, + const SymbolType &rhs); + static SemanticError printErrorMessageUnary(const AstNode *node, const std::string &name, const SymbolType &lhs); + static SemanticError printErrorMessageUnsafe(const AstNode *node, const std::string &name, const SymbolType &lhs, + const SymbolType &rhs); }; \ No newline at end of file diff --git a/src/analyzer/PreAnalyzerVisitor.cpp b/src/analyzer/PreAnalyzerVisitor.cpp index a1a66f41f..a7e9a7687 100644 --- a/src/analyzer/PreAnalyzerVisitor.cpp +++ b/src/analyzer/PreAnalyzerVisitor.cpp @@ -30,8 +30,7 @@ std::any PreAnalyzerVisitor::visitImportStmt(ImportStmtNode *node) { // Find std library std::string stdPath = FileUtil::getStdDir(); if (stdPath.empty()) - throw SemanticError(node->codeLoc, STD_NOT_FOUND, - "Standard library could not be found. Check if the env var SPICE_STD_DIR exists"); + throw SemanticError(node, STD_NOT_FOUND, "Standard library could not be found. Check if the env var SPICE_STD_DIR exists"); // Check if source file exists std::string defaultPath = stdPath + sourceFileIden + ".spice"; std::string osPath = stdPath + sourceFileIden + "_" + cliOptions.targetOs + ".spice"; @@ -44,7 +43,7 @@ std::any PreAnalyzerVisitor::visitImportStmt(ImportStmtNode *node) { } else if (FileUtil::fileExists(osArchPath)) { importPath = osArchPath; } else { - throw SemanticError(node->codeLoc, IMPORTED_FILE_NOT_EXISTING, + throw SemanticError(node, IMPORTED_FILE_NOT_EXISTING, "The source file '" + node->importPath + ".spice' was not found in the standard library"); } } else { // Include own source file @@ -63,8 +62,7 @@ std::any PreAnalyzerVisitor::visitImportStmt(ImportStmtNode *node) { } else if (FileUtil::fileExists(osArchPath)) { importPath = osArchPath; } else { - throw SemanticError(node->codeLoc, IMPORTED_FILE_NOT_EXISTING, - "The source file '" + node->importPath + ".spice' does not exist"); + throw SemanticError(node, IMPORTED_FILE_NOT_EXISTING, "The source file '" + node->importPath + ".spice' does not exist"); } } CommonUtil::replaceAll(importPath, "/", std::string(1, FileUtil::DIR_SEPARATOR)); diff --git a/src/ast/AstNodes.h b/src/ast/AstNodes.h index 9ccd1e4ce..80ce4e2a8 100644 --- a/src/ast/AstNodes.h +++ b/src/ast/AstNodes.h @@ -122,6 +122,7 @@ class AstNode { AstNode *parent; std::vector children; const CodeLoc codeLoc; + std::string errorMessage; size_t symbolTypeIndex = SIZE_MAX; std::vector symbolTypes; CompileTimeValue compileTimeValue = {}; diff --git a/src/dependency/SourceFile.cpp b/src/dependency/SourceFile.cpp index d101e6b5d..01bc163fb 100644 --- a/src/dependency/SourceFile.cpp +++ b/src/dependency/SourceFile.cpp @@ -108,7 +108,7 @@ void SourceFile::buildAST() { sourceFile.second.first->buildAST(); // Transform this source file - AstBuilderVisitor astBuilder(ast.get(), filePath); + AstBuilderVisitor astBuilder(ast.get(), filePath, antlrCtx.inputStream.get()); astBuilder.visit(antlrCtx.parser->entry()); antlrCtx.parser->reset(); } @@ -303,7 +303,7 @@ void SourceFile::addDependency(const std::shared_ptr &sourceFile, co const std::string &filePath) { // Check if this would cause a circular dependency if (isAlreadyImported(filePath)) - throw SemanticError(declAstNode->codeLoc, CIRCULAR_DEPENDENCY, "Circular import detected while importing '" + filePath + "'"); + throw SemanticError(declAstNode, CIRCULAR_DEPENDENCY, "Circular import detected while importing '" + filePath + "'"); // Add the dependency dependencies.insert({name, {sourceFile, declAstNode}}); diff --git a/src/exception/SemanticError.cpp b/src/exception/SemanticError.cpp index dfe57fb92..bc104d392 100644 --- a/src/exception/SemanticError.cpp +++ b/src/exception/SemanticError.cpp @@ -2,17 +2,13 @@ #include "SemanticError.h" +#include #include -/** - * Constructor: Used in case that the exact code position where the error occurred is known - * - * @param codeLoc Code location where the error occurred - * @param type Type of the error - * @param message Error message suffix - */ -SemanticError::SemanticError(const CodeLoc &codeLoc, const SemanticErrorType &type, const std::string &message) { - errorMessage = "Semantic error in " + codeLoc.toPrettyString() + ": " + getMessagePrefix(type) + ": " + message; +SemanticError::SemanticError(const AstNode *node, const SemanticErrorType &type, const std::string &message) { + errorMessage = "Semantic error in : " + node->codeLoc.toPrettyString() + ":\n"; + errorMessage += getMessagePrefix(type) + ": " + message + "\n\n"; + errorMessage += node->errorMessage; } /** diff --git a/src/exception/SemanticError.h b/src/exception/SemanticError.h index 3d8133781..47c624c4b 100644 --- a/src/exception/SemanticError.h +++ b/src/exception/SemanticError.h @@ -8,6 +8,7 @@ #include // Forward declarations +struct AstNode; struct CodeLoc; enum SemanticErrorType { @@ -79,7 +80,7 @@ enum SemanticErrorType { class SemanticError : public std::exception { public: // Constructors - explicit SemanticError(const CodeLoc &codeLoc, const SemanticErrorType &type, const std::string &message); + explicit SemanticError(const AstNode *node, const SemanticErrorType &type, const std::string &message); // Public methods [[nodiscard]] const char *what() const noexcept override; diff --git a/src/generator/GeneratorVisitor.cpp b/src/generator/GeneratorVisitor.cpp index c182d6c9d..681ee938b 100644 --- a/src/generator/GeneratorVisitor.cpp +++ b/src/generator/GeneratorVisitor.cpp @@ -2987,21 +2987,21 @@ std::any GeneratorVisitor::visitDataType(DataTypeNode *node) { DataTypeNode::TypeModifier typeModifier = tmQueue.front(); switch (typeModifier.modifierType) { case DataTypeNode::TYPE_PTR: { - symbolType = symbolType.toPointer(node->codeLoc); + symbolType = symbolType.toPointer(node); break; } case DataTypeNode::TYPE_ARRAY: { if (!typeModifier.hasSize) { - symbolType = symbolType.toPointer(node->codeLoc); + symbolType = symbolType.toPointer(node); } else if (typeModifier.isSizeHardcoded) { - symbolType = symbolType.toArray(node->codeLoc, typeModifier.hardcodedSize); + symbolType = symbolType.toArray(node, typeModifier.hardcodedSize); } else { AssignExprNode *indexExpr = arraySizeExpr[assignExprCounter++]; assert(indexExpr != nullptr); auto sizeValuePtr = any_cast(visit(indexExpr)); llvm::Type *sizeType = indexExpr->getEvaluatedSymbolType().toLLVMType(*context, currentScope); dynamicArraySize = builder->CreateLoad(sizeType, sizeValuePtr); - symbolType = symbolType.toPointer(node->codeLoc, dynamicArraySize); + symbolType = symbolType.toPointer(node, dynamicArraySize); } break; } diff --git a/src/parser/AstBuilderVisitor.cpp b/src/parser/AstBuilderVisitor.cpp index 64e69f512..17781c8ae 100644 --- a/src/parser/AstBuilderVisitor.cpp +++ b/src/parser/AstBuilderVisitor.cpp @@ -44,6 +44,8 @@ std::any AstBuilderVisitor::visitEntry(SpiceParser::EntryContext *ctx) { std::any AstBuilderVisitor::visitMainFunctionDef(SpiceParser::MainFunctionDefContext *ctx) { auto mainFctDefNode = dynamic_cast(currentNode); + saveErrorMessage(mainFctDefNode, ctx); + for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) { // ArgLstDef @@ -64,6 +66,7 @@ std::any AstBuilderVisitor::visitMainFunctionDef(SpiceParser::MainFunctionDefCon std::any AstBuilderVisitor::visitFunctionDef(SpiceParser::FunctionDefContext *ctx) { auto fctDefNode = dynamic_cast(currentNode); + saveErrorMessage(fctDefNode, ctx); // Extract function name fctDefNode->functionName = ctx->IDENTIFIER().back()->getText(); @@ -100,6 +103,7 @@ std::any AstBuilderVisitor::visitFunctionDef(SpiceParser::FunctionDefContext *ct std::any AstBuilderVisitor::visitProcedureDef(SpiceParser::ProcedureDefContext *ctx) { auto procDefNode = dynamic_cast(currentNode); + saveErrorMessage(procDefNode, ctx); // Extract procedure name procDefNode->procedureName = ctx->IDENTIFIER().back()->getText(); @@ -134,6 +138,7 @@ std::any AstBuilderVisitor::visitProcedureDef(SpiceParser::ProcedureDefContext * std::any AstBuilderVisitor::visitStructDef(SpiceParser::StructDefContext *ctx) { auto structDefNode = dynamic_cast(currentNode); + saveErrorMessage(structDefNode, ctx); // Extract struct name structDefNode->structName = ctx->IDENTIFIER()->getText(); @@ -160,6 +165,7 @@ std::any AstBuilderVisitor::visitStructDef(SpiceParser::StructDefContext *ctx) { std::any AstBuilderVisitor::visitEnumDef(SpiceParser::EnumDefContext *ctx) { auto enumDefNode = dynamic_cast(currentNode); + saveErrorMessage(enumDefNode, ctx); // Extract enum name enumDefNode->enumName = ctx->IDENTIFIER()->getText(); @@ -184,6 +190,7 @@ std::any AstBuilderVisitor::visitEnumDef(SpiceParser::EnumDefContext *ctx) { std::any AstBuilderVisitor::visitGenericTypeDef(SpiceParser::GenericTypeDefContext *ctx) { auto genericTypeDefNode = dynamic_cast(currentNode); + saveErrorMessage(genericTypeDefNode, ctx); // Extract type name genericTypeDefNode->typeName = ctx->IDENTIFIER()->getText(); @@ -207,6 +214,7 @@ std::any AstBuilderVisitor::visitGenericTypeDef(SpiceParser::GenericTypeDefConte std::any AstBuilderVisitor::visitGlobalVarDef(SpiceParser::GlobalVarDefContext *ctx) { auto globalVarDefNode = dynamic_cast(currentNode); + saveErrorMessage(globalVarDefNode, ctx); // Extract function name globalVarDefNode->varName = ctx->IDENTIFIER()->getText(); @@ -232,6 +240,7 @@ std::any AstBuilderVisitor::visitGlobalVarDef(SpiceParser::GlobalVarDefContext * std::any AstBuilderVisitor::visitExtDecl(SpiceParser::ExtDeclContext *ctx) { auto extDeclNode = dynamic_cast(currentNode); + saveErrorMessage(extDeclNode, ctx); // Extract function name extDeclNode->extFunctionName = ctx->IDENTIFIER()->getText(); @@ -257,6 +266,7 @@ std::any AstBuilderVisitor::visitExtDecl(SpiceParser::ExtDeclContext *ctx) { std::any AstBuilderVisitor::visitThreadDef(SpiceParser::ThreadDefContext *ctx) { auto threadDefNode = dynamic_cast(currentNode); + saveErrorMessage(threadDefNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -275,6 +285,7 @@ std::any AstBuilderVisitor::visitThreadDef(SpiceParser::ThreadDefContext *ctx) { std::any AstBuilderVisitor::visitUnsafeBlockDef(SpiceParser::UnsafeBlockDefContext *ctx) { auto unsafeBlockDefNode = dynamic_cast(currentNode); + saveErrorMessage(unsafeBlockDefNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -293,6 +304,7 @@ std::any AstBuilderVisitor::visitUnsafeBlockDef(SpiceParser::UnsafeBlockDefConte std::any AstBuilderVisitor::visitForLoop(SpiceParser::ForLoopContext *ctx) { auto forLoopNode = dynamic_cast(currentNode); + saveErrorMessage(forLoopNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -313,6 +325,7 @@ std::any AstBuilderVisitor::visitForLoop(SpiceParser::ForLoopContext *ctx) { std::any AstBuilderVisitor::visitForHead(SpiceParser::ForHeadContext *ctx) { auto forLoopNode = dynamic_cast(currentNode); + saveErrorMessage(forLoopNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -333,6 +346,7 @@ std::any AstBuilderVisitor::visitForHead(SpiceParser::ForHeadContext *ctx) { std::any AstBuilderVisitor::visitForeachLoop(SpiceParser::ForeachLoopContext *ctx) { auto foreachLoopNode = dynamic_cast(currentNode); + saveErrorMessage(foreachLoopNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -353,6 +367,7 @@ std::any AstBuilderVisitor::visitForeachLoop(SpiceParser::ForeachLoopContext *ct std::any AstBuilderVisitor::visitForeachHead(SpiceParser::ForeachHeadContext *ctx) { auto foreachLoopNode = dynamic_cast(currentNode); + saveErrorMessage(foreachLoopNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -373,6 +388,7 @@ std::any AstBuilderVisitor::visitForeachHead(SpiceParser::ForeachHeadContext *ct std::any AstBuilderVisitor::visitWhileLoop(SpiceParser::WhileLoopContext *ctx) { auto whileLoopNode = dynamic_cast(currentNode); + saveErrorMessage(whileLoopNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -393,6 +409,7 @@ std::any AstBuilderVisitor::visitWhileLoop(SpiceParser::WhileLoopContext *ctx) { std::any AstBuilderVisitor::visitIfStmt(SpiceParser::IfStmtContext *ctx) { auto ifStmtNode = dynamic_cast(currentNode); + saveErrorMessage(ifStmtNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -415,6 +432,7 @@ std::any AstBuilderVisitor::visitIfStmt(SpiceParser::IfStmtContext *ctx) { std::any AstBuilderVisitor::visitElseStmt(SpiceParser::ElseStmtContext *ctx) { auto elseStmtNode = dynamic_cast(currentNode); + saveErrorMessage(elseStmtNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -436,6 +454,7 @@ std::any AstBuilderVisitor::visitElseStmt(SpiceParser::ElseStmtContext *ctx) { std::any AstBuilderVisitor::visitAssertStmt(SpiceParser::AssertStmtContext *ctx) { auto assertStmtNode = dynamic_cast(currentNode); + saveErrorMessage(assertStmtNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -455,6 +474,8 @@ std::any AstBuilderVisitor::visitAssertStmt(SpiceParser::AssertStmtContext *ctx) std::any AstBuilderVisitor::visitStmtLst(SpiceParser::StmtLstContext *ctx) { auto stmtLstNode = dynamic_cast(currentNode); + saveErrorMessage(stmtLstNode, ctx); + for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // Stmt @@ -486,6 +507,7 @@ std::any AstBuilderVisitor::visitStmtLst(SpiceParser::StmtLstContext *ctx) { std::any AstBuilderVisitor::visitTypeLst(SpiceParser::TypeLstContext *ctx) { auto typeLstNode = dynamic_cast(currentNode); + saveErrorMessage(typeLstNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -505,6 +527,7 @@ std::any AstBuilderVisitor::visitTypeLst(SpiceParser::TypeLstContext *ctx) { std::any AstBuilderVisitor::visitTypeAltsLst(SpiceParser::TypeAltsLstContext *ctx) { auto typeAltsLstNode = dynamic_cast(currentNode); + saveErrorMessage(typeAltsLstNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -524,6 +547,7 @@ std::any AstBuilderVisitor::visitTypeAltsLst(SpiceParser::TypeAltsLstContext *ct std::any AstBuilderVisitor::visitParamLst(SpiceParser::ParamLstContext *ctx) { auto argLstDefNode = dynamic_cast(currentNode); + saveErrorMessage(argLstDefNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -542,6 +566,7 @@ std::any AstBuilderVisitor::visitParamLst(SpiceParser::ParamLstContext *ctx) { std::any AstBuilderVisitor::visitArgLst(SpiceParser::ArgLstContext *ctx) { auto argLstNode = dynamic_cast(currentNode); + saveErrorMessage(argLstNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -560,6 +585,7 @@ std::any AstBuilderVisitor::visitArgLst(SpiceParser::ArgLstContext *ctx) { std::any AstBuilderVisitor::visitEnumItemLst(SpiceParser::EnumItemLstContext *ctx) { auto enumItemLstNode = dynamic_cast(currentNode); + saveErrorMessage(enumItemLstNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -578,6 +604,7 @@ std::any AstBuilderVisitor::visitEnumItemLst(SpiceParser::EnumItemLstContext *ct std::any AstBuilderVisitor::visitEnumItem(SpiceParser::EnumItemContext *ctx) { auto enumItemNode = dynamic_cast(currentNode); + saveErrorMessage(enumItemNode, ctx); for (const auto &subTree : ctx->children) { if (auto t = dynamic_cast(subTree); t->getSymbol()->getType() == SpiceParser::IDENTIFIER) @@ -593,6 +620,7 @@ std::any AstBuilderVisitor::visitEnumItem(SpiceParser::EnumItemContext *ctx) { std::any AstBuilderVisitor::visitField(SpiceParser::FieldContext *ctx) { auto fieldNode = dynamic_cast(currentNode); + saveErrorMessage(fieldNode, ctx); // Extract field name fieldNode->name = ctx->IDENTIFIER()->getText(); @@ -616,6 +644,7 @@ std::any AstBuilderVisitor::visitField(SpiceParser::FieldContext *ctx) { std::any AstBuilderVisitor::visitStmt(SpiceParser::StmtContext *ctx) { auto stmtNode = dynamic_cast(currentNode); + saveErrorMessage(stmtNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -642,6 +671,7 @@ std::any AstBuilderVisitor::visitStmt(SpiceParser::StmtContext *ctx) { std::any AstBuilderVisitor::visitDeclStmt(SpiceParser::DeclStmtContext *ctx) { auto declStmtNode = dynamic_cast(currentNode); + saveErrorMessage(declStmtNode, ctx); // Extract var name declStmtNode->varName = ctx->IDENTIFIER()->getText(); @@ -668,6 +698,7 @@ std::any AstBuilderVisitor::visitDeclStmt(SpiceParser::DeclStmtContext *ctx) { std::any AstBuilderVisitor::visitSpecifierLst(SpiceParser::SpecifierLstContext *ctx) { auto specifierLstNode = dynamic_cast(currentNode); + saveErrorMessage(specifierLstNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -686,6 +717,7 @@ std::any AstBuilderVisitor::visitSpecifierLst(SpiceParser::SpecifierLstContext * std::any AstBuilderVisitor::visitSpecifier(SpiceParser::SpecifierContext *ctx) { auto specifierNode = dynamic_cast(currentNode); + saveErrorMessage(specifierNode, ctx); for (const auto &subTree : ctx->children) { auto token = dynamic_cast(subTree); @@ -709,6 +741,7 @@ std::any AstBuilderVisitor::visitSpecifier(SpiceParser::SpecifierContext *ctx) { std::any AstBuilderVisitor::visitImportStmt(SpiceParser::ImportStmtContext *ctx) { auto importStmtNode = dynamic_cast(currentNode); + saveErrorMessage(importStmtNode, ctx); // Extract path std::string pathStr = ctx->STRING_LIT()->getText(); @@ -722,6 +755,7 @@ std::any AstBuilderVisitor::visitImportStmt(SpiceParser::ImportStmtContext *ctx) std::any AstBuilderVisitor::visitReturnStmt(SpiceParser::ReturnStmtContext *ctx) { auto returnStmtNode = dynamic_cast(currentNode); + saveErrorMessage(returnStmtNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -741,6 +775,7 @@ std::any AstBuilderVisitor::visitReturnStmt(SpiceParser::ReturnStmtContext *ctx) std::any AstBuilderVisitor::visitBreakStmt(SpiceParser::BreakStmtContext *ctx) { auto breakStmtNode = dynamic_cast(currentNode); + saveErrorMessage(breakStmtNode, ctx); // Extract number of breaks if (ctx->INT_LIT()) @@ -751,6 +786,7 @@ std::any AstBuilderVisitor::visitBreakStmt(SpiceParser::BreakStmtContext *ctx) { std::any AstBuilderVisitor::visitContinueStmt(SpiceParser::ContinueStmtContext *ctx) { auto continueStmtNode = dynamic_cast(currentNode); + saveErrorMessage(continueStmtNode, ctx); // Extract number of continues if (ctx->INT_LIT()) @@ -761,6 +797,7 @@ std::any AstBuilderVisitor::visitContinueStmt(SpiceParser::ContinueStmtContext * std::any AstBuilderVisitor::visitBuiltinCall(SpiceParser::BuiltinCallContext *ctx) { auto atomicExprNode = dynamic_cast(currentNode); + saveErrorMessage(atomicExprNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -787,6 +824,7 @@ std::any AstBuilderVisitor::visitBuiltinCall(SpiceParser::BuiltinCallContext *ct std::any AstBuilderVisitor::visitPrintfCall(SpiceParser::PrintfCallContext *ctx) { auto printfCallNode = dynamic_cast(currentNode); + saveErrorMessage(printfCallNode, ctx); // Extract templated string std::string templatedString = ctx->STRING_LIT()->getText(); @@ -811,6 +849,7 @@ std::any AstBuilderVisitor::visitPrintfCall(SpiceParser::PrintfCallContext *ctx) std::any AstBuilderVisitor::visitSizeOfCall(SpiceParser::SizeOfCallContext *ctx) { auto sizeofCallNode = dynamic_cast(currentNode); + saveErrorMessage(sizeofCallNode, ctx); // Check if type or value sizeofCallNode->isType = ctx->TYPE(); @@ -834,6 +873,7 @@ std::any AstBuilderVisitor::visitSizeOfCall(SpiceParser::SizeOfCallContext *ctx) std::any AstBuilderVisitor::visitLenCall(SpiceParser::LenCallContext *ctx) { auto lenCallNode = dynamic_cast(currentNode); + saveErrorMessage(lenCallNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -850,10 +890,15 @@ std::any AstBuilderVisitor::visitLenCall(SpiceParser::LenCallContext *ctx) { return nullptr; } -std::any AstBuilderVisitor::visitTidCall(SpiceParser::TidCallContext *ctx) { return nullptr; } +std::any AstBuilderVisitor::visitTidCall(SpiceParser::TidCallContext *ctx) { + auto tidCallNode = dynamic_cast(currentNode); + saveErrorMessage(tidCallNode, ctx); + return nullptr; +} std::any AstBuilderVisitor::visitJoinCall(SpiceParser::JoinCallContext *ctx) { auto joinCallNode = dynamic_cast(currentNode); + saveErrorMessage(joinCallNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -872,6 +917,7 @@ std::any AstBuilderVisitor::visitJoinCall(SpiceParser::JoinCallContext *ctx) { std::any AstBuilderVisitor::visitAssignExpr(SpiceParser::AssignExprContext *ctx) { auto assignExprNode = dynamic_cast(currentNode); + saveErrorMessage(assignExprNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -898,6 +944,7 @@ std::any AstBuilderVisitor::visitAssignExpr(SpiceParser::AssignExprContext *ctx) std::any AstBuilderVisitor::visitTernaryExpr(SpiceParser::TernaryExprContext *ctx) { auto ternaryExprNode = dynamic_cast(currentNode); + saveErrorMessage(ternaryExprNode, ctx); // Check if is shortened ternaryExprNode->isShortened = ctx->logicalOrExpr().size() == 2; @@ -919,6 +966,7 @@ std::any AstBuilderVisitor::visitTernaryExpr(SpiceParser::TernaryExprContext *ct std::any AstBuilderVisitor::visitLogicalOrExpr(SpiceParser::LogicalOrExprContext *ctx) { auto logicalOrExprNode = dynamic_cast(currentNode); + saveErrorMessage(logicalOrExprNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -937,6 +985,7 @@ std::any AstBuilderVisitor::visitLogicalOrExpr(SpiceParser::LogicalOrExprContext std::any AstBuilderVisitor::visitLogicalAndExpr(SpiceParser::LogicalAndExprContext *ctx) { auto logicalAndExprNode = dynamic_cast(currentNode); + saveErrorMessage(logicalAndExprNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -955,6 +1004,7 @@ std::any AstBuilderVisitor::visitLogicalAndExpr(SpiceParser::LogicalAndExprConte std::any AstBuilderVisitor::visitBitwiseOrExpr(SpiceParser::BitwiseOrExprContext *ctx) { auto bitwiseOrExprNode = dynamic_cast(currentNode); + saveErrorMessage(bitwiseOrExprNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -973,6 +1023,7 @@ std::any AstBuilderVisitor::visitBitwiseOrExpr(SpiceParser::BitwiseOrExprContext std::any AstBuilderVisitor::visitBitwiseXorExpr(SpiceParser::BitwiseXorExprContext *ctx) { auto bitwiseXorExprNode = dynamic_cast(currentNode); + saveErrorMessage(bitwiseXorExprNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -991,6 +1042,7 @@ std::any AstBuilderVisitor::visitBitwiseXorExpr(SpiceParser::BitwiseXorExprConte std::any AstBuilderVisitor::visitBitwiseAndExpr(SpiceParser::BitwiseAndExprContext *ctx) { auto bitwiseAndExprNode = dynamic_cast(currentNode); + saveErrorMessage(bitwiseAndExprNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -1009,6 +1061,7 @@ std::any AstBuilderVisitor::visitBitwiseAndExpr(SpiceParser::BitwiseAndExprConte std::any AstBuilderVisitor::visitEqualityExpr(SpiceParser::EqualityExprContext *ctx) { auto equalityExprNode = dynamic_cast(currentNode); + saveErrorMessage(equalityExprNode, ctx); // Extract operator if (ctx->EQUAL()) @@ -1033,6 +1086,7 @@ std::any AstBuilderVisitor::visitEqualityExpr(SpiceParser::EqualityExprContext * std::any AstBuilderVisitor::visitRelationalExpr(SpiceParser::RelationalExprContext *ctx) { auto relationalExprNode = dynamic_cast(currentNode); + saveErrorMessage(relationalExprNode, ctx); // Extract operator if (ctx->LESS()) @@ -1061,6 +1115,7 @@ std::any AstBuilderVisitor::visitRelationalExpr(SpiceParser::RelationalExprConte std::any AstBuilderVisitor::visitShiftExpr(SpiceParser::ShiftExprContext *ctx) { auto shiftExprNode = dynamic_cast(currentNode); + saveErrorMessage(shiftExprNode, ctx); // Extract operator if (!ctx->LESS().empty()) @@ -1085,6 +1140,7 @@ std::any AstBuilderVisitor::visitShiftExpr(SpiceParser::ShiftExprContext *ctx) { std::any AstBuilderVisitor::visitAdditiveExpr(SpiceParser::AdditiveExprContext *ctx) { auto additiveExprNode = dynamic_cast(currentNode); + saveErrorMessage(additiveExprNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -1107,6 +1163,7 @@ std::any AstBuilderVisitor::visitAdditiveExpr(SpiceParser::AdditiveExprContext * std::any AstBuilderVisitor::visitMultiplicativeExpr(SpiceParser::MultiplicativeExprContext *ctx) { auto multiplicativeExprNode = dynamic_cast(currentNode); + saveErrorMessage(multiplicativeExprNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -1131,6 +1188,7 @@ std::any AstBuilderVisitor::visitMultiplicativeExpr(SpiceParser::MultiplicativeE std::any AstBuilderVisitor::visitCastExpr(SpiceParser::CastExprContext *ctx) { auto castExprNode = dynamic_cast(currentNode); + saveErrorMessage(castExprNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -1152,6 +1210,7 @@ std::any AstBuilderVisitor::visitCastExpr(SpiceParser::CastExprContext *ctx) { std::any AstBuilderVisitor::visitPrefixUnaryExpr(SpiceParser::PrefixUnaryExprContext *ctx) { auto prefixUnaryExprNode = dynamic_cast(currentNode); + saveErrorMessage(prefixUnaryExprNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -1172,6 +1231,7 @@ std::any AstBuilderVisitor::visitPrefixUnaryExpr(SpiceParser::PrefixUnaryExprCon std::any AstBuilderVisitor::visitPostfixUnaryExpr(SpiceParser::PostfixUnaryExprContext *ctx) { auto postfixUnaryExprNode = dynamic_cast(currentNode); + saveErrorMessage(postfixUnaryExprNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -1204,6 +1264,7 @@ std::any AstBuilderVisitor::visitPostfixUnaryExpr(SpiceParser::PostfixUnaryExprC std::any AstBuilderVisitor::visitAtomicExpr(SpiceParser::AtomicExprContext *ctx) { auto atomicExprNode = dynamic_cast(currentNode); + saveErrorMessage(atomicExprNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -1228,6 +1289,7 @@ std::any AstBuilderVisitor::visitAtomicExpr(SpiceParser::AtomicExprContext *ctx) std::any AstBuilderVisitor::visitValue(SpiceParser::ValueContext *ctx) { auto valueNode = dynamic_cast(currentNode); + saveErrorMessage(valueNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -1255,6 +1317,7 @@ std::any AstBuilderVisitor::visitValue(SpiceParser::ValueContext *ctx) { std::any AstBuilderVisitor::visitPrimitiveValue(SpiceParser::PrimitiveValueContext *ctx) { auto primitiveValueNode = dynamic_cast(currentNode); + saveErrorMessage(primitiveValueNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -1309,6 +1372,7 @@ std::any AstBuilderVisitor::visitPrimitiveValue(SpiceParser::PrimitiveValueConte std::any AstBuilderVisitor::visitFunctionCall(SpiceParser::FunctionCallContext *ctx) { auto fctCallNode = dynamic_cast(currentNode); + saveErrorMessage(fctCallNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -1338,6 +1402,7 @@ std::any AstBuilderVisitor::visitFunctionCall(SpiceParser::FunctionCallContext * std::any AstBuilderVisitor::visitArrayInitialization(SpiceParser::ArrayInitializationContext *ctx) { auto arrayInitializationNode = dynamic_cast(currentNode); + saveErrorMessage(arrayInitializationNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -1356,6 +1421,7 @@ std::any AstBuilderVisitor::visitArrayInitialization(SpiceParser::ArrayInitializ std::any AstBuilderVisitor::visitStructInstantiation(SpiceParser::StructInstantiationContext *ctx) { auto structInstantiationNode = dynamic_cast(currentNode); + saveErrorMessage(structInstantiationNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -1382,6 +1448,7 @@ std::any AstBuilderVisitor::visitStructInstantiation(SpiceParser::StructInstanti std::any AstBuilderVisitor::visitDataType(SpiceParser::DataTypeContext *ctx) { auto dataTypeNode = dynamic_cast(currentNode); + saveErrorMessage(dataTypeNode, ctx); for (int i = 0; i < ctx->children.size(); i++) { auto subTree = ctx->children[i]; @@ -1422,6 +1489,7 @@ std::any AstBuilderVisitor::visitDataType(SpiceParser::DataTypeContext *ctx) { std::any AstBuilderVisitor::visitBaseDataType(SpiceParser::BaseDataTypeContext *ctx) { auto baseDataTypeNode = dynamic_cast(currentNode); + saveErrorMessage(baseDataTypeNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -1460,6 +1528,7 @@ std::any AstBuilderVisitor::visitBaseDataType(SpiceParser::BaseDataTypeContext * std::any AstBuilderVisitor::visitCustomDataType(SpiceParser::CustomDataTypeContext *ctx) { auto customDataTypeNode = dynamic_cast(currentNode); + saveErrorMessage(customDataTypeNode, ctx); for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; @@ -1484,6 +1553,7 @@ std::any AstBuilderVisitor::visitCustomDataType(SpiceParser::CustomDataTypeConte std::any AstBuilderVisitor::visitAssignOp(SpiceParser::AssignOpContext *ctx) { auto assignExprNode = dynamic_cast(currentNode); + saveErrorMessage(assignExprNode, ctx); assignExprNode->hasOperator = true; @@ -1518,6 +1588,7 @@ std::any AstBuilderVisitor::visitAssignOp(SpiceParser::AssignOpContext *ctx) { std::any AstBuilderVisitor::visitPrefixUnaryOp(SpiceParser::PrefixUnaryOpContext *ctx) { auto prefixUnaryExprNode = dynamic_cast(currentNode); + saveErrorMessage(prefixUnaryExprNode, ctx); // Extract assign operator if (ctx->MINUS()) @@ -1603,11 +1674,11 @@ int8_t AstBuilderVisitor::parseChar(antlr4::tree::TerminalNode *terminal) { return '\0'; default: CodeLoc codeLoc = CodeLoc(terminal->getSymbol(), fileName); - throw LexerParserError(codeLoc, PARSING_FAILED, "Invalid escape sequence " + input); + throw LexerParserError(codeLoc, INVALID_CHAR_LITERAL, "Invalid escape sequence " + input); } } else { CodeLoc codeLoc = CodeLoc(terminal->getSymbol(), fileName); - throw LexerParserError(codeLoc, PARSING_FAILED, "Invalid char literal " + input); + throw LexerParserError(codeLoc, INVALID_CHAR_LITERAL, "Invalid char literal " + input); } } @@ -1655,4 +1726,53 @@ T AstBuilderVisitor::parseNumeric(antlr4::tree::TerminalNode *terminal, std::fun throw LexerParserError(codeLoc, NUMBER_OUT_OF_RANGE, "You tried to parse '" + input + "' as an integer, but it was no integer"); } +} + +void AstBuilderVisitor::saveErrorMessage(AstNode *node, const antlr4::ParserRuleContext *ctx) { + const antlr4::misc::Interval sourceInterval(ctx->start->getStartIndex(), ctx->stop->getStopIndex()); + antlr4::misc::Interval extendedSourceInterval(sourceInterval); + + if (inputStream->getText(extendedSourceInterval).find('\n') != std::string::npos) { + extendedSourceInterval.b = extendedSourceInterval.a; + while (inputStream->getText(extendedSourceInterval).find('\n') == std::string::npos) + extendedSourceInterval.b++; + } + + size_t indentation = 0; + for (; indentation < ERROR_MESSAGE_CONTEXT; indentation++) { + extendedSourceInterval.a--; + if (extendedSourceInterval.a < 0 || inputStream->getText(extendedSourceInterval).find('\n') != std::string::npos) { + extendedSourceInterval.a++; + break; + } + } + for (size_t suffixContext = 0; suffixContext < ERROR_MESSAGE_CONTEXT; suffixContext++) { + extendedSourceInterval.b++; + if (extendedSourceInterval.b > inputStream->size() || + inputStream->getText(extendedSourceInterval).find('\n') != std::string::npos) { + extendedSourceInterval.b--; + break; + } + } + + // Trim start + while (inputStream->getText(extendedSourceInterval)[0] == ' ') { + extendedSourceInterval.a++; + indentation--; + } + + // Trim end + if (inputStream->getText(extendedSourceInterval)[extendedSourceInterval.length() - 1] == '\n') + extendedSourceInterval.b--; + + std::string lineNumberStr = std::to_string(ctx->start->getLine()); + indentation += lineNumberStr.length() + 2; + + std::stringstream ss; + ss << lineNumberStr << " " << inputStream->getText(extendedSourceInterval) << "\n"; + for (size_t i = 0; i < indentation; i++) + ss << " "; + for (size_t i = 0; i < std::min(sourceInterval.length(), extendedSourceInterval.length()); i++) + ss << "^"; + node->errorMessage = ss.str(); } \ No newline at end of file diff --git a/src/parser/AstBuilderVisitor.h b/src/parser/AstBuilderVisitor.h index 51d154829..a344ddc48 100644 --- a/src/parser/AstBuilderVisitor.h +++ b/src/parser/AstBuilderVisitor.h @@ -10,10 +10,13 @@ // Forward declarations class AstNode; +#define ERROR_MESSAGE_CONTEXT 20 + class AstBuilderVisitor : public SpiceVisitor { public: // Constructors - explicit AstBuilderVisitor(AstNode *rootNode, std::string fileName) : currentNode(rootNode), fileName(std::move(fileName)) {} + explicit AstBuilderVisitor(AstNode *rootNode, std::string fileName, antlr4::ANTLRInputStream *inputStream) + : currentNode(rootNode), fileName(std::move(fileName)), inputStream(inputStream) {} // Public methods std::any visitEntry(SpiceParser::EntryContext *ctx) override; @@ -88,6 +91,7 @@ class AstBuilderVisitor : public SpiceVisitor { // Members AstNode *currentNode; std::string fileName; + antlr4::ANTLRInputStream *inputStream; // Private methods int32_t parseInt(antlr4::tree::TerminalNode *terminal); @@ -97,4 +101,5 @@ class AstBuilderVisitor : public SpiceVisitor { static std::string parseString(std::string input); template T parseNumeric(antlr4::tree::TerminalNode *terminal, std::function cb); static void replaceEscapeChars(std::string &string); + void saveErrorMessage(AstNode *node, const antlr4::ParserRuleContext *ctx); }; \ No newline at end of file diff --git a/src/symbol/Function.h b/src/symbol/Function.h index 42260745f..615f85bb4 100644 --- a/src/symbol/Function.h +++ b/src/symbol/Function.h @@ -10,6 +10,7 @@ // Forward declarations struct AstNode; +struct CodeLoc; typedef std::vector> ParamList; typedef std::vector> NamedParamList; diff --git a/src/symbol/SymbolTable.cpp b/src/symbol/SymbolTable.cpp index d8c63b9aa..875518256 100644 --- a/src/symbol/SymbolTable.cpp +++ b/src/symbol/SymbolTable.cpp @@ -377,13 +377,13 @@ void SymbolTable::insertFunction(const Function &function) { * @param callThisType This type requirement * @param callArgTypes Argument types requirement * @param err Error Factory - * @param codeLoc Declaration code location for the error message + * @param node Declaration node for the error message * * @return Matched function or nullptr */ Function *SymbolTable::matchFunction(SymbolTable *currentScope, const std::string &callFunctionName, const SymbolType &callThisType, const std::vector &callArgTypes, - const CodeLoc &codeLoc) { + const AstNode *node) { std::vector matches; // Loop through functions and add any matches to the matches vector @@ -469,7 +469,7 @@ Function *SymbolTable::matchFunction(SymbolTable *currentScope, const std::strin if ((f.isMethodFunction() || f.isMethodProcedure()) && !fctThisType.getTemplateTypes().empty()) { SymbolTableEntry *thisEntry = childBlock->lookup(THIS_VARIABLE_NAME); assert(thisEntry != nullptr); - SymbolType newThisType = callThisType.toPointer(codeLoc); + SymbolType newThisType = callThisType.toPointer(node); thisEntry->updateType(newThisType, true); } } @@ -486,13 +486,13 @@ Function *SymbolTable::matchFunction(SymbolTable *currentScope, const std::strin // Throw error if more than one function matches the criteria if (matches.size() > 1) throw SemanticError( - codeLoc, FUNCTION_AMBIGUITY, + node, FUNCTION_AMBIGUITY, "More than one function matches your requested signature criteria. Please try to specify the return type explicitly"); // Add function access pointer for function call if (currentScope != nullptr) { std::string suffix = callFunctionName == DTOR_VARIABLE_NAME ? callFunctionName : ""; - currentScope->insertFunctionAccessPointer(matches.front(), codeLoc, suffix); + currentScope->insertFunctionAccessPointer(matches.front(), node->codeLoc, suffix); } return matches.front(); @@ -549,7 +549,7 @@ void SymbolTable::insertSubstantiatedFunction(const Function &function, const As std::string mangledFctName = function.getMangledName(); for (const auto &[_, manifestations] : functions) { if (manifestations->contains(mangledFctName)) - throw SemanticError(declNode->codeLoc, FUNCTION_DECLARED_TWICE, + throw SemanticError(declNode, FUNCTION_DECLARED_TWICE, "The function/procedure '" + function.getSignature() + "' is declared twice"); } // Add function to function list @@ -580,11 +580,11 @@ void SymbolTable::insertStruct(const Struct &s) { * @param currentScope Current scope * @param structName Struct name * @param templateTypes Template type requirements - * @param codeLoc Declaration code location for the error message + * @param node Declaration node for the error message * @return Matched struct or nullptr */ Struct *SymbolTable::matchStruct(SymbolTable *currentScope, const std::string &structName, - const std::vector &templateTypes, const CodeLoc &codeLoc) { + const std::vector &templateTypes, const AstNode *node) { std::vector matches; // Loop through structs and add any matches to the matches vector @@ -632,7 +632,7 @@ Struct *SymbolTable::matchStruct(SymbolTable *currentScope, const std::string &s } if (matches.empty() && parent) - matches.push_back(parent->matchStruct(currentScope, structName, templateTypes, codeLoc)); + matches.push_back(parent->matchStruct(currentScope, structName, templateTypes, node)); if (matches.empty()) return nullptr; @@ -640,12 +640,12 @@ Struct *SymbolTable::matchStruct(SymbolTable *currentScope, const std::string &s // Throw error if more than one struct matches the criteria if (matches.size() > 1) throw SemanticError( - codeLoc, STRUCT_AMBIGUITY, + node, STRUCT_AMBIGUITY, "More than one struct matches your requested signature criteria. Please try to specify the return type explicitly"); // Add struct access pointer for struct reference if (currentScope != nullptr) - currentScope->insertStructAccessPointer(codeLoc, matches.front()); + currentScope->insertStructAccessPointer(node->codeLoc, matches.front()); return matches.front(); } @@ -697,7 +697,7 @@ void SymbolTable::insertSubstantiatedStruct(const Struct &s, const AstNode *decl // Check if the struct exists already for (const auto &[_, manifestations] : structs) { if (manifestations->contains(s.getMangledName())) - throw SemanticError(declNode->codeLoc, STRUCT_DECLARED_TWICE, "The struct '" + s.getSignature() + "' is declared twice"); + throw SemanticError(declNode, STRUCT_DECLARED_TWICE, "The struct '" + s.getSignature() + "' is declared twice"); } // Add struct to struct list assert(structs.at(declNode->codeLoc.toString()) != nullptr); diff --git a/src/symbol/SymbolTable.h b/src/symbol/SymbolTable.h index d9ad10f46..ee88ad876 100644 --- a/src/symbol/SymbolTable.h +++ b/src/symbol/SymbolTable.h @@ -74,7 +74,7 @@ class SymbolTable { void insertFunction(const Function &function); Function *matchFunction(SymbolTable *currentScope, const std::string &callFunctionName, const SymbolType &callThisType, - const std::vector &callArgTypes, const CodeLoc &codeLoc); + const std::vector &callArgTypes, const AstNode *node); [[nodiscard]] std::map *getFunctionManifestations(const CodeLoc &defCodeLoc) const; void insertFunctionAccessPointer(Function *spiceFunc, const CodeLoc &codeLoc, const std::string &suffix); Function *getFunctionAccessPointer(const CodeLoc &codeLoc, const std::string &suffix = ""); @@ -82,7 +82,7 @@ class SymbolTable { void insertStruct(const Struct &s); Struct *matchStruct(SymbolTable *currentScope, const std::string &structName, const std::vector &templateTypes, - const CodeLoc &codeLoc); + const AstNode *node); [[nodiscard]] std::map *getStructManifestations(const CodeLoc &defCodeLoc) const; void insertStructAccessPointer(const CodeLoc &codeLoc, Struct *spiceStruct); Struct *getStructAccessPointer(const CodeLoc &codeLoc); diff --git a/src/symbol/SymbolTableEntry.cpp b/src/symbol/SymbolTableEntry.cpp index 806c5a1d6..43c4c4e9a 100644 --- a/src/symbol/SymbolTableEntry.cpp +++ b/src/symbol/SymbolTableEntry.cpp @@ -28,19 +28,26 @@ void SymbolTableEntry::updateType(const SymbolType &newType, bool force) { * @throws runtime_error When the state of the symbol is set to initialized before a concrete type was set * * @param newState New state of the current symbol - * @param codeLoc Code location where the update takes place + * @param node AST node where the update takes place * @param force Force update. This can only be used compiler-internal */ -void SymbolTableEntry::updateState(SymbolState newState, const CodeLoc &codeLoc, bool force) { +void SymbolTableEntry::updateState(SymbolState newState, const AstNode *node, bool force) { // Check if this is a constant variable and is already initialized if (state == INITIALIZED && specifiers.isConst() && !force) - throw SemanticError(codeLoc, REASSIGN_CONST_VARIABLE, "Not re-assignable variable '" + name + "'"); + throw SemanticError(node, REASSIGN_CONST_VARIABLE, "Not re-assignable variable '" + name + "'"); // Check if the type is known at time of initialization if (newState == INITIALIZED && type == SymbolType(TY_DYN)) // GCOV_EXCL_LINE throw std::runtime_error("Internal compiler error: could not determine type of variable '" + name + "'"); // GCOV_EXCL_LINE state = newState; } +/** + * Retrieve the AST node where the symbol was declared + * + * @return Declaration node + */ +const AstNode *SymbolTableEntry::getDeclNode() const { return declNode; } + /** * Retrieve the code location where the symbol was declared * diff --git a/src/symbol/SymbolTableEntry.h b/src/symbol/SymbolTableEntry.h index 45683b278..dd14535fd 100644 --- a/src/symbol/SymbolTableEntry.h +++ b/src/symbol/SymbolTableEntry.h @@ -15,6 +15,7 @@ // Forward declarations class SymbolTable; struct AstNode; +struct CodeLoc; enum SymbolState { DECLARED, INITIALIZED }; @@ -31,7 +32,8 @@ class SymbolTableEntry { // Public methods void updateType(const SymbolType &newType, bool force); - void updateState(SymbolState newState, const CodeLoc &codeLoc, bool force = false); + void updateState(SymbolState newState, const AstNode *node, bool force = false); + [[nodiscard]] const AstNode *getDeclNode() const; [[nodiscard]] const CodeLoc &getDeclCodeLoc() const; [[nodiscard]] llvm::Type *getStructLLVMType() const; void setStructLLVMType(llvm::Type *newStructType); diff --git a/src/symbol/SymbolType.cpp b/src/symbol/SymbolType.cpp index 496736746..34df89ada 100644 --- a/src/symbol/SymbolType.cpp +++ b/src/symbol/SymbolType.cpp @@ -23,13 +23,13 @@ SymbolType::TypeChain SymbolType::getTypeChain() const { return typeChain; } * * @return Pointer type of the current type */ -SymbolType SymbolType::toPointer(const CodeLoc &codeLoc, llvm::Value *dynamicSize) const { +SymbolType SymbolType::toPointer(const AstNode *node, llvm::Value *dynamicSize) const { // Do not allow pointers of dyn if (typeChain.top().superType == TY_DYN) - throw SemanticError(codeLoc, DYN_POINTERS_NOT_ALLOWED, "Just use the dyn type without '*' instead"); + throw SemanticError(node, DYN_POINTERS_NOT_ALLOWED, "Just use the dyn type without '*' instead"); TypeChain newTypeChain = typeChain; - newTypeChain.push({TY_PTR, "", 0, {}, dynamicSize}); + newTypeChain.push({TY_PTR, "", {.arraySize = 0}, {}, dynamicSize}); return SymbolType(newTypeChain); } @@ -38,10 +38,10 @@ SymbolType SymbolType::toPointer(const CodeLoc &codeLoc, llvm::Value *dynamicSiz * * @return Array type of the current type */ -SymbolType SymbolType::toArray(const CodeLoc &codeLoc, int size) const { +SymbolType SymbolType::toArray(const AstNode *node, int size) const { // Do not allow arrays of dyn if (typeChain.top().superType == TY_DYN) - throw SemanticError(codeLoc, DYN_ARRAYS_NOT_ALLOWED, "Just use the dyn type without '[]' instead"); + throw SemanticError(node, DYN_ARRAYS_NOT_ALLOWED, "Just use the dyn type without '[]' instead"); TypeChain newTypeChain = typeChain; newTypeChain.push({TY_ARRAY, "", {.arraySize = size}, {}, nullptr}); diff --git a/src/symbol/SymbolType.h b/src/symbol/SymbolType.h index 02a16d654..c86c1a337 100644 --- a/src/symbol/SymbolType.h +++ b/src/symbol/SymbolType.h @@ -15,7 +15,7 @@ // Forward declarations class SymbolTable; -struct CodeLoc; +struct AstNode; enum SymbolSuperType { TY_INVALID, @@ -89,8 +89,8 @@ class SymbolType { // Public methods [[nodiscard]] TypeChain getTypeChain() const; - SymbolType toPointer(const CodeLoc &codeLoc, llvm::Value *dynamicSize = nullptr) const; - [[nodiscard]] SymbolType toArray(const CodeLoc &codeLoc, int size = 0) const; + SymbolType toPointer(const AstNode *node, llvm::Value *dynamicSize = nullptr) const; + [[nodiscard]] SymbolType toArray(const AstNode *node, int size = 0) const; [[nodiscard]] SymbolType getContainedTy() const; [[nodiscard]] SymbolType replaceBaseSubType(const std::string &newSubType) const; [[nodiscard]] SymbolType replaceBaseType(const SymbolType &newBaseType) const; diff --git a/test/test-files/analyzer/arrays/array-index-not-type-int/exception.out b/test/test-files/analyzer/arrays/array-index-not-type-int/exception.out index cd2f5ddc4..f17ccdbc5 100644 --- a/test/test-files/analyzer/arrays/array-index-not-type-int/exception.out +++ b/test/test-files/analyzer/arrays/array-index-not-type-int/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/arrays/array-index-not-type-int/source.spice:3:30: Array index not of type int or long: Array index must be of type int or long \ No newline at end of file +Semantic error in : ./test-files/analyzer/arrays/array-index-not-type-int/source.spice:3:30: +Array index not of type int or long: Array index must be of type int or long + +3 f("Array item: %d", longArray[1s]); + ^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/arrays/error-array-size-attached/exception.out b/test/test-files/analyzer/arrays/error-array-size-attached/exception.out index 874467c99..9e6d17867 100644 --- a/test/test-files/analyzer/arrays/error-array-size-attached/exception.out +++ b/test/test-files/analyzer/arrays/error-array-size-attached/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/arrays/error-array-size-attached/source.spice:2:5: Array size invalid: The declaration of an array type must have a size attached \ No newline at end of file +Semantic error in : ./test-files/analyzer/arrays/error-array-size-attached/source.spice:2:5: +Array size invalid: The declaration of an array type must have a size attached + +2 double[] doubleArray = { 1.1 + ^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/arrays/error-dyn-arrays/exception.out b/test/test-files/analyzer/arrays/error-dyn-arrays/exception.out index 92e26fcfa..1bdf8fc8e 100644 --- a/test/test-files/analyzer/arrays/error-dyn-arrays/exception.out +++ b/test/test-files/analyzer/arrays/error-dyn-arrays/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/arrays/error-dyn-arrays/source.spice:2:5: Dyn arrays not allowed: Just use the dyn type without '[]' instead \ No newline at end of file +Semantic error in : ./test-files/analyzer/arrays/error-dyn-arrays/source.spice:2:5: +Dyn arrays not allowed: Just use the dyn type without '[]' instead + +2 dyn[] test = { "This", "i + ^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/arrays/error-out-of-bounds/exception.out b/test/test-files/analyzer/arrays/error-out-of-bounds/exception.out index 8008ea862..d015b27aa 100644 --- a/test/test-files/analyzer/arrays/error-out-of-bounds/exception.out +++ b/test/test-files/analyzer/arrays/error-out-of-bounds/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/arrays/error-out-of-bounds/source.spice:3:26: Array index out of bounds: You are trying to access element with index 15 of an array with size 10 \ No newline at end of file +Semantic error in : ./test-files/analyzer/arrays/error-out-of-bounds/source.spice:3:26: +Array index out of bounds: You are trying to access element with index 15 of an array with size 10 + +3 rintf("Test: %d/n", testArray[15]); + ^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/arrays/error-sized-not-matching/exception.out b/test/test-files/analyzer/arrays/error-sized-not-matching/exception.out index 6a1c3d112..cd3e168b3 100644 --- a/test/test-files/analyzer/arrays/error-sized-not-matching/exception.out +++ b/test/test-files/analyzer/arrays/error-sized-not-matching/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/arrays/error-sized-not-matching/source.spice:4:5: Wrong data type for operator: Cannot apply '=' operator on types double[3] and double[2] \ No newline at end of file +Semantic error in : ./test-files/analyzer/arrays/error-sized-not-matching/source.spice:4:5: +Wrong data type for operator: Cannot apply '=' operator on types double[3] and double[2] + +4 double[3] anotherArray = doubleArray; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/arrays/error-type-not-matching/exception.out b/test/test-files/analyzer/arrays/error-type-not-matching/exception.out index ae5a9ba8f..79d5d4e78 100644 --- a/test/test-files/analyzer/arrays/error-type-not-matching/exception.out +++ b/test/test-files/analyzer/arrays/error-type-not-matching/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/arrays/error-type-not-matching/source.spice:2:41: Array item type not matching: All provided values have to be of the same data type. You provided long and bool \ No newline at end of file +Semantic error in : ./test-files/analyzer/arrays/error-type-not-matching/source.spice:2:41: +Array item type not matching: All provided values have to be of the same data type. You provided long and bool + +2 , 2l , 3l, 4l , 5l, false, 7l }; + ^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/assertions/error-assert-condition-bool/exception.out b/test/test-files/analyzer/assertions/error-assert-condition-bool/exception.out index 07b7ea5a6..55a9a37e6 100644 --- a/test/test-files/analyzer/assertions/error-assert-condition-bool/exception.out +++ b/test/test-files/analyzer/assertions/error-assert-condition-bool/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/assertions/error-assert-condition-bool/source.spice:2:12: Assertion condition must be bool: The asserted condition must be of type bool \ No newline at end of file +Semantic error in : ./test-files/analyzer/assertions/error-assert-condition-bool/source.spice:2:12: +Assertion condition must be bool: The asserted condition must be of type bool + +2 assert "Test"; + ^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/builtins/error-printf-too-less-args/exception.out b/test/test-files/analyzer/builtins/error-printf-too-less-args/exception.out index b8f4c9694..16b1623c3 100644 --- a/test/test-files/analyzer/builtins/error-printf-too-less-args/exception.out +++ b/test/test-files/analyzer/builtins/error-printf-too-less-args/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/builtins/error-printf-too-less-args/source.spice:2:5: Printf arg number not matching template string: The placeholder string contains more placeholders that arguments were passed \ No newline at end of file +Semantic error in : ./test-files/analyzer/builtins/error-printf-too-less-args/source.spice:2:5: +Printf arg number not matching template string: The placeholder string contains more placeholders that arguments were passed + +2 printf("Test: %d, %f", 3); + ^^^^^^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/builtins/error-printf-too-many-args/exception.out b/test/test-files/analyzer/builtins/error-printf-too-many-args/exception.out index 854d3df60..799b4ff54 100644 --- a/test/test-files/analyzer/builtins/error-printf-too-many-args/exception.out +++ b/test/test-files/analyzer/builtins/error-printf-too-many-args/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/builtins/error-printf-too-many-args/source.spice:2:5: Printf arg number not matching template string: The placeholder string contains less placeholders that arguments were passed \ No newline at end of file +Semantic error in : ./test-files/analyzer/builtins/error-printf-too-many-args/source.spice:2:5: +Printf arg number not matching template string: The placeholder string contains less placeholders that arguments were passed + +2 printf("Test", 3); + ^^^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/builtins/error-printf-type-incompatibility/exception.out b/test/test-files/analyzer/builtins/error-printf-type-incompatibility/exception.out index b4e9ed089..5d05700a7 100644 --- a/test/test-files/analyzer/builtins/error-printf-type-incompatibility/exception.out +++ b/test/test-files/analyzer/builtins/error-printf-type-incompatibility/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/builtins/error-printf-type-incompatibility/source.spice:6:36: Types of printf call not matching: Template string expects char, but got string \ No newline at end of file +Semantic error in : ./test-files/analyzer/builtins/error-printf-type-incompatibility/source.spice:6:36: +Types of printf call not matching: Template string expects char, but got string + +6 s is a string: %c", "test"); + ^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/builtins/error-printf-wrong-type1/exception.out b/test/test-files/analyzer/builtins/error-printf-wrong-type1/exception.out index d51d71dc7..a17fd664e 100644 --- a/test/test-files/analyzer/builtins/error-printf-wrong-type1/exception.out +++ b/test/test-files/analyzer/builtins/error-printf-wrong-type1/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/builtins/error-printf-wrong-type1/source.spice:2:18: Types of printf call not matching: Template string expects int, byte or bool, but got double \ No newline at end of file +Semantic error in : ./test-files/analyzer/builtins/error-printf-wrong-type1/source.spice:2:18: +Types of printf call not matching: Template string expects int, byte or bool, but got double + +2 printf("%d", 6.23456); + ^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/builtins/error-printf-wrong-type2/exception.out b/test/test-files/analyzer/builtins/error-printf-wrong-type2/exception.out index 24be8fb7c..4d0524915 100644 --- a/test/test-files/analyzer/builtins/error-printf-wrong-type2/exception.out +++ b/test/test-files/analyzer/builtins/error-printf-wrong-type2/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/builtins/error-printf-wrong-type2/source.spice:2:18: Types of printf call not matching: Template string expects double, but got bool \ No newline at end of file +Semantic error in : ./test-files/analyzer/builtins/error-printf-wrong-type2/source.spice:2:18: +Types of printf call not matching: Template string expects double, but got bool + +2 printf("%f", true); + ^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/builtins/error-printf-wrong-type3/exception.out b/test/test-files/analyzer/builtins/error-printf-wrong-type3/exception.out index fed5fe523..03d102141 100644 --- a/test/test-files/analyzer/builtins/error-printf-wrong-type3/exception.out +++ b/test/test-files/analyzer/builtins/error-printf-wrong-type3/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/builtins/error-printf-wrong-type3/source.spice:3:18: Types of printf call not matching: Template string expects string, but got int* \ No newline at end of file +Semantic error in : ./test-files/analyzer/builtins/error-printf-wrong-type3/source.spice:3:18: +Types of printf call not matching: Template string expects string, but got int* + +3 printf("%s", &integer); + ^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/builtins/error-printf-wrong-type4/exception.out b/test/test-files/analyzer/builtins/error-printf-wrong-type4/exception.out index bb1d2c499..aaafb2b90 100644 --- a/test/test-files/analyzer/builtins/error-printf-wrong-type4/exception.out +++ b/test/test-files/analyzer/builtins/error-printf-wrong-type4/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/builtins/error-printf-wrong-type4/source.spice:5:18: Types of printf call not matching: Template string expects pointer, but got NotAPointer \ No newline at end of file +Semantic error in : ./test-files/analyzer/builtins/error-printf-wrong-type4/source.spice:5:18: +Types of printf call not matching: Template string expects pointer, but got NotAPointer + +5 printf("%p", nonPtr); + ^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/builtins/error-sizeof-dyn-size-array/exception.out b/test/test-files/analyzer/builtins/error-sizeof-dyn-size-array/exception.out index 6aab87d71..53ed0150f 100644 --- a/test/test-files/analyzer/builtins/error-sizeof-dyn-size-array/exception.out +++ b/test/test-files/analyzer/builtins/error-sizeof-dyn-size-array/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/builtins/error-sizeof-dyn-size-array/source.spice:4:18: Sizeof dynamically sized array: Cannot get sizeof dynamically sized array at compile time \ No newline at end of file +Semantic error in : ./test-files/analyzer/builtins/error-sizeof-dyn-size-array/source.spice:4:18: +Sizeof dynamically sized array: Cannot get sizeof dynamically sized array at compile time + +4 printf("%d", sizeof(array)); + ^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/builtins/error-sizeof-expected-type/exception.out b/test/test-files/analyzer/builtins/error-sizeof-expected-type/exception.out index 7ad1eaa19..e29213de9 100644 --- a/test/test-files/analyzer/builtins/error-sizeof-expected-type/exception.out +++ b/test/test-files/analyzer/builtins/error-sizeof-expected-type/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/builtins/error-sizeof-expected-type/source.spice:3:36: Expected type: Expected type, but got double \ No newline at end of file +Semantic error in : ./test-files/analyzer/builtins/error-sizeof-expected-type/source.spice:3:36: +Expected type: Expected type, but got double + +3 e: %d", sizeof(type doubleValue)); + ^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/builtins/error-sizeof-expected-value/exception.out b/test/test-files/analyzer/builtins/error-sizeof-expected-value/exception.out index 0e4e17436..06e7492c3 100644 --- a/test/test-files/analyzer/builtins/error-sizeof-expected-value/exception.out +++ b/test/test-files/analyzer/builtins/error-sizeof-expected-value/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/builtins/error-sizeof-expected-value/source.spice:4:31: Referenced undefined variable: Variable 'T' was referenced before declared \ No newline at end of file +Semantic error in : ./test-files/analyzer/builtins/error-sizeof-expected-value/source.spice:4:31: +Referenced undefined variable: Variable 'T' was referenced before declared + +4 ("Size: %d", sizeof(T)); + ^ \ No newline at end of file diff --git a/test/test-files/analyzer/coming-soon/error-coming-soon1/exception.out b/test/test-files/analyzer/coming-soon/error-coming-soon1/exception.out index e988cacab..769bb9862 100644 --- a/test/test-files/analyzer/coming-soon/error-coming-soon1/exception.out +++ b/test/test-files/analyzer/coming-soon/error-coming-soon1/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/coming-soon/error-coming-soon1/source.spice:1:1: Coming soon: Spice currently not supports pointer return types due to not handling pointer escaping. \ No newline at end of file +Semantic error in : ./test-files/analyzer/coming-soon/error-coming-soon1/source.spice:1:1: +Coming soon: Spice currently not supports pointer return types due to not handling pointer escaping. + +1 f escapingFunction(int arg) { + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/enums/error-duplicate-item-name/exception.out b/test/test-files/analyzer/enums/error-duplicate-item-name/exception.out index 10156c16b..126c20d81 100644 --- a/test/test-files/analyzer/enums/error-duplicate-item-name/exception.out +++ b/test/test-files/analyzer/enums/error-duplicate-item-name/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/enums/error-duplicate-item-name/source.spice:4:5: Duplicate enum item name: Duplicate enum item name, please use another \ No newline at end of file +Semantic error in : ./test-files/analyzer/enums/error-duplicate-item-name/source.spice:4:5: +Duplicate enum item name: Duplicate enum item name, please use another + +4 ITEM_NAME + ^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/enums/error-duplicate-item-value/exception.out b/test/test-files/analyzer/enums/error-duplicate-item-value/exception.out index bb389cd54..05c7c88c5 100644 --- a/test/test-files/analyzer/enums/error-duplicate-item-value/exception.out +++ b/test/test-files/analyzer/enums/error-duplicate-item-value/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/enums/error-duplicate-item-value/source.spice:3:5: Duplicate enum item value: Duplicate enum item value, please use another \ No newline at end of file +Semantic error in : ./test-files/analyzer/enums/error-duplicate-item-value/source.spice:3:5: +Duplicate enum item value: Duplicate enum item value, please use another + +3 ITEM_NAME2 = 1, + ^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/for-loops/error-for-condition-bool/exception.out b/test/test-files/analyzer/for-loops/error-for-condition-bool/exception.out index 44d1258d3..0cf2de0ea 100644 --- a/test/test-files/analyzer/for-loops/error-for-condition-bool/exception.out +++ b/test/test-files/analyzer/for-loops/error-for-condition-bool/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/for-loops/error-for-condition-bool/source.spice:2:20: Condition must be bool: For loop condition must be of type bool \ No newline at end of file +Semantic error in : ./test-files/analyzer/for-loops/error-for-condition-bool/source.spice:2:20: +Condition must be bool: For loop condition must be of type bool + +2 for int i = 0; "No bool"; i++ { + ^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/foreach-loops/error-foreach-wrong-array-type/exception.out b/test/test-files/analyzer/foreach-loops/error-foreach-wrong-array-type/exception.out index c1d2414b5..ea64798df 100644 --- a/test/test-files/analyzer/foreach-loops/error-foreach-wrong-array-type/exception.out +++ b/test/test-files/analyzer/foreach-loops/error-foreach-wrong-array-type/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/foreach-loops/error-foreach-wrong-array-type/source.spice:3:27: Wrong data type for operator: Can only apply foreach loop on an array type. You provided bool \ No newline at end of file +Semantic error in : ./test-files/analyzer/foreach-loops/error-foreach-wrong-array-type/source.spice:3:27: +Wrong data type for operator: Can only apply foreach loop on an array type. You provided bool + +3 reach string item : b { + ^ \ No newline at end of file diff --git a/test/test-files/analyzer/foreach-loops/error-foreach-wrong-index-type/exception.out b/test/test-files/analyzer/foreach-loops/error-foreach-wrong-index-type/exception.out index c9b73c950..b147f8a75 100644 --- a/test/test-files/analyzer/foreach-loops/error-foreach-wrong-index-type/exception.out +++ b/test/test-files/analyzer/foreach-loops/error-foreach-wrong-index-type/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/foreach-loops/error-foreach-wrong-index-type/source.spice:3:13: Array index not of type int or long: Index in foreach loop must be of type int. You provided double \ No newline at end of file +Semantic error in : ./test-files/analyzer/foreach-loops/error-foreach-wrong-index-type/source.spice:3:13: +Array index not of type int or long: Index in foreach loop must be of type int. You provided double + +3 foreach double i, int item : array { + ^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/foreach-loops/error-foreach-wrong-item-type/exception.out b/test/test-files/analyzer/foreach-loops/error-foreach-wrong-item-type/exception.out index 5dbd2b321..1e3835818 100644 --- a/test/test-files/analyzer/foreach-loops/error-foreach-wrong-item-type/exception.out +++ b/test/test-files/analyzer/foreach-loops/error-foreach-wrong-item-type/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/foreach-loops/error-foreach-wrong-item-type/source.spice:3:13: Wrong data type for operator: Foreach loop item type does not match array type. Expected int[], provided double \ No newline at end of file +Semantic error in : ./test-files/analyzer/foreach-loops/error-foreach-wrong-item-type/source.spice:3:13: +Wrong data type for operator: Foreach loop item type does not match array type. Expected int[], provided double + +3 foreach double item : array { + ^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/function-calls/error-cannot-call-variables/exception.out b/test/test-files/analyzer/function-calls/error-cannot-call-variables/exception.out index c30f532b3..bae72ec01 100644 --- a/test/test-files/analyzer/function-calls/error-cannot-call-variables/exception.out +++ b/test/test-files/analyzer/function-calls/error-cannot-call-variables/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/function-calls/error-cannot-call-variables/source.spice:3:22: Referenced undefined function: Function/Procedure 'variable()' could not be found \ No newline at end of file +Semantic error in : ./test-files/analyzer/function-calls/error-cannot-call-variables/source.spice:3:22: +Referenced undefined function: Function/Procedure 'variable()' could not be found + +3 int calcResult = variable(); + ^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/functions/error-duplicate-function-def/exception.out b/test/test-files/analyzer/functions/error-duplicate-function-def/exception.out index a2993045e..fb9a6b1f4 100644 --- a/test/test-files/analyzer/functions/error-duplicate-function-def/exception.out +++ b/test/test-files/analyzer/functions/error-duplicate-function-def/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/functions/error-duplicate-function-def/source.spice:5:1: Multiple declarations of a function/procedure: The function/procedure 'exampleFunc(): string' is declared twice \ No newline at end of file +Semantic error in : ./test-files/analyzer/functions/error-duplicate-function-def/source.spice:5:1: +Multiple declarations of a function/procedure: The function/procedure 'exampleFunc(): string' is declared twice + +5 f exampleFunc() { + ^^^^^^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/functions/error-duplicate-main-function-def/exception.out b/test/test-files/analyzer/functions/error-duplicate-main-function-def/exception.out index 274f397ef..ab54f6929 100644 --- a/test/test-files/analyzer/functions/error-duplicate-main-function-def/exception.out +++ b/test/test-files/analyzer/functions/error-duplicate-main-function-def/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/functions/error-duplicate-main-function-def/source.spice:5:1: Multiple declarations of a function/procedure: Main function is declared twice \ No newline at end of file +Semantic error in : ./test-files/analyzer/functions/error-duplicate-main-function-def/source.spice:5:1: +Multiple declarations of a function/procedure: Main function is declared twice + +5 f main() { + ^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/functions/error-ext-dyn-arg/exception.out b/test/test-files/analyzer/functions/error-ext-dyn-arg/exception.out index 341773071..e200aa871 100644 --- a/test/test-files/analyzer/functions/error-ext-dyn-arg/exception.out +++ b/test/test-files/analyzer/functions/error-ext-dyn-arg/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/functions/error-ext-dyn-arg/source.spice:1:26: Unexpected dyn type: Dyn data type is not allowed as arg type for external functions \ No newline at end of file +Semantic error in : ./test-files/analyzer/functions/error-ext-dyn-arg/source.spice:1:26: +Unexpected dyn type: Dyn data type is not allowed as arg type for external functions + +1 nt> exteralFunction(dyn, int); + ^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/functions/error-ext-dyn-return/exception.out b/test/test-files/analyzer/functions/error-ext-dyn-return/exception.out index 4d915cfa4..7058c3803 100644 --- a/test/test-files/analyzer/functions/error-ext-dyn-return/exception.out +++ b/test/test-files/analyzer/functions/error-ext-dyn-return/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/functions/error-ext-dyn-return/source.spice:1:5: Unexpected dyn type: Dyn data type is not allowed as return type for external functions \ No newline at end of file +Semantic error in : ./test-files/analyzer/functions/error-ext-dyn-return/source.spice:1:5: +Unexpected dyn type: Dyn data type is not allowed as return type for external functions + +1 ext exteralFunction(); + ^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/functions/error-function-arg-decl-type-dyn/exception.out b/test/test-files/analyzer/functions/error-function-arg-decl-type-dyn/exception.out index c9fd4fc61..e8366b522 100644 --- a/test/test-files/analyzer/functions/error-function-arg-decl-type-dyn/exception.out +++ b/test/test-files/analyzer/functions/error-function-arg-decl-type-dyn/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/functions/error-function-arg-decl-type-dyn/source.spice:1:21: Parameter type dyn not valid in function/procedure definition without default value: Type of parameter 'arg2' is invalid \ No newline at end of file +Semantic error in : ./test-files/analyzer/functions/error-function-arg-decl-type-dyn/source.spice:1:21: +Parameter type dyn not valid in function/procedure definition without default value: Type of parameter 'arg2' is invalid + +1 f testFunction(int arg0, dyn arg1 = "value", dyn arg2) { + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/functions/error-function-arg-types-match-declaration/exception.out b/test/test-files/analyzer/functions/error-function-arg-types-match-declaration/exception.out index 166837f9a..bc3e78ed5 100644 --- a/test/test-files/analyzer/functions/error-function-arg-types-match-declaration/exception.out +++ b/test/test-files/analyzer/functions/error-function-arg-types-match-declaration/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/functions/error-function-arg-types-match-declaration/source.spice:6:5: Referenced undefined function: Function/Procedure 'testFunction(string)' could not be found \ No newline at end of file +Semantic error in : ./test-files/analyzer/functions/error-function-arg-types-match-declaration/source.spice:6:5: +Referenced undefined function: Function/Procedure 'testFunction(string)' could not be found + +6 testFunction("No double"); + ^^^^^^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/functions/error-function-args-match-declaration/exception.out b/test/test-files/analyzer/functions/error-function-args-match-declaration/exception.out index 82b384b67..d8d5ab201 100644 --- a/test/test-files/analyzer/functions/error-function-args-match-declaration/exception.out +++ b/test/test-files/analyzer/functions/error-function-args-match-declaration/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/functions/error-function-args-match-declaration/source.spice:6:5: Referenced undefined function: Function/Procedure 'testFunction()' could not be found \ No newline at end of file +Semantic error in : ./test-files/analyzer/functions/error-function-args-match-declaration/source.spice:6:5: +Referenced undefined function: Function/Procedure 'testFunction()' could not be found + +6 testFunction(); + ^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/functions/error-function-dyn-return/exception.out b/test/test-files/analyzer/functions/error-function-dyn-return/exception.out index a436f73e9..5a0ae8f6f 100644 --- a/test/test-files/analyzer/functions/error-function-dyn-return/exception.out +++ b/test/test-files/analyzer/functions/error-function-dyn-return/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/functions/error-function-dyn-return/source.spice:1:1: Unexpected dyn type: Dyn return types are not allowed \ No newline at end of file +Semantic error in : ./test-files/analyzer/functions/error-function-dyn-return/source.spice:1:1: +Unexpected dyn type: Dyn return types are not allowed + +1 f test() { + ^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/functions/error-function-without-return/exception.out b/test/test-files/analyzer/functions/error-function-without-return/exception.out index 9e33c6d1f..071bbd029 100644 --- a/test/test-files/analyzer/functions/error-function-without-return/exception.out +++ b/test/test-files/analyzer/functions/error-function-without-return/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/functions/error-function-without-return/source.spice:1:1: Missing return statement: Function without return statement \ No newline at end of file +Semantic error in : ./test-files/analyzer/functions/error-function-without-return/source.spice:1:1: +Missing return statement: Function without return statement + +1 f isValid(int input = 12) { + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/functions/error-mandatory-after-optional-arg/exception.out b/test/test-files/analyzer/functions/error-mandatory-after-optional-arg/exception.out index eac195351..ee6141ed5 100644 --- a/test/test-files/analyzer/functions/error-mandatory-after-optional-arg/exception.out +++ b/test/test-files/analyzer/functions/error-mandatory-after-optional-arg/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/functions/error-mandatory-after-optional-arg/source.spice:1:28: Invalid argument order: Mandatory parameters must go before any optional parameters \ No newline at end of file +Semantic error in : ./test-files/analyzer/functions/error-mandatory-after-optional-arg/source.spice:1:28: +Invalid argument order: Mandatory parameters must go before any optional parameters + +1 testFunc(int i = 5, int j) { + ^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/functions/error-must-contain-main-function/exception.out b/test/test-files/analyzer/functions/error-must-contain-main-function/exception.out index 6678bb8b6..4d8ec89d8 100644 --- a/test/test-files/analyzer/functions/error-must-contain-main-function/exception.out +++ b/test/test-files/analyzer/functions/error-must-contain-main-function/exception.out @@ -1 +1,3 @@ -Semantic error in ./test-files/analyzer/functions/error-must-contain-main-function/source.spice:1:1: Spice programs must contain a main function: No main function found \ No newline at end of file +Semantic error in : ./test-files/analyzer/functions/error-must-contain-main-function/source.spice:1:1: +Spice programs must contain a main function: No main function found + diff --git a/test/test-files/analyzer/functions/error-return-type-matches-def/exception.out b/test/test-files/analyzer/functions/error-return-type-matches-def/exception.out index e04f53111..a5373283a 100644 --- a/test/test-files/analyzer/functions/error-return-type-matches-def/exception.out +++ b/test/test-files/analyzer/functions/error-return-type-matches-def/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/functions/error-return-type-matches-def/source.spice:2:12: Wrong data type for operator: Passed wrong data type to return statement. Expected string but got int \ No newline at end of file +Semantic error in : ./test-files/analyzer/functions/error-return-type-matches-def/source.spice:2:12: +Wrong data type for operator: Passed wrong data type to return statement. Expected string but got int + +2 return 7; + ^ \ No newline at end of file diff --git a/test/test-files/analyzer/functions/error-return-without-value-result/exception.out b/test/test-files/analyzer/functions/error-return-without-value-result/exception.out index a70859fa0..100ef247a 100644 --- a/test/test-files/analyzer/functions/error-return-without-value-result/exception.out +++ b/test/test-files/analyzer/functions/error-return-without-value-result/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/functions/error-return-without-value-result/source.spice:4:9: Return without initialization of result variable: Return without value, but result variable is not initialized yet \ No newline at end of file +Semantic error in : ./test-files/analyzer/functions/error-return-without-value-result/source.spice:4:9: +Return without initialization of result variable: Return without value, but result variable is not initialized yet + +4 return; + ^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/functions/errror-function-param-dyn-sized/exception.out b/test/test-files/analyzer/functions/errror-function-param-dyn-sized/exception.out index 3685d09a0..70d23460f 100644 --- a/test/test-files/analyzer/functions/errror-function-param-dyn-sized/exception.out +++ b/test/test-files/analyzer/functions/errror-function-param-dyn-sized/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/functions/errror-function-param-dyn-sized/source.spice:3:9: Array size invalid: Types in parameter lists may not be dynamically sized \ No newline at end of file +Semantic error in : ./test-files/analyzer/functions/errror-function-param-dyn-sized/source.spice:3:9: +Array size invalid: Types in parameter lists may not be dynamically sized + +3 p print(int[SIZE][SIZE] grid) { + ^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/generics/error-failing-type-condition/exception.out b/test/test-files/analyzer/generics/error-failing-type-condition/exception.out index a55102079..85c9a5982 100644 --- a/test/test-files/analyzer/generics/error-failing-type-condition/exception.out +++ b/test/test-files/analyzer/generics/error-failing-type-condition/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/generics/error-failing-type-condition/source.spice:8:16: Referenced undefined function: Function/Procedure 'max(short,short)' could not be found \ No newline at end of file +Semantic error in : ./test-files/analyzer/generics/error-failing-type-condition/source.spice:8:16: +Referenced undefined function: Function/Procedure 'max(short,short)' could not be found + +8 dyn test = max(1s, 2s); + ^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/generics/error-generic-function-not-found/exception.out b/test/test-files/analyzer/generics/error-generic-function-not-found/exception.out index a1a346c67..7b1832899 100644 --- a/test/test-files/analyzer/generics/error-generic-function-not-found/exception.out +++ b/test/test-files/analyzer/generics/error-generic-function-not-found/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/generics/error-generic-function-not-found/source.spice:7:5: Referenced undefined function: Function/Procedure 's1.Vector.setData(double)' could not be found \ No newline at end of file +Semantic error in : ./test-files/analyzer/generics/error-generic-function-not-found/source.spice:7:5: +Referenced undefined function: Function/Procedure 's1.Vector.setData(double)' could not be found + +7 v.setData(1.5); + ^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/generics/error-generic-type-check/exception.out b/test/test-files/analyzer/generics/error-generic-type-check/exception.out index 0b3dbc81b..bc48acd47 100644 --- a/test/test-files/analyzer/generics/error-generic-type-check/exception.out +++ b/test/test-files/analyzer/generics/error-generic-type-check/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/generics/error-generic-type-check/source.spice:4:18: Types of printf call not matching: Template string expects int, byte or bool, but got string \ No newline at end of file +Semantic error in : ./test-files/analyzer/generics/error-generic-type-check/source.spice:4:18: +Types of printf call not matching: Template string expects int, byte or bool, but got string + +4 printf("%d", g); + ^ \ No newline at end of file diff --git a/test/test-files/analyzer/generics/error-not-in-template1/exception.out b/test/test-files/analyzer/generics/error-not-in-template1/exception.out index bb348ee92..b5433eb2d 100644 --- a/test/test-files/analyzer/generics/error-not-in-template1/exception.out +++ b/test/test-files/analyzer/generics/error-not-in-template1/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/generics/error-not-in-template1/source.spice:4:16: Generic type not contained in template: Generic arg type not included in function template \ No newline at end of file +Semantic error in : ./test-files/analyzer/generics/error-not-in-template1/source.spice:4:16: +Generic type not contained in template: Generic arg type not included in function template + +4 f getDyn(T a1, U a2) { + ^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/generics/error-not-in-template2/exception.out b/test/test-files/analyzer/generics/error-not-in-template2/exception.out index caa13e2ab..bd823cf1d 100644 --- a/test/test-files/analyzer/generics/error-not-in-template2/exception.out +++ b/test/test-files/analyzer/generics/error-not-in-template2/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/generics/error-not-in-template2/source.spice:4:15: Generic type not contained in template: Generic arg type not included in procedure template \ No newline at end of file +Semantic error in : ./test-files/analyzer/generics/error-not-in-template2/source.spice:4:15: +Generic type not contained in template: Generic arg type not included in procedure template + +4 p printDyn(T a1, U a2) { + ^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/generics/error-not-in-template3/exception.out b/test/test-files/analyzer/generics/error-not-in-template3/exception.out index de7c37159..47330f38a 100644 --- a/test/test-files/analyzer/generics/error-not-in-template3/exception.out +++ b/test/test-files/analyzer/generics/error-not-in-template3/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/generics/error-not-in-template3/source.spice:4:5: Generic type not contained in template: Generic field type not included in struct template \ No newline at end of file +Semantic error in : ./test-files/analyzer/generics/error-not-in-template3/source.spice:4:5: +Generic type not contained in template: Generic field type not included in struct template + +4 T genericField + ^ \ No newline at end of file diff --git a/test/test-files/analyzer/if-stmts/error-else-if-condition-bool/exception.out b/test/test-files/analyzer/if-stmts/error-else-if-condition-bool/exception.out index ab3c82ba6..357fce160 100644 --- a/test/test-files/analyzer/if-stmts/error-else-if-condition-bool/exception.out +++ b/test/test-files/analyzer/if-stmts/error-else-if-condition-bool/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/if-stmts/error-else-if-condition-bool/source.spice:4:15: Condition must be bool: If condition must be of type bool \ No newline at end of file +Semantic error in : ./test-files/analyzer/if-stmts/error-else-if-condition-bool/source.spice:4:15: +Condition must be bool: If condition must be of type bool + +4 } else if "not a bool" { + ^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/if-stmts/error-if-condition-bool/exception.out b/test/test-files/analyzer/if-stmts/error-if-condition-bool/exception.out index e22339dfa..afd2ccce9 100644 --- a/test/test-files/analyzer/if-stmts/error-if-condition-bool/exception.out +++ b/test/test-files/analyzer/if-stmts/error-if-condition-bool/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/if-stmts/error-if-condition-bool/source.spice:2:8: Condition must be bool: If condition must be of type bool \ No newline at end of file +Semantic error in : ./test-files/analyzer/if-stmts/error-if-condition-bool/source.spice:2:8: +Condition must be bool: If condition must be of type bool + +2 if 7 { + ^ \ No newline at end of file diff --git a/test/test-files/analyzer/imports/error-circular-import/exception.out b/test/test-files/analyzer/imports/error-circular-import/exception.out index 67ef36820..c670d8971 100644 --- a/test/test-files/analyzer/imports/error-circular-import/exception.out +++ b/test/test-files/analyzer/imports/error-circular-import/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/imports/error-circular-import/source2.spice:1:1: Circular import detected: Circular import detected while importing './test-files/analyzer/imports/error-circular-import/source.spice' \ No newline at end of file +Semantic error in : ./test-files/analyzer/imports/error-circular-import/source2.spice:1:1: +Circular import detected: Circular import detected while importing './test-files/analyzer/imports/error-circular-import/source.spice' + +1 import "source" as s; + ^^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/imports/error-imported-file-not-existing/exception.out b/test/test-files/analyzer/imports/error-imported-file-not-existing/exception.out index 660baafda..1492cbe1d 100644 --- a/test/test-files/analyzer/imports/error-imported-file-not-existing/exception.out +++ b/test/test-files/analyzer/imports/error-imported-file-not-existing/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/imports/error-imported-file-not-existing/source.spice:1:1: Imported source file not existing: The source file 'source2.spice' does not exist \ No newline at end of file +Semantic error in : ./test-files/analyzer/imports/error-imported-file-not-existing/source.spice:1:1: +Imported source file not existing: The source file 'source2.spice' does not exist + +1 import "source2" as s2; + ^^^^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/imports/error-imported-std-not-existing/exception.out b/test/test-files/analyzer/imports/error-imported-std-not-existing/exception.out index 04845ea40..7f0304914 100644 --- a/test/test-files/analyzer/imports/error-imported-std-not-existing/exception.out +++ b/test/test-files/analyzer/imports/error-imported-std-not-existing/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/imports/error-imported-std-not-existing/source.spice:1:1: Imported source file not existing: The source file 'std/non-existing/foo.spice' was not found in the standard library \ No newline at end of file +Semantic error in : ./test-files/analyzer/imports/error-imported-std-not-existing/source.spice:1:1: +Imported source file not existing: The source file 'std/non-existing/foo.spice' was not found in the standard library + +1 import "std/non-existing/foo" as foo; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/imports/error-insufficient-function-visibility/exception.out b/test/test-files/analyzer/imports/error-insufficient-function-visibility/exception.out index ae6f1945b..8b4c7555c 100644 --- a/test/test-files/analyzer/imports/error-insufficient-function-visibility/exception.out +++ b/test/test-files/analyzer/imports/error-insufficient-function-visibility/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/imports/error-insufficient-function-visibility/source.spice:4:15: Insufficient symbol visibility: Cannot access function/procedure 'testFunc(): int' due to its private visibility \ No newline at end of file +Semantic error in : ./test-files/analyzer/imports/error-insufficient-function-visibility/source.spice:4:15: +Insufficient symbol visibility: Cannot access function/procedure 'testFunc(): int' due to its private visibility + +4 int res = src1.testFunc(); + ^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/imports/error-insufficient-global-var-visibility/exception.out b/test/test-files/analyzer/imports/error-insufficient-global-var-visibility/exception.out index 37998092c..56055cc93 100644 --- a/test/test-files/analyzer/imports/error-insufficient-global-var-visibility/exception.out +++ b/test/test-files/analyzer/imports/error-insufficient-global-var-visibility/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/imports/error-insufficient-global-var-visibility/source.spice:4:34: Insufficient symbol visibility: Cannot access 'globalTestVar' due to its private visibility \ No newline at end of file +Semantic error in : ./test-files/analyzer/imports/error-insufficient-global-var-visibility/source.spice:4:34: +Insufficient symbol visibility: Cannot access 'globalTestVar' due to its private visibility + +4 esult: %d/n", src1::globalTestVar); + ^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/imports/error-insufficient-struct-visibility/exception.out b/test/test-files/analyzer/imports/error-insufficient-struct-visibility/exception.out index 02c5bd94f..716c1bcc2 100644 --- a/test/test-files/analyzer/imports/error-insufficient-struct-visibility/exception.out +++ b/test/test-files/analyzer/imports/error-insufficient-struct-visibility/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/imports/error-insufficient-struct-visibility/source.spice:5:28: Insufficient symbol visibility: Cannot access 's1.Vector' due to its private visibility \ No newline at end of file +Semantic error in : ./test-files/analyzer/imports/error-insufficient-struct-visibility/source.spice:5:28: +Insufficient symbol visibility: Cannot access 's1.Vector' due to its private visibility + +5 ntf("Result: %d/n", s.i); + ^ \ No newline at end of file diff --git a/test/test-files/analyzer/loop-control-insts/error-break-count-invalid/exception.out b/test/test-files/analyzer/loop-control-insts/error-break-count-invalid/exception.out index 249078a03..370d1170d 100644 --- a/test/test-files/analyzer/loop-control-insts/error-break-count-invalid/exception.out +++ b/test/test-files/analyzer/loop-control-insts/error-break-count-invalid/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/loop-control-insts/error-break-count-invalid/source.spice:3:9: Invalid number of break calls: Break count must be >= 1, you provided 0 \ No newline at end of file +Semantic error in : ./test-files/analyzer/loop-control-insts/error-break-count-invalid/source.spice:3:9: +Invalid number of break calls: Break count must be >= 1, you provided 0 + +3 break 0; + ^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/loop-control-insts/error-break-count-not-too-high/exception.out b/test/test-files/analyzer/loop-control-insts/error-break-count-not-too-high/exception.out index 1614cc41c..70bc1105c 100644 --- a/test/test-files/analyzer/loop-control-insts/error-break-count-not-too-high/exception.out +++ b/test/test-files/analyzer/loop-control-insts/error-break-count-not-too-high/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/loop-control-insts/error-break-count-not-too-high/source.spice:7:17: Invalid number of break calls: We can only break 2 time(s) here \ No newline at end of file +Semantic error in : ./test-files/analyzer/loop-control-insts/error-break-count-not-too-high/source.spice:7:17: +Invalid number of break calls: We can only break 2 time(s) here + +7 break 4; + ^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/loop-control-insts/error-continue-count-invalid/exception.out b/test/test-files/analyzer/loop-control-insts/error-continue-count-invalid/exception.out index 01bd78700..6def1b361 100644 --- a/test/test-files/analyzer/loop-control-insts/error-continue-count-invalid/exception.out +++ b/test/test-files/analyzer/loop-control-insts/error-continue-count-invalid/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/loop-control-insts/error-continue-count-invalid/source.spice:3:9: Invalid number of continue calls: Continue count must be >= 1, you provided 0 \ No newline at end of file +Semantic error in : ./test-files/analyzer/loop-control-insts/error-continue-count-invalid/source.spice:3:9: +Invalid number of continue calls: Continue count must be >= 1, you provided 0 + +3 continue 0; + ^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/loop-control-insts/error-continue-count-not-too-high/exception.out b/test/test-files/analyzer/loop-control-insts/error-continue-count-not-too-high/exception.out index cbddeaf82..f2638014f 100644 --- a/test/test-files/analyzer/loop-control-insts/error-continue-count-not-too-high/exception.out +++ b/test/test-files/analyzer/loop-control-insts/error-continue-count-not-too-high/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/loop-control-insts/error-continue-count-not-too-high/source.spice:7:17: Invalid number of continue calls: We can only continue 2 time(s) here \ No newline at end of file +Semantic error in : ./test-files/analyzer/loop-control-insts/error-continue-count-not-too-high/source.spice:7:17: +Invalid number of continue calls: We can only continue 2 time(s) here + +7 continue 3; + ^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/methods/error-destructor-is-function/exception.out b/test/test-files/analyzer/methods/error-destructor-is-function/exception.out index caa318f66..c2ad82b6a 100644 --- a/test/test-files/analyzer/methods/error-destructor-is-function/exception.out +++ b/test/test-files/analyzer/methods/error-destructor-is-function/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/methods/error-destructor-is-function/source.spice:5:1: Destructor must be a procedure: Destructors are not allowed to be of type function \ No newline at end of file +Semantic error in : ./test-files/analyzer/methods/error-destructor-is-function/source.spice:5:1: +Destructor must be a procedure: Destructors are not allowed to be of type function + +5 f TestStruct.dtor() { + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/methods/error-destructor-with-args/exception.out b/test/test-files/analyzer/methods/error-destructor-with-args/exception.out index d317f31e1..889f90b81 100644 --- a/test/test-files/analyzer/methods/error-destructor-with-args/exception.out +++ b/test/test-files/analyzer/methods/error-destructor-with-args/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/methods/error-destructor-with-args/source.spice:5:1: Destructors must not have parameters: It is not allowed to specify parameters for destructors \ No newline at end of file +Semantic error in : ./test-files/analyzer/methods/error-destructor-with-args/source.spice:5:1: +Destructors must not have parameters: It is not allowed to specify parameters for destructors + +5 p TestStruct.dtor(int test) { + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/methods/error-field-without-this/exception.out b/test/test-files/analyzer/methods/error-field-without-this/exception.out index 559d8cc6c..35bf4bddc 100644 --- a/test/test-files/analyzer/methods/error-field-without-this/exception.out +++ b/test/test-files/analyzer/methods/error-field-without-this/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/methods/error-field-without-this/source.spice:13:18: Referenced undefined variable: The symbol 'size' could not be found. Missing 'this.' prefix? \ No newline at end of file +Semantic error in : ./test-files/analyzer/methods/error-field-without-this/source.spice:13:18: +Referenced undefined variable: The symbol 'size' could not be found. Missing 'this.' prefix? + +13 if (index <= size) { // size instead + ^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/methods/error-method-before-struct/exception.out b/test/test-files/analyzer/methods/error-method-before-struct/exception.out index a0f7b366a..7b9fc8451 100644 --- a/test/test-files/analyzer/methods/error-method-before-struct/exception.out +++ b/test/test-files/analyzer/methods/error-method-before-struct/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/methods/error-method-before-struct/source.spice:1:1: Referenced undefined struct: Struct 'Vec' could not be found \ No newline at end of file +Semantic error in : ./test-files/analyzer/methods/error-method-before-struct/source.spice:1:1: +Referenced undefined struct: Struct 'Vec' could not be found + +1 public p Vec.print() { + ^^^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/methods/error-method-not-existing/exception.out b/test/test-files/analyzer/methods/error-method-not-existing/exception.out index adc776163..dbf028b9d 100644 --- a/test/test-files/analyzer/methods/error-method-not-existing/exception.out +++ b/test/test-files/analyzer/methods/error-method-not-existing/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/methods/error-method-not-existing/source.spice:12:14: Referenced undefined function: Function/Procedure 'Test.getInt()' could not be found \ No newline at end of file +Semantic error in : ./test-files/analyzer/methods/error-method-not-existing/source.spice:12:14: +Referenced undefined function: Function/Procedure 'Test.getInt()' could not be found + +12 result = test.getInt(); + ^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/operators/error-additive-operators-some-combinations/exception.out b/test/test-files/analyzer/operators/error-additive-operators-some-combinations/exception.out index ba21041c6..c67b64703 100644 --- a/test/test-files/analyzer/operators/error-additive-operators-some-combinations/exception.out +++ b/test/test-files/analyzer/operators/error-additive-operators-some-combinations/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/operators/error-additive-operators-some-combinations/source.spice:2:29: Wrong data type for operator: Cannot apply '+' operator on types bool and string \ No newline at end of file +Semantic error in : ./test-files/analyzer/operators/error-additive-operators-some-combinations/source.spice:2:29: +Wrong data type for operator: Cannot apply '+' operator on types bool and string + +2 calcResult = true + "test"; + ^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/operators/error-assignment-same-type/exception.out b/test/test-files/analyzer/operators/error-assignment-same-type/exception.out index 8978fa766..63958a949 100644 --- a/test/test-files/analyzer/operators/error-assignment-same-type/exception.out +++ b/test/test-files/analyzer/operators/error-assignment-same-type/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/operators/error-assignment-same-type/source.spice:2:5: Wrong data type for operator: Cannot apply '=' operator on types int and string \ No newline at end of file +Semantic error in : ./test-files/analyzer/operators/error-assignment-same-type/source.spice:2:5: +Wrong data type for operator: Cannot apply '=' operator on types int and string + +2 int test = "Test"; + ^^^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/operators/error-bitwise-operators-are-booleans-or-integers/exception.out b/test/test-files/analyzer/operators/error-bitwise-operators-are-booleans-or-integers/exception.out index 5299e7fa6..02b30776f 100644 --- a/test/test-files/analyzer/operators/error-bitwise-operators-are-booleans-or-integers/exception.out +++ b/test/test-files/analyzer/operators/error-bitwise-operators-are-booleans-or-integers/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/operators/error-bitwise-operators-are-booleans-or-integers/source.spice:2:22: Wrong data type for operator: Cannot apply '|' operator on types string and int \ No newline at end of file +Semantic error in : ./test-files/analyzer/operators/error-bitwise-operators-are-booleans-or-integers/source.spice:2:22: +Wrong data type for operator: Cannot apply '|' operator on types string and int + +2 int calcResult = "test" | 6; + ^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/operators/error-equality-operators-some-combinations/exception.out b/test/test-files/analyzer/operators/error-equality-operators-some-combinations/exception.out index 82cea5f24..fed1640af 100644 --- a/test/test-files/analyzer/operators/error-equality-operators-some-combinations/exception.out +++ b/test/test-files/analyzer/operators/error-equality-operators-some-combinations/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/operators/error-equality-operators-some-combinations/source.spice:2:9: Wrong data type for operator: Cannot apply '==' operator on types string and double \ No newline at end of file +Semantic error in : ./test-files/analyzer/operators/error-equality-operators-some-combinations/source.spice:2:9: +Wrong data type for operator: Cannot apply '==' operator on types string and double + +2 if ("test" == 5.6) { + ^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/operators/error-logical-operators-are-booleans/exception.out b/test/test-files/analyzer/operators/error-logical-operators-are-booleans/exception.out index b61faa37e..396bfb38d 100644 --- a/test/test-files/analyzer/operators/error-logical-operators-are-booleans/exception.out +++ b/test/test-files/analyzer/operators/error-logical-operators-are-booleans/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/operators/error-logical-operators-are-booleans/source.spice:2:9: Wrong data type for operator: Cannot apply '||' operator on types string and bool \ No newline at end of file +Semantic error in : ./test-files/analyzer/operators/error-logical-operators-are-booleans/source.spice:2:9: +Wrong data type for operator: Cannot apply '||' operator on types string and bool + +2 if ("test" || false) { + ^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/operators/error-member-access-only-struct/exception.out b/test/test-files/analyzer/operators/error-member-access-only-struct/exception.out index 03420e0bb..7b846c845 100644 --- a/test/test-files/analyzer/operators/error-member-access-only-struct/exception.out +++ b/test/test-files/analyzer/operators/error-member-access-only-struct/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/operators/error-member-access-only-struct/source.spice:3:5: Member access is only allowed on structs: Cannot apply member access operator on double \ No newline at end of file +Semantic error in : ./test-files/analyzer/operators/error-member-access-only-struct/source.spice:3:5: +Member access is only allowed on structs: Cannot apply member access operator on double + +3 doubleVar.test = 1; + ^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/operators/error-multiplicative-operators-some-combinations/exception.out b/test/test-files/analyzer/operators/error-multiplicative-operators-some-combinations/exception.out index 0ede25bc2..f16a2a213 100644 --- a/test/test-files/analyzer/operators/error-multiplicative-operators-some-combinations/exception.out +++ b/test/test-files/analyzer/operators/error-multiplicative-operators-some-combinations/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/operators/error-multiplicative-operators-some-combinations/source.spice:2:29: Wrong data type for operator: Cannot apply '*' operator on types bool and string \ No newline at end of file +Semantic error in : ./test-files/analyzer/operators/error-multiplicative-operators-some-combinations/source.spice:2:29: +Wrong data type for operator: Cannot apply '*' operator on types bool and string + +2 calcResult = true * "test"; + ^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/operators/error-postfix-unary-only-integer-identifiers/exception.out b/test/test-files/analyzer/operators/error-postfix-unary-only-integer-identifiers/exception.out index c0db86331..0ed4be9e9 100644 --- a/test/test-files/analyzer/operators/error-postfix-unary-only-integer-identifiers/exception.out +++ b/test/test-files/analyzer/operators/error-postfix-unary-only-integer-identifiers/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/operators/error-postfix-unary-only-integer-identifiers/source.spice:2:5: Wrong data type for operator: Cannot apply '++' operator on type string \ No newline at end of file +Semantic error in : ./test-files/analyzer/operators/error-postfix-unary-only-integer-identifiers/source.spice:2:5: +Wrong data type for operator: Cannot apply '++' operator on type string + +2 "test"++; + ^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/operators/error-prefix-unary-only-integer-identifiers/exception.out b/test/test-files/analyzer/operators/error-prefix-unary-only-integer-identifiers/exception.out index 665d7624c..64099aa50 100644 --- a/test/test-files/analyzer/operators/error-prefix-unary-only-integer-identifiers/exception.out +++ b/test/test-files/analyzer/operators/error-prefix-unary-only-integer-identifiers/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/operators/error-prefix-unary-only-integer-identifiers/source.spice:2:7: Wrong data type for operator: Cannot apply '--' operator on type string \ No newline at end of file +Semantic error in : ./test-files/analyzer/operators/error-prefix-unary-only-integer-identifiers/source.spice:2:7: +Wrong data type for operator: Cannot apply '--' operator on type string + +2 --"test"; + ^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/operators/error-relational-operators-are-doubles-or-integers/exception.out b/test/test-files/analyzer/operators/error-relational-operators-are-doubles-or-integers/exception.out index bed056a0e..418b169f3 100644 --- a/test/test-files/analyzer/operators/error-relational-operators-are-doubles-or-integers/exception.out +++ b/test/test-files/analyzer/operators/error-relational-operators-are-doubles-or-integers/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/operators/error-relational-operators-are-doubles-or-integers/source.spice:3:12: Wrong data type for operator: Cannot apply '>' operator on types double and string \ No newline at end of file +Semantic error in : ./test-files/analyzer/operators/error-relational-operators-are-doubles-or-integers/source.spice:3:12: +Wrong data type for operator: Cannot apply '>' operator on types double and string + +3 while (variable > "test") { + ^^^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/operators/error-scope-access-only-import/exception.out b/test/test-files/analyzer/operators/error-scope-access-only-import/exception.out index 49cf46840..3abfd1df0 100644 --- a/test/test-files/analyzer/operators/error-scope-access-only-import/exception.out +++ b/test/test-files/analyzer/operators/error-scope-access-only-import/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/operators/error-scope-access-only-import/source.spice:8:5: Scope access is only allowed on imports: Cannot apply scope access operator on TestStruct \ No newline at end of file +Semantic error in : ./test-files/analyzer/operators/error-scope-access-only-import/source.spice:8:5: +Scope access is only allowed on imports: Cannot apply scope access operator on TestStruct + +8 ts::t1 = 2; + ^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/pointers/error-dyn-pointers/exception.out b/test/test-files/analyzer/pointers/error-dyn-pointers/exception.out index 03ef2e337..ddcbe511c 100644 --- a/test/test-files/analyzer/pointers/error-dyn-pointers/exception.out +++ b/test/test-files/analyzer/pointers/error-dyn-pointers/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/pointers/error-dyn-pointers/source.spice:3:5: Dyn pointers not allowed: Just use the dyn type without '*' instead \ No newline at end of file +Semantic error in : ./test-files/analyzer/pointers/error-dyn-pointers/source.spice:3:5: +Dyn pointers not allowed: Just use the dyn type without '*' instead + +3 dyn* test = &i; + ^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/procedures/error-duplicate-procedure-def/exception.out b/test/test-files/analyzer/procedures/error-duplicate-procedure-def/exception.out index 63d7f86e2..65f3d9290 100644 --- a/test/test-files/analyzer/procedures/error-duplicate-procedure-def/exception.out +++ b/test/test-files/analyzer/procedures/error-duplicate-procedure-def/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/procedures/error-duplicate-procedure-def/source.spice:5:1: Multiple declarations of a function/procedure: The function/procedure 'exampleProcedure()' is declared twice \ No newline at end of file +Semantic error in : ./test-files/analyzer/procedures/error-duplicate-procedure-def/source.spice:5:1: +Multiple declarations of a function/procedure: The function/procedure 'exampleProcedure()' is declared twice + +5 p exampleProcedure() { + ^^^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/procedures/error-mandatory-after-optional-arg/exception.out b/test/test-files/analyzer/procedures/error-mandatory-after-optional-arg/exception.out index 7765c0893..40a4b0435 100644 --- a/test/test-files/analyzer/procedures/error-mandatory-after-optional-arg/exception.out +++ b/test/test-files/analyzer/procedures/error-mandatory-after-optional-arg/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/procedures/error-mandatory-after-optional-arg/source.spice:1:44: Invalid argument order: Mandatory parameters must go before any optional parameters \ No newline at end of file +Semantic error in : ./test-files/analyzer/procedures/error-mandatory-after-optional-arg/source.spice:1:44: +Invalid argument order: Mandatory parameters must go before any optional parameters + +1 bool arg1 = false, int arg2) { + ^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/procedures/error-return-value/exception.out b/test/test-files/analyzer/procedures/error-return-value/exception.out index fb1a48a07..1a6c48a72 100644 --- a/test/test-files/analyzer/procedures/error-return-value/exception.out +++ b/test/test-files/analyzer/procedures/error-return-value/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/procedures/error-return-value/source.spice:3:12: Return with value in procedure: Return statements in procedures may not have a value attached \ No newline at end of file +Semantic error in : ./test-files/analyzer/procedures/error-return-value/source.spice:3:12: +Return with value in procedure: Return statements in procedures may not have a value attached + +3 return "Invalid return value"; + ^^^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/structs/error-constructor-not-found/exception.out b/test/test-files/analyzer/structs/error-constructor-not-found/exception.out index 81e918efd..3081d02f0 100644 --- a/test/test-files/analyzer/structs/error-constructor-not-found/exception.out +++ b/test/test-files/analyzer/structs/error-constructor-not-found/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/structs/error-constructor-not-found/source.spice:7:29: Referenced undefined function: Function/Procedure 'TestStruct.ctor()' could not be found \ No newline at end of file +Semantic error in : ./test-files/analyzer/structs/error-constructor-not-found/source.spice:7:29: +Referenced undefined function: Function/Procedure 'TestStruct.ctor()' could not be found + +7 Struct testStruct = TestStruct(); + ^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/structs/error-constructor-wrong-args/exception.out b/test/test-files/analyzer/structs/error-constructor-wrong-args/exception.out index cf2084611..7a93fd482 100644 --- a/test/test-files/analyzer/structs/error-constructor-wrong-args/exception.out +++ b/test/test-files/analyzer/structs/error-constructor-wrong-args/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/structs/error-constructor-wrong-args/source.spice:11:22: Referenced undefined function: Function/Procedure 'TestStruct.ctor(int)' could not be found \ No newline at end of file +Semantic error in : ./test-files/analyzer/structs/error-constructor-wrong-args/source.spice:11:22: +Referenced undefined function: Function/Procedure 'TestStruct.ctor(int)' could not be found + +11 dyn testStruct = TestStruct(345); + ^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/structs/error-custom-type-unknown/exception.out b/test/test-files/analyzer/structs/error-custom-type-unknown/exception.out index afe8fcf5b..15d9b9f01 100644 --- a/test/test-files/analyzer/structs/error-custom-type-unknown/exception.out +++ b/test/test-files/analyzer/structs/error-custom-type-unknown/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/structs/error-custom-type-unknown/source.spice:8:5: Unknown datatype: Unknown symbol 'NonExisting' \ No newline at end of file +Semantic error in : ./test-files/analyzer/structs/error-custom-type-unknown/source.spice:8:5: +Unknown datatype: Unknown symbol 'NonExisting' + +8 NonExisting instance = Test { " + ^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/structs/error-duplicate-struct-def/exception.out b/test/test-files/analyzer/structs/error-duplicate-struct-def/exception.out index 410841b31..da20935d3 100644 --- a/test/test-files/analyzer/structs/error-duplicate-struct-def/exception.out +++ b/test/test-files/analyzer/structs/error-duplicate-struct-def/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/structs/error-duplicate-struct-def/source.spice:7:1: Multiple declarations of a struct with the same name: Duplicate struct 'Person' \ No newline at end of file +Semantic error in : ./test-files/analyzer/structs/error-duplicate-struct-def/source.spice:7:1: +Multiple declarations of a struct with the same name: Duplicate struct 'Person' + +7 type Person struct { + ^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/structs/error-referenced-undefined-struct-field/exception.out b/test/test-files/analyzer/structs/error-referenced-undefined-struct-field/exception.out index 374d64663..e6bc76b5d 100644 --- a/test/test-files/analyzer/structs/error-referenced-undefined-struct-field/exception.out +++ b/test/test-files/analyzer/structs/error-referenced-undefined-struct-field/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/structs/error-referenced-undefined-struct-field/source.spice:8:29: Referenced undefined variable: Variable 'f3' was referenced before declared \ No newline at end of file +Semantic error in : ./test-files/analyzer/structs/error-referenced-undefined-struct-field/source.spice:8:29: +Referenced undefined variable: Variable 'f3' was referenced before declared + +8 tf("Field 1: %d", a.f3); + ^^ \ No newline at end of file diff --git a/test/test-files/analyzer/structs/error-referenced-undefined-struct/exception.out b/test/test-files/analyzer/structs/error-referenced-undefined-struct/exception.out index 68f359abc..c264fae64 100644 --- a/test/test-files/analyzer/structs/error-referenced-undefined-struct/exception.out +++ b/test/test-files/analyzer/structs/error-referenced-undefined-struct/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/structs/error-referenced-undefined-struct/source.spice:7:20: Referenced undefined struct: Struct 'TestStructTypo' could not be found \ No newline at end of file +Semantic error in : ./test-files/analyzer/structs/error-referenced-undefined-struct/source.spice:7:20: +Referenced undefined struct: Struct 'TestStructTypo' could not be found + +7 TestStruct a = TestStructTypo { 1, 2 }; + ^^^^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/structs/error-struct-field-const/exception.out b/test/test-files/analyzer/structs/error-struct-field-const/exception.out index 13d5dc828..9a1d6e038 100644 --- a/test/test-files/analyzer/structs/error-struct-field-const/exception.out +++ b/test/test-files/analyzer/structs/error-struct-field-const/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/structs/error-struct-field-const/source.spice:2:5: Specifier at illegal context: Struct fields cannot have the const specifier attached \ No newline at end of file +Semantic error in : ./test-files/analyzer/structs/error-struct-field-const/source.spice:2:5: +Specifier at illegal context: Struct fields cannot have the const specifier attached + +2 const string f1 + ^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/structs/error-struct-fields-match-declaration/exception.out b/test/test-files/analyzer/structs/error-struct-fields-match-declaration/exception.out index 025b25bb6..cdeeffb27 100644 --- a/test/test-files/analyzer/structs/error-struct-fields-match-declaration/exception.out +++ b/test/test-files/analyzer/structs/error-struct-fields-match-declaration/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/structs/error-struct-fields-match-declaration/source.spice:8:37: The type of a field value does not match the declaration: Expected type double* for the field 'dbl', but got double \ No newline at end of file +Semantic error in : ./test-files/analyzer/structs/error-struct-fields-match-declaration/source.spice:8:37: +The type of a field value does not match the declaration: Expected type double* for the field 'dbl', but got double + +8 ance = TestStruct { 6.987, "Hello!", false }; + ^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/structs/error-struct-passed-too-many-less-values/exception.out b/test/test-files/analyzer/structs/error-struct-passed-too-many-less-values/exception.out index a8f0d146e..b4c0e7a53 100644 --- a/test/test-files/analyzer/structs/error-struct-passed-too-many-less-values/exception.out +++ b/test/test-files/analyzer/structs/error-struct-passed-too-many-less-values/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/structs/error-struct-passed-too-many-less-values/source.spice:9:37: Number of struct fields not matching declaration: You've passed too less/many field values. Pass either none or all of them \ No newline at end of file +Semantic error in : ./test-files/analyzer/structs/error-struct-passed-too-many-less-values/source.spice:9:37: +Number of struct fields not matching declaration: You've passed too less/many field values. Pass either none or all of them + +9 ance = TestStruct { &str, false }; + ^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/structs/error-struct-types-not-matching/exception.out b/test/test-files/analyzer/structs/error-struct-types-not-matching/exception.out index 62a103d46..3fb797d3a 100644 --- a/test/test-files/analyzer/structs/error-struct-types-not-matching/exception.out +++ b/test/test-files/analyzer/structs/error-struct-types-not-matching/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/structs/error-struct-types-not-matching/source.spice:12:5: Wrong data type for operator: Cannot apply '=' operator on types AnotherStruct and TestStruct \ No newline at end of file +Semantic error in : ./test-files/analyzer/structs/error-struct-types-not-matching/source.spice:12:5: +Wrong data type for operator: Cannot apply '=' operator on types AnotherStruct and TestStruct + +12 AnotherStruct testInstance = TestStruct { 6.456, "Hi!", false }; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/ternary/error-ternary-condition-bool/exception.out b/test/test-files/analyzer/ternary/error-ternary-condition-bool/exception.out index 9744867b4..65b9a2462 100644 --- a/test/test-files/analyzer/ternary/error-ternary-condition-bool/exception.out +++ b/test/test-files/analyzer/ternary/error-ternary-condition-bool/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/ternary/error-ternary-condition-bool/source.spice:2:25: Wrong data type for operator: Condition operand in ternary must be a bool \ No newline at end of file +Semantic error in : ./test-files/analyzer/ternary/error-ternary-condition-bool/source.spice:2:25: +Wrong data type for operator: Condition operand in ternary must be a bool + +2 double calcResult = "No bool" ? 5.6 : 1.0; + ^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/ternary/error-ternary-types-match/exception.out b/test/test-files/analyzer/ternary/error-ternary-types-match/exception.out index 4f6cd856b..3ba31b196 100644 --- a/test/test-files/analyzer/ternary/error-ternary-types-match/exception.out +++ b/test/test-files/analyzer/ternary/error-ternary-types-match/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/ternary/error-ternary-types-match/source.spice:2:25: Wrong data type for operator: True and false operands in ternary must be of same data type \ No newline at end of file +Semantic error in : ./test-files/analyzer/ternary/error-ternary-types-match/source.spice:2:25: +Wrong data type for operator: True and false operands in ternary must be of same data type + +2 double calcResult = 1 != 2 ? false : 1.0; + ^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/unsafe/error-pointer-cast/exception.out b/test/test-files/analyzer/unsafe/error-pointer-cast/exception.out index 81d5c62e6..66ac6c20b 100644 --- a/test/test-files/analyzer/unsafe/error-pointer-cast/exception.out +++ b/test/test-files/analyzer/unsafe/error-pointer-cast/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/unsafe/error-pointer-cast/source.spice:4:17: Unsafe operation in safe context: Cannot apply '(cast)' operator on types int* and long* as this is an unsafe operation. Please use unsafe blocks if you know what you are doing. \ No newline at end of file +Semantic error in : ./test-files/analyzer/unsafe/error-pointer-cast/source.spice:4:17: +Unsafe operation in safe context: Cannot apply '(cast)' operator on types int* and long* as this is an unsafe operation. Please use unsafe blocks if you know what you are doing. + +4 int* iPtr = (int*) lPtr; + ^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/variables/error-dyn-pointer/exception.out b/test/test-files/analyzer/variables/error-dyn-pointer/exception.out index 6801cb057..f7de64c13 100644 --- a/test/test-files/analyzer/variables/error-dyn-pointer/exception.out +++ b/test/test-files/analyzer/variables/error-dyn-pointer/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/variables/error-dyn-pointer/source.spice:3:5: Dyn pointers not allowed: Just use the dyn type without '*' instead \ No newline at end of file +Semantic error in : ./test-files/analyzer/variables/error-dyn-pointer/source.spice:3:5: +Dyn pointers not allowed: Just use the dyn type without '*' instead + +3 dyn** dynPointer = &&s; + ^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/variables/error-global-const-not-initialized/exception.out b/test/test-files/analyzer/variables/error-global-const-not-initialized/exception.out index 89bd3d87a..62e12e4e8 100644 --- a/test/test-files/analyzer/variables/error-global-const-not-initialized/exception.out +++ b/test/test-files/analyzer/variables/error-global-const-not-initialized/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/variables/error-global-const-not-initialized/source.spice:1:1: Global const without value: You must specify a value for constant global variables \ No newline at end of file +Semantic error in : ./test-files/analyzer/variables/error-global-const-not-initialized/source.spice:1:1: +Global const without value: You must specify a value for constant global variables + +1 const int count; + ^^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/variables/error-global-var-decl-twice-external/exception.out b/test/test-files/analyzer/variables/error-global-var-decl-twice-external/exception.out index 957a76e2c..3ed86d4d8 100644 --- a/test/test-files/analyzer/variables/error-global-var-decl-twice-external/exception.out +++ b/test/test-files/analyzer/variables/error-global-var-decl-twice-external/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/variables/error-global-var-decl-twice-external/source.spice:3:1: Multiple declarations of the same variable: A global variable named 'GLOBAL_VARIABLE' is already declared in another module. Please use a different name. \ No newline at end of file +Semantic error in : ./test-files/analyzer/variables/error-global-var-decl-twice-external/source.spice:3:1: +Multiple declarations of the same variable: A global variable named 'GLOBAL_VARIABLE' is already declared in another module. Please use a different name. + +3 double GLOBAL_VARIABLE = 14.4; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/variables/error-global-var-decl-twice/exception.out b/test/test-files/analyzer/variables/error-global-var-decl-twice/exception.out index c320b0c61..7e7b62ea7 100644 --- a/test/test-files/analyzer/variables/error-global-var-decl-twice/exception.out +++ b/test/test-files/analyzer/variables/error-global-var-decl-twice/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/variables/error-global-var-decl-twice/source.spice:3:1: Multiple declarations of the same variable: The global variable 'GLOBAL_VAR' was declared more than once \ No newline at end of file +Semantic error in : ./test-files/analyzer/variables/error-global-var-decl-twice/source.spice:3:1: +Multiple declarations of the same variable: The global variable 'GLOBAL_VAR' was declared more than once + +3 double GLOBAL_VAR = 4.567; + ^^^^^^^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/variables/error-global-var-different-type-assign/exception.out b/test/test-files/analyzer/variables/error-global-var-different-type-assign/exception.out index 8b91a6784..7c629eccb 100644 --- a/test/test-files/analyzer/variables/error-global-var-different-type-assign/exception.out +++ b/test/test-files/analyzer/variables/error-global-var-different-type-assign/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/variables/error-global-var-different-type-assign/source.spice:1:32: Wrong data type for operator: Cannot apply the assign operator on different data types. You provided short and int \ No newline at end of file +Semantic error in : ./test-files/analyzer/variables/error-global-var-different-type-assign/source.spice:1:32: +Wrong data type for operator: Cannot apply the assign operator on different data types. You provided short and int + +1 ort unsignedShort = -10; + ^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/variables/error-global-var-dyn/exception.out b/test/test-files/analyzer/variables/error-global-var-dyn/exception.out index 9973eeeba..41373521e 100644 --- a/test/test-files/analyzer/variables/error-global-var-dyn/exception.out +++ b/test/test-files/analyzer/variables/error-global-var-dyn/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/variables/error-global-var-dyn/source.spice:2:1: Global of type dyn: Global variables must have an explicit data type \ No newline at end of file +Semantic error in : ./test-files/analyzer/variables/error-global-var-dyn/source.spice:2:1: +Global of type dyn: Global variables must have an explicit data type + +2 dyn invalid; + ^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/variables/error-global-var-struct-array/exception.out b/test/test-files/analyzer/variables/error-global-var-struct-array/exception.out index cb0362872..93edd2be3 100644 --- a/test/test-files/analyzer/variables/error-global-var-struct-array/exception.out +++ b/test/test-files/analyzer/variables/error-global-var-struct-array/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/variables/error-global-var-struct-array/source.spice:8:7: Global of invalid type: Spice does not allow global variables of this type \ No newline at end of file +Semantic error in : ./test-files/analyzer/variables/error-global-var-struct-array/source.spice:8:7: +Global of invalid type: Spice does not allow global variables of this type + +8 const dyn RULE_SET = { + ^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/variables/error-reserved-keyword-as-identifier/exception.out b/test/test-files/analyzer/variables/error-reserved-keyword-as-identifier/exception.out index 632a0adef..c57eeee1a 100644 --- a/test/test-files/analyzer/variables/error-reserved-keyword-as-identifier/exception.out +++ b/test/test-files/analyzer/variables/error-reserved-keyword-as-identifier/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/variables/error-reserved-keyword-as-identifier/source.spice:3:26: Reserved keyword used as identifier: 'new' is a reserved keyword for future development of the language. Please use another identifier instead \ No newline at end of file +Semantic error in : ./test-files/analyzer/variables/error-reserved-keyword-as-identifier/source.spice:3:26: +Reserved keyword used as identifier: 'new' is a reserved keyword for future development of the language. Please use another identifier instead + +3 rintf("New is: %s", new); + ^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/variables/error-variable-const-not-modified-1/exception.out b/test/test-files/analyzer/variables/error-variable-const-not-modified-1/exception.out index 09fbadc26..b25aadf94 100644 --- a/test/test-files/analyzer/variables/error-variable-const-not-modified-1/exception.out +++ b/test/test-files/analyzer/variables/error-variable-const-not-modified-1/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/variables/error-variable-const-not-modified-1/source.spice:3:5: Cannot re-assign constant variable: Not re-assignable variable 'variable' \ No newline at end of file +Semantic error in : ./test-files/analyzer/variables/error-variable-const-not-modified-1/source.spice:3:5: +Cannot re-assign constant variable: Not re-assignable variable 'variable' + +3 variable = 3.2; + ^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/variables/error-variable-const-not-modified-2/exception.out b/test/test-files/analyzer/variables/error-variable-const-not-modified-2/exception.out index 5a5bde4f5..71e354c66 100644 --- a/test/test-files/analyzer/variables/error-variable-const-not-modified-2/exception.out +++ b/test/test-files/analyzer/variables/error-variable-const-not-modified-2/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/variables/error-variable-const-not-modified-2/source.spice:3:5: Cannot re-assign constant variable: Not re-assignable variable 'constVar' \ No newline at end of file +Semantic error in : ./test-files/analyzer/variables/error-variable-const-not-modified-2/source.spice:3:5: +Cannot re-assign constant variable: Not re-assignable variable 'constVar' + +3 constVar++; + ^^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/variables/error-variable-declared-before-referenced/exception.out b/test/test-files/analyzer/variables/error-variable-declared-before-referenced/exception.out index 0f90f6e23..8af8d3871 100644 --- a/test/test-files/analyzer/variables/error-variable-declared-before-referenced/exception.out +++ b/test/test-files/analyzer/variables/error-variable-declared-before-referenced/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/variables/error-variable-declared-before-referenced/source.spice:2:26: Referenced undefined variable: Variable 'test' was referenced before declared \ No newline at end of file +Semantic error in : ./test-files/analyzer/variables/error-variable-declared-before-referenced/source.spice:2:26: +Referenced undefined variable: Variable 'test' was referenced before declared + +2 rintf("Output: %s", test); + ^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/variables/error-variable-declared-only-once/exception.out b/test/test-files/analyzer/variables/error-variable-declared-only-once/exception.out index a436b3653..12c7c7052 100644 --- a/test/test-files/analyzer/variables/error-variable-declared-only-once/exception.out +++ b/test/test-files/analyzer/variables/error-variable-declared-only-once/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/variables/error-variable-declared-only-once/source.spice:3:5: Multiple declarations of the same variable: The variable 'i' was declared more than once \ No newline at end of file +Semantic error in : ./test-files/analyzer/variables/error-variable-declared-only-once/source.spice:3:5: +Multiple declarations of the same variable: The variable 'i' was declared more than once + +3 int i = 2; + ^^^^^^^^^ \ No newline at end of file diff --git a/test/test-files/analyzer/while-loops/error-while-condition-bool/exception.out b/test/test-files/analyzer/while-loops/error-while-condition-bool/exception.out index c5a182431..70db08418 100644 --- a/test/test-files/analyzer/while-loops/error-while-condition-bool/exception.out +++ b/test/test-files/analyzer/while-loops/error-while-condition-bool/exception.out @@ -1 +1,5 @@ -Semantic error in ./test-files/analyzer/while-loops/error-while-condition-bool/source.spice:2:11: Condition must be bool: While loop condition must be of type bool \ No newline at end of file +Semantic error in : ./test-files/analyzer/while-loops/error-while-condition-bool/source.spice:2:11: +Condition must be bool: While loop condition must be of type bool + +2 while 5.6 { + ^^^ \ No newline at end of file