diff --git a/.github/workflows/ci-cpp.yml b/.github/workflows/ci-cpp.yml index 758881af4..b13c16cb5 100644 --- a/.github/workflows/ci-cpp.yml +++ b/.github/workflows/ci-cpp.yml @@ -43,14 +43,14 @@ jobs: uses: actions/cache@v3 with: path: /home/runner/work/spice/llvm - key: llvm-15.0.0-rc2 + key: llvm-15.0.0-rc3 - name: Setup LLVM if: steps.cache-llvm.outputs.cache-hit != 'true' run: | cd .. rm -rf llvm - git clone --depth 1 --branch llvmorg-15.0.0-rc2 https://github.com/llvm/llvm-project llvm + git clone --depth 1 --branch llvmorg-15.0.0-rc3 https://github.com/llvm/llvm-project llvm mkdir ./llvm/build cd ./llvm/build cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_CXX_FLAGS_RELEASE="-O2" -GNinja ../llvm diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index d681f7907..3caaffe1a 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -10,8 +10,6 @@ jobs: analyze-cpp: name: Analyze C++ Code runs-on: ubuntu-latest - strategy: - fail-fast: false steps: - name: Checkout uses: actions/checkout@v3 @@ -43,13 +41,13 @@ jobs: uses: actions/cache@v3 with: path: /home/runner/work/spice/llvm - key: 15.0.0-rc2 + key: 15.0.0-rc3 - name: Setup LLVM if: steps.cache-llvm.outputs.cache-hit != 'true' run: | cd .. - git clone --depth 1 --branch llvmorg-15.0.0-rc2 https://github.com/llvm/llvm-project llvm + git clone --depth 1 --branch llvmorg-15.0.0-rc3 https://github.com/llvm/llvm-project llvm mkdir ./llvm/build cd ./llvm/build cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_CXX_FLAGS_RELEASE="-O2" -GNinja ../llvm diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 89d3e312a..775e88214 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -44,12 +44,12 @@ jobs: uses: actions/cache@v3 with: path: /home/runner/work/spice/spice/llvm - key: llvm-15.0.0-rc2-linux-x64 + key: llvm-15.0.0-rc3-linux-x64 - name: Setup LLVM if: steps.cache-llvm.outputs.cache-hit != 'true' run: | - git clone --depth 1 --branch llvmorg-15.0.0-rc2 https://github.com/llvm/llvm-project.git llvm + git clone --depth 1 --branch llvmorg-15.0.0-rc3 https://github.com/llvm/llvm-project.git llvm mkdir ./llvm/build cd ./llvm/build cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_CXX_FLAGS_RELEASE="-O2" -GNinja -Wno-dev -Wattributes ../llvm @@ -124,12 +124,12 @@ jobs: uses: actions/cache@v3 with: path: D:/a/spice/spice/llvm - key: llvm-15.0.0-rc2-win-x64 + key: llvm-15.0.0-rc3-win-x64 - name: Setup LLVM if: steps.cache-llvm.outputs.cache-hit != 'true' run: | - git clone --depth 1 --branch llvmorg-15.0.0-rc2 https://github.com/llvm/llvm-project.git llvm + git clone --depth 1 --branch llvmorg-15.0.0-rc3 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." @@ -351,8 +351,9 @@ jobs: asset_name: spice_${{ matrix.config.label }}_setup.msi tag: ${{ github.ref }} - - uses: vedantmgoyal2009/winget-releaser@latest + - name: Deploy to WinGet + uses: vedantmgoyal2009/winget-releaser@latest with: identifier: ChilliBits.Spice release-tag: ${{ github.ref }} - token: ${{ secrets.CR_PAT }} + token: ${{ secrets.CR_PAT }} \ No newline at end of file diff --git a/dev-setup.bat b/dev-setup.bat index 73cd44d25..5d45459a0 100644 --- a/dev-setup.bat +++ b/dev-setup.bat @@ -27,7 +27,7 @@ echo done. REM - Clone LLVM echo [Step 2] Cloning LLVM (Could take a while) ... -git clone --depth 1 --branch llvmorg-15.0.0-rc2 https://github.com/llvm/llvm-project llvm +git clone --depth 1 --branch llvmorg-15.0.0-rc3 https://github.com/llvm/llvm-project llvm echo done. REM - Build LLVM diff --git a/dev-setup.sh b/dev-setup.sh index da5169fe9..bddda4a97 100644 --- a/dev-setup.sh +++ b/dev-setup.sh @@ -16,7 +16,7 @@ colored_echo "done." # Clone LLVM colored_echo "[Step 2] Cloning LLVM (Could take a while) ... " -git clone --depth 1 --branch llvmorg-15.0.0-rc2 https://github.com/llvm/llvm-project llvm +git clone --depth 1 --branch llvmorg-15.0.0-rc3 https://github.com/llvm/llvm-project llvm colored_echo "done." # Build LLVM diff --git a/media/test-project/os-test.spice b/media/test-project/os-test.spice index 5020d1c58..34e41f8b9 100644 --- a/media/test-project/os-test.spice +++ b/media/test-project/os-test.spice @@ -2,15 +2,17 @@ import "std/data/pair" as pair; f main() { - vec.Vector> pairVector = vec.Vector>(); + vec::Vector> pairVector = vec.Vector>(); pairVector.pushBack(pair.Pair(0, "Hello")); pairVector.pushBack(pair.Pair(1, "World")); - pair.Pair p1 = pairVector.get(1); + pair::Pair p1 = pairVector.get(1); printf("Hello %s!", p1.getSecond()); }*/ +import "std/net/http" as http; + f main() { - int[10] testArray = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - printf("Test: %d\n", testArray[10]); + http::HttpServer server = http::HttpServer(); + server.serve("/test", "Hello World!"); } \ No newline at end of file diff --git a/src/analyzer/AnalyzerVisitor.cpp b/src/analyzer/AnalyzerVisitor.cpp index f20c2b4b9..21cda463b 100644 --- a/src/analyzer/AnalyzerVisitor.cpp +++ b/src/analyzer/AnalyzerVisitor.cpp @@ -839,7 +839,7 @@ std::any AnalyzerVisitor::visitForeachLoop(ForeachLoopNode *node) { std::string varName = node->idxVarDecl()->varName; SymbolTableEntry *entry = currentScope->lookup(varName); assert(entry != nullptr); - entry->updateState(INITIALIZED, err.get(), node->idxVarDecl()->codeLoc); + entry->updateState(INITIALIZED, node->idxVarDecl()->codeLoc); } // Check if index type is int @@ -870,7 +870,7 @@ std::any AnalyzerVisitor::visitForeachLoop(ForeachLoopNode *node) { "Foreach loop item type does not match array type. Expected " + arrayType.getName(false) + ", provided " + itemType.getName(false)); } - itemVarSymbol->updateState(INITIALIZED, err.get(), node->itemDecl()->codeLoc); + itemVarSymbol->updateState(INITIALIZED, node->itemDecl()->codeLoc); // Visit statement list in new scope nestedLoopCounter++; @@ -1052,7 +1052,7 @@ std::any AnalyzerVisitor::visitReturnStmt(ReturnStmtNode *node) { } // Set the return variable to initialized - returnVariable->updateState(INITIALIZED, err.get(), node->codeLoc); + returnVariable->updateState(INITIALIZED, node->codeLoc); } else { returnType = returnVariable->getType(); } @@ -1270,7 +1270,7 @@ std::any AnalyzerVisitor::visitAssignExpr(AssignExprNode *node) { // Update state in symbol table if (!currentEntry->getType().isOneOf({TY_FUNCTION, TY_PROCEDURE})) - currentEntry->updateState(INITIALIZED, err.get(), node->lhs()->codeLoc); + currentEntry->updateState(INITIALIZED, node->lhs()->codeLoc); // In case the lhs variable is captured, notify the capture about the write access Capture *lhsCapture = currentScope->lookupCapture(variableName); @@ -1528,7 +1528,7 @@ std::any AnalyzerVisitor::visitPrefixUnaryExpr(PrefixUnaryExprNode *node) { // Update state in symbol table if (currentEntry != nullptr) - currentEntry->updateState(INITIALIZED, err.get(), node->codeLoc); + currentEntry->updateState(INITIALIZED, node->codeLoc); // In case the lhs is captured, notify the capture about the write access if (Capture *lhsCapture = currentScope->lookupCapture(currentVarName); lhsCapture) @@ -1539,7 +1539,7 @@ std::any AnalyzerVisitor::visitPrefixUnaryExpr(PrefixUnaryExprNode *node) { // Update state in symbol table if (currentEntry != nullptr) - currentEntry->updateState(INITIALIZED, err.get(), node->codeLoc); + currentEntry->updateState(INITIALIZED, node->codeLoc); // In case the lhs is captured, notify the capture about the write access if (Capture *lhsCapture = currentScope->lookupCapture(currentVarName); lhsCapture) @@ -1653,7 +1653,7 @@ std::any AnalyzerVisitor::visitPostfixUnaryExpr(PostfixUnaryExprNode *node) { // Update state in symbol table if (currentEntry != nullptr) - currentEntry->updateState(INITIALIZED, err.get(), node->codeLoc); + currentEntry->updateState(INITIALIZED, node->codeLoc); // In case the lhs is captured, notify the capture about the write access if (Capture *lhsCapture = currentScope->lookupCapture(currentVarName); lhsCapture) @@ -1665,7 +1665,7 @@ std::any AnalyzerVisitor::visitPostfixUnaryExpr(PostfixUnaryExprNode *node) { // Update state in symbol table if (currentEntry != nullptr) - currentEntry->updateState(INITIALIZED, err.get(), node->codeLoc); + currentEntry->updateState(INITIALIZED, node->codeLoc); // In case the lhs is captured, notify the capture about the write access if (Capture *lhsCapture = currentScope->lookupCapture(currentVarName); lhsCapture) @@ -1959,8 +1959,8 @@ std::any AnalyzerVisitor::visitFunctionCall(FunctionCallNode *node) { // If the return type is an external struct, initialize it if (!scopePathBackup.isEmpty() && returnType.is(TY_STRUCT) && scopePathBackup.getCurrentScope()->isImported(currentScope)) { - SymbolType symbolType = initExtStruct(scopePathBackup.getCurrentScope(), scopePathBackup.getScopePrefix(true), - returnType.getSubType(), thisType.getTemplateTypes(), node->codeLoc); + SymbolType symbolType = initExtStruct(currentScope, scopePathBackup.getScopePrefix(true), returnType.getSubType(), + returnType.getTemplateTypes(), node->codeLoc); return node->setEvaluatedSymbolType(symbolType); } diff --git a/src/dependency/SourceFile.cpp b/src/dependency/SourceFile.cpp index c214e0913..302fb85a4 100644 --- a/src/dependency/SourceFile.cpp +++ b/src/dependency/SourceFile.cpp @@ -51,7 +51,7 @@ SourceFile::SourceFile(CliOptions &options, SourceFile *parent, std::string name antlrCtx.parser->removeParseListeners(); // Create AST - ast = std::make_shared(nullptr, CodeLoc(filePath, 1, 1)); + ast = std::make_shared(nullptr, CodeLoc(1, 1, filePath)); // Create symbol table symbolTable = std::make_shared(nullptr, SCOPE_GLOBAL, parent == nullptr, true); diff --git a/src/exception/AntlrThrowingErrorListener.cpp b/src/exception/AntlrThrowingErrorListener.cpp index 486e42796..59d40f974 100644 --- a/src/exception/AntlrThrowingErrorListener.cpp +++ b/src/exception/AntlrThrowingErrorListener.cpp @@ -7,6 +7,5 @@ void AntlrThrowingErrorListener::syntaxError(antlr4::Recognizer *recognizer, antlr4::Token *offendingSymbol, size_t line, size_t charPositionInLine, const std::string &msg, std::exception_ptr e) { - CodeLoc codeLoc = CodeLoc("", line, charPositionInLine); - throw LexerParserError(codeLoc, mode == LEXER ? TOKENIZING_FAILED : PARSING_FAILED, msg); + throw LexerParserError(CodeLoc(line, charPositionInLine), mode == LEXER ? TOKENIZING_FAILED : PARSING_FAILED, msg); } \ No newline at end of file diff --git a/src/parser/AstBuilderVisitor.cpp b/src/parser/AstBuilderVisitor.cpp index 7b2066c18..590195488 100644 --- a/src/parser/AstBuilderVisitor.cpp +++ b/src/parser/AstBuilderVisitor.cpp @@ -19,21 +19,21 @@ std::any AstBuilderVisitor::visitEntry(SpiceParser::EntryContext *ctx) { // Create child for the current node antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // MainFctDef - currentNode = entryNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = entryNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // FctDef - currentNode = entryNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = entryNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // ProcDef - currentNode = entryNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = entryNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // StructDef - currentNode = entryNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = entryNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // GenericTypeDef - currentNode = entryNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = entryNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // GlobalVarDef - currentNode = entryNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = entryNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // ImportStmt - currentNode = entryNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = entryNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // ExtDecl - currentNode = entryNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = entryNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -50,10 +50,10 @@ std::any AstBuilderVisitor::visitMainFunctionDef(SpiceParser::MainFunctionDefCon for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) { // ArgLstDef - currentNode = mainFctDefNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = mainFctDefNode->createChild(CodeLoc(rule->start, fileName)); mainFctDefNode->hasArgs = true; } else if (rule = dynamic_cast(subTree); rule != nullptr) // StmtLst - currentNode = mainFctDefNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = mainFctDefNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -79,17 +79,17 @@ std::any AstBuilderVisitor::visitFunctionDef(SpiceParser::FunctionDefContext *ct for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // DeclSpecifiers - currentNode = fctDefNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = fctDefNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // DataType - currentNode = fctDefNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = fctDefNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) { // TypeLst - currentNode = fctDefNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = fctDefNode->createChild(CodeLoc(rule->start, fileName)); fctDefNode->isGeneric = true; } else if (rule = dynamic_cast(subTree); rule != nullptr) { // ParamLst - currentNode = fctDefNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = fctDefNode->createChild(CodeLoc(rule->start, fileName)); fctDefNode->hasParams = true; } else if (rule = dynamic_cast(subTree); rule != nullptr) // StmtLst - currentNode = fctDefNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = fctDefNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -115,15 +115,15 @@ std::any AstBuilderVisitor::visitProcedureDef(SpiceParser::ProcedureDefContext * for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // DeclSpecifiers - currentNode = procDefNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = procDefNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) { // TypeLst - currentNode = procDefNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = procDefNode->createChild(CodeLoc(rule->start, fileName)); procDefNode->isGeneric = true; } else if (rule = dynamic_cast(subTree); rule != nullptr) { // ParamLst - currentNode = procDefNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = procDefNode->createChild(CodeLoc(rule->start, fileName)); procDefNode->hasParams = true; } else if (rule = dynamic_cast(subTree); rule != nullptr) // StmtLst - currentNode = procDefNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = procDefNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -144,12 +144,12 @@ std::any AstBuilderVisitor::visitStructDef(SpiceParser::StructDefContext *ctx) { for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // DeclSpecifiers - currentNode = structDefNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = structDefNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) { // TypeLst - currentNode = structDefNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = structDefNode->createChild(CodeLoc(rule->start, fileName)); structDefNode->isGeneric = true; } else if (rule = dynamic_cast(subTree); rule != nullptr) // Field - currentNode = structDefNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = structDefNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -170,9 +170,9 @@ std::any AstBuilderVisitor::visitGenericTypeDef(SpiceParser::GenericTypeDefConte for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // DeclSpecifiers - currentNode = genericTypeDefNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = genericTypeDefNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // TypeAltsLst - currentNode = genericTypeDefNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = genericTypeDefNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -193,11 +193,11 @@ std::any AstBuilderVisitor::visitGlobalVarDef(SpiceParser::GlobalVarDefContext * for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // DeclSpecifiers - currentNode = globalVarDefNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = globalVarDefNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // DataType - currentNode = globalVarDefNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = globalVarDefNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // Value - currentNode = globalVarDefNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = globalVarDefNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -218,9 +218,9 @@ std::any AstBuilderVisitor::visitExtDecl(SpiceParser::ExtDeclContext *ctx) { for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // DataType - currentNode = extDeclNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = extDeclNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) { // TypeLst - currentNode = extDeclNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = extDeclNode->createChild(CodeLoc(rule->start, fileName)); extDeclNode->hasArgs = true; } else @@ -240,7 +240,7 @@ std::any AstBuilderVisitor::visitThreadDef(SpiceParser::ThreadDefContext *ctx) { for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // StmtLst - currentNode = threadDefNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = threadDefNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -258,7 +258,7 @@ std::any AstBuilderVisitor::visitUnsafeBlockDef(SpiceParser::UnsafeBlockDefConte for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // StmtLst - currentNode = unsafeBlockDefNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = unsafeBlockDefNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -278,7 +278,7 @@ std::any AstBuilderVisitor::visitForLoop(SpiceParser::ForLoopContext *ctx) { if (rule = dynamic_cast(subTree); rule != nullptr) // ForHead visit(rule); else if (rule = dynamic_cast(subTree); rule != nullptr) // StmtLst - currentNode = forLoopNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = forLoopNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -296,9 +296,9 @@ std::any AstBuilderVisitor::visitForHead(SpiceParser::ForHeadContext *ctx) { for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // DeclStmt - currentNode = forLoopNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = forLoopNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // AssignExpr - currentNode = forLoopNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = forLoopNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -318,7 +318,7 @@ std::any AstBuilderVisitor::visitForeachLoop(SpiceParser::ForeachLoopContext *ct if (rule = dynamic_cast(subTree); rule != nullptr) // ForeachHead visit(rule); else if (rule = dynamic_cast(subTree); rule != nullptr) // StmtLst - currentNode = foreachLoopNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = foreachLoopNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -336,9 +336,9 @@ std::any AstBuilderVisitor::visitForeachHead(SpiceParser::ForeachHeadContext *ct for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // DeclStmt - currentNode = foreachLoopNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = foreachLoopNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // AssignExpr - currentNode = foreachLoopNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = foreachLoopNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -356,9 +356,9 @@ std::any AstBuilderVisitor::visitWhileLoop(SpiceParser::WhileLoopContext *ctx) { for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // AssignExpr - currentNode = whileLoopNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = whileLoopNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // StmtLst - currentNode = whileLoopNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = whileLoopNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -376,11 +376,11 @@ std::any AstBuilderVisitor::visitIfStmt(SpiceParser::IfStmtContext *ctx) { for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // AssignExpr - currentNode = ifStmtNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = ifStmtNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // StmtLst - currentNode = ifStmtNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = ifStmtNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // ElseStmt - currentNode = ifStmtNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = ifStmtNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -398,10 +398,10 @@ std::any AstBuilderVisitor::visitElseStmt(SpiceParser::ElseStmtContext *ctx) { for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) { // IfStmt - currentNode = elseStmtNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = elseStmtNode->createChild(CodeLoc(rule->start, fileName)); elseStmtNode->isElseIf = true; } else if (rule = dynamic_cast(subTree); rule != nullptr) // StmtLst - currentNode = elseStmtNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = elseStmtNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -419,7 +419,7 @@ std::any AstBuilderVisitor::visitAssertStmt(SpiceParser::AssertStmtContext *ctx) for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) { // AssignExpr - currentNode = assertStmtNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = assertStmtNode->createChild(CodeLoc(rule->start, fileName)); assertStmtNode->expressionString = rule->getText(); } else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -437,21 +437,21 @@ std::any AstBuilderVisitor::visitStmtLst(SpiceParser::StmtLstContext *ctx) { for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // Stmt - currentNode = stmtLstNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = stmtLstNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // ForLoop - currentNode = stmtLstNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = stmtLstNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // ForeachLoop - currentNode = stmtLstNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = stmtLstNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // WhileLoop - currentNode = stmtLstNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = stmtLstNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // IfStmt - currentNode = stmtLstNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = stmtLstNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // AssertStmt - currentNode = stmtLstNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = stmtLstNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // ThreadDef - currentNode = stmtLstNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = stmtLstNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // UnsafeBlockDef - currentNode = stmtLstNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = stmtLstNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -469,7 +469,7 @@ std::any AstBuilderVisitor::visitTypeLst(SpiceParser::TypeLstContext *ctx) { for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) { // DataType - currentNode = typeLstNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = typeLstNode->createChild(CodeLoc(rule->start, fileName)); typeLstNode->numberOfTypes++; } else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -488,7 +488,7 @@ std::any AstBuilderVisitor::visitTypeAltsLst(SpiceParser::TypeAltsLstContext *ct for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) { // DataType - currentNode = typeAltsLstNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = typeAltsLstNode->createChild(CodeLoc(rule->start, fileName)); typeAltsLstNode->numberOfAlts++; } else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -507,7 +507,7 @@ std::any AstBuilderVisitor::visitParamLst(SpiceParser::ParamLstContext *ctx) { for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // DeclStmt - currentNode = argLstDefNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = argLstDefNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -525,7 +525,7 @@ std::any AstBuilderVisitor::visitArgLst(SpiceParser::ArgLstContext *ctx) { for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // AssignStmt - currentNode = argLstNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = argLstNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -546,9 +546,9 @@ std::any AstBuilderVisitor::visitField(SpiceParser::FieldContext *ctx) { for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // DeclSpecifiers - currentNode = fieldNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = fieldNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // DataType - currentNode = fieldNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = fieldNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -566,15 +566,15 @@ std::any AstBuilderVisitor::visitStmt(SpiceParser::StmtContext *ctx) { for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // DeclStmt - currentNode = stmtNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = stmtNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // AssignExpr - currentNode = stmtNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = stmtNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // ReturnStmt - currentNode = stmtNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = stmtNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // BreakStmt - currentNode = stmtNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = stmtNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // ContinueStmt - currentNode = stmtNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = stmtNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -595,11 +595,11 @@ std::any AstBuilderVisitor::visitDeclStmt(SpiceParser::DeclStmtContext *ctx) { for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // DeclSpecifiers - currentNode = declStmtNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = declStmtNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // DataType - currentNode = declStmtNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = declStmtNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) { // AssignExpr - currentNode = declStmtNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = declStmtNode->createChild(CodeLoc(rule->start, fileName)); declStmtNode->hasAssignment = true; } else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -618,7 +618,7 @@ std::any AstBuilderVisitor::visitSpecifierLst(SpiceParser::SpecifierLstContext * for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // DeclSpecifier - currentNode = specifierLstNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = specifierLstNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -672,7 +672,7 @@ std::any AstBuilderVisitor::visitReturnStmt(SpiceParser::ReturnStmtContext *ctx) for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) { // AssignExpr - currentNode = returnStmtNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = returnStmtNode->createChild(CodeLoc(rule->start, fileName)); returnStmtNode->hasReturnValue = true; } else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -711,15 +711,15 @@ std::any AstBuilderVisitor::visitBuiltinCall(SpiceParser::BuiltinCallContext *ct for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // PrintfCall - currentNode = atomicExprNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = atomicExprNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // SizeofCall - currentNode = atomicExprNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = atomicExprNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // LenCall - currentNode = atomicExprNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = atomicExprNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // TidCall - currentNode = atomicExprNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = atomicExprNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // JoinCall - currentNode = atomicExprNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = atomicExprNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -743,7 +743,7 @@ std::any AstBuilderVisitor::visitPrintfCall(SpiceParser::PrintfCallContext *ctx) for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // AssignExpr - currentNode = printfCallNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = printfCallNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -764,9 +764,9 @@ std::any AstBuilderVisitor::visitSizeOfCall(SpiceParser::SizeOfCallContext *ctx) for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // AssignExpr - currentNode = sizeofCallNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = sizeofCallNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // DataType - currentNode = sizeofCallNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = sizeofCallNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -784,7 +784,7 @@ std::any AstBuilderVisitor::visitLenCall(SpiceParser::LenCallContext *ctx) { for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // AssignExpr - currentNode = lenCallNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = lenCallNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -804,7 +804,7 @@ std::any AstBuilderVisitor::visitJoinCall(SpiceParser::JoinCallContext *ctx) { for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // AssignExpr - currentNode = joinCallNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = joinCallNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -822,15 +822,15 @@ std::any AstBuilderVisitor::visitAssignExpr(SpiceParser::AssignExprContext *ctx) for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // PrefixUnaryExpr - currentNode = assignExprNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = assignExprNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // AssignOp visit(rule); else if (rule = dynamic_cast(subTree); rule != nullptr) // AssignExpr - currentNode = assignExprNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = assignExprNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // TernaryExpr - currentNode = assignExprNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = assignExprNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // ThreadDef - currentNode = assignExprNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = assignExprNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -848,7 +848,7 @@ std::any AstBuilderVisitor::visitTernaryExpr(SpiceParser::TernaryExprContext *ct for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // LogicalOrExpr - currentNode = ternaryExprNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = ternaryExprNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -866,7 +866,7 @@ std::any AstBuilderVisitor::visitLogicalOrExpr(SpiceParser::LogicalOrExprContext for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // LogicalAndExpr - currentNode = logicalOrExprNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = logicalOrExprNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -884,7 +884,7 @@ std::any AstBuilderVisitor::visitLogicalAndExpr(SpiceParser::LogicalAndExprConte for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // BitwiseOr - currentNode = logicalAndExprNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = logicalAndExprNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -902,7 +902,7 @@ std::any AstBuilderVisitor::visitBitwiseOrExpr(SpiceParser::BitwiseOrExprContext for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // BitwiseXor - currentNode = bitwiseOrExprNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = bitwiseOrExprNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -920,7 +920,7 @@ std::any AstBuilderVisitor::visitBitwiseXorExpr(SpiceParser::BitwiseXorExprConte for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // BitwiseAnd - currentNode = bitwiseXorExprNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = bitwiseXorExprNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -938,7 +938,7 @@ std::any AstBuilderVisitor::visitBitwiseAndExpr(SpiceParser::BitwiseAndExprConte for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // EqualityExpr - currentNode = bitwiseAndExprNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = bitwiseAndExprNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -962,7 +962,7 @@ std::any AstBuilderVisitor::visitEqualityExpr(SpiceParser::EqualityExprContext * for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // RelationalExpr - currentNode = equalityExprNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = equalityExprNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -990,7 +990,7 @@ std::any AstBuilderVisitor::visitRelationalExpr(SpiceParser::RelationalExprConte for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // ShiftExpr - currentNode = relationalExprNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = relationalExprNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -1014,7 +1014,7 @@ std::any AstBuilderVisitor::visitShiftExpr(SpiceParser::ShiftExprContext *ctx) { for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // AdditiveExpr - currentNode = shiftExprNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = shiftExprNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -1032,7 +1032,7 @@ std::any AstBuilderVisitor::visitAdditiveExpr(SpiceParser::AdditiveExprContext * for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // MultiplicativeExpr - currentNode = additiveExprNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = additiveExprNode->createChild(CodeLoc(rule->start, fileName)); else if (auto t = dynamic_cast(subTree); t->getSymbol()->getType() == SpiceParser::PLUS) additiveExprNode->opQueue.emplace(AdditiveExprNode::OP_PLUS, SymbolType(TY_INVALID)); else if (auto t = dynamic_cast(subTree); t->getSymbol()->getType() == SpiceParser::MINUS) @@ -1054,7 +1054,7 @@ std::any AstBuilderVisitor::visitMultiplicativeExpr(SpiceParser::MultiplicativeE for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // CastExpr - currentNode = multiplicativeExprNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = multiplicativeExprNode->createChild(CodeLoc(rule->start, fileName)); else if (auto t = dynamic_cast(subTree); t->getSymbol()->getType() == SpiceParser::MUL) multiplicativeExprNode->opQueue.emplace(MultiplicativeExprNode::OP_MUL, SymbolType(TY_INVALID)); else if (auto t = dynamic_cast(subTree); t->getSymbol()->getType() == SpiceParser::DIV) @@ -1078,9 +1078,9 @@ std::any AstBuilderVisitor::visitCastExpr(SpiceParser::CastExprContext *ctx) { for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // PrefixUnaryExpr - currentNode = castExprNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = castExprNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) { // DataType - currentNode = castExprNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = castExprNode->createChild(CodeLoc(rule->start, fileName)); castExprNode->isCasted = true; } else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -1101,7 +1101,7 @@ std::any AstBuilderVisitor::visitPrefixUnaryExpr(SpiceParser::PrefixUnaryExprCon if (rule = dynamic_cast(subTree); rule != nullptr) // PrefixUnaryOp visit(rule); else if (rule = dynamic_cast(subTree); rule != nullptr) // PostfixUnaryExpr - currentNode = prefixUnaryExprNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = prefixUnaryExprNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -1119,11 +1119,11 @@ std::any AstBuilderVisitor::visitPostfixUnaryExpr(SpiceParser::PostfixUnaryExprC for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // AtomicExpr - currentNode = postfixUnaryExprNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = postfixUnaryExprNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // AssignExpr - currentNode = postfixUnaryExprNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = postfixUnaryExprNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // PostfixUnaryExpr - currentNode = postfixUnaryExprNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = postfixUnaryExprNode->createChild(CodeLoc(rule->start, fileName)); else if (auto t = dynamic_cast(subTree); t->getSymbol()->getType() == SpiceParser::LBRACKET) postfixUnaryExprNode->opQueue.emplace(PostfixUnaryExprNode::OP_SUBSCRIPT, SymbolType(TY_INVALID)); else if (auto t = dynamic_cast(subTree); t->getSymbol()->getType() == SpiceParser::DOT) @@ -1151,11 +1151,11 @@ std::any AstBuilderVisitor::visitAtomicExpr(SpiceParser::AtomicExprContext *ctx) for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // Value - currentNode = atomicExprNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = atomicExprNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // BuiltinCall visit(rule); else if (rule = dynamic_cast(subTree); rule != nullptr) // AssignExpr - currentNode = atomicExprNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = atomicExprNode->createChild(CodeLoc(rule->start, fileName)); else if (auto t = dynamic_cast(subTree); t->getSymbol()->getType() == SpiceParser::IDENTIFIER) atomicExprNode->identifier = t->getText(); else @@ -1175,15 +1175,15 @@ std::any AstBuilderVisitor::visitValue(SpiceParser::ValueContext *ctx) { for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // PrimitiveValue - currentNode = valueNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = valueNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // FunctionCall - currentNode = valueNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = valueNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // ArrayInitialization - currentNode = valueNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = valueNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // StructInstantiation - currentNode = valueNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = valueNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) { // DataType - currentNode = valueNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = valueNode->createChild(CodeLoc(rule->start, fileName)); valueNode->isNil = true; } else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -1256,10 +1256,10 @@ std::any AstBuilderVisitor::visitFunctionCall(SpiceParser::FunctionCallContext * for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) { // TypeLst - currentNode = fctCallNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = fctCallNode->createChild(CodeLoc(rule->start, fileName)); fctCallNode->isGeneric = true; } else if (rule = dynamic_cast(subTree); rule != nullptr) { // ArgLst - currentNode = fctCallNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = fctCallNode->createChild(CodeLoc(rule->start, fileName)); fctCallNode->hasArgs = true; } else if (auto t = dynamic_cast(subTree); t->getSymbol()->getType() == SpiceParser::IDENTIFIER) { @@ -1285,7 +1285,7 @@ std::any AstBuilderVisitor::visitArrayInitialization(SpiceParser::ArrayInitializ for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // ArgLst - currentNode = arrayInitializationNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = arrayInitializationNode->createChild(CodeLoc(rule->start, fileName)); else assert(dynamic_cast(subTree)); // Fail if we did not get a terminal @@ -1303,9 +1303,9 @@ std::any AstBuilderVisitor::visitStructInstantiation(SpiceParser::StructInstanti for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // TypeLst - currentNode = structInstantiationNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = structInstantiationNode->createChild(CodeLoc(rule->start, fileName)); else if (rule = dynamic_cast(subTree); rule != nullptr) // ArgLst - currentNode = structInstantiationNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = structInstantiationNode->createChild(CodeLoc(rule->start, fileName)); else if (auto t = dynamic_cast(subTree); t->getSymbol()->getType() == SpiceParser::IDENTIFIER) { std::string fragment = t->toString(); structInstantiationNode->structNameFragments.push_back(fragment); @@ -1330,7 +1330,7 @@ std::any AstBuilderVisitor::visitDataType(SpiceParser::DataTypeContext *ctx) { auto subTree = ctx->children[i]; antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // BaseDataType - currentNode = dataTypeNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = dataTypeNode->createChild(CodeLoc(rule->start, fileName)); else if (auto t = dynamic_cast(subTree); t->getSymbol()->getType() == SpiceParser::MUL) dataTypeNode->tmQueue.push({DataTypeNode::TYPE_PTR, false, false, 0}); else if (auto t = dynamic_cast(subTree); t->getSymbol()->getType() == SpiceParser::LBRACKET) { @@ -1342,7 +1342,7 @@ std::any AstBuilderVisitor::visitDataType(SpiceParser::DataTypeContext *ctx) { if (rule = dynamic_cast(subTree); rule != nullptr) { // AssignExpr hasSize = true; hardCodedSize = -1; - currentNode = dataTypeNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = dataTypeNode->createChild(CodeLoc(rule->start, fileName)); i++; // Consume INTEGER } else if (auto t = dynamic_cast(subTree); t->getSymbol()->getType() == SpiceParser::INT_LIT) { @@ -1370,7 +1370,7 @@ std::any AstBuilderVisitor::visitBaseDataType(SpiceParser::BaseDataTypeContext * antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) { // CustomDataType baseDataTypeNode->type = BaseDataTypeNode::TY_CUSTOM; - currentNode = baseDataTypeNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = baseDataTypeNode->createChild(CodeLoc(rule->start, fileName)); } else if (auto t = dynamic_cast(subTree); t->getSymbol()->getType() == SpiceParser::TYPE_DOUBLE) baseDataTypeNode->type = BaseDataTypeNode::TYPE_DOUBLE; @@ -1407,7 +1407,7 @@ std::any AstBuilderVisitor::visitCustomDataType(SpiceParser::CustomDataTypeConte for (const auto &subTree : ctx->children) { antlr4::ParserRuleContext *rule; if (rule = dynamic_cast(subTree); rule != nullptr) // TypeLst - currentNode = customDataTypeNode->createChild(CodeLoc(fileName, rule->start)); + currentNode = customDataTypeNode->createChild(CodeLoc(rule->start, fileName)); else if (auto t = dynamic_cast(subTree); t->getSymbol()->getType() == SpiceParser::IDENTIFIER) { std::string fragment = t->toString(); customDataTypeNode->typeNameFragments.push_back(fragment); @@ -1521,7 +1521,7 @@ int64_t AstBuilderVisitor::parseLong(antlr4::tree::TerminalNode *terminal) { int8_t AstBuilderVisitor::parseChar(antlr4::tree::TerminalNode *terminal) { std::string input = terminal->toString(); if (input.length() != 3) { - CodeLoc codeLoc = CodeLoc(fileName, terminal->getSymbol()); + CodeLoc codeLoc = CodeLoc(terminal->getSymbol(), fileName); throw err->get(codeLoc, PARSING_FAILED, "Invalid char literal " + input); } return input[1]; @@ -1564,10 +1564,10 @@ T AstBuilderVisitor::parseNumeric(antlr4::tree::TerminalNode *terminal, std::fun } return cb(input, 10); } catch (std::out_of_range &e) { - CodeLoc codeLoc = CodeLoc(fileName, terminal->getSymbol()); + CodeLoc codeLoc = CodeLoc(terminal->getSymbol(), fileName); throw err->get(codeLoc, NUMBER_OUT_OF_RANGE, "The provided number is out of range"); } catch (std::invalid_argument &e) { - CodeLoc codeLoc = CodeLoc(fileName, terminal->getSymbol()); + CodeLoc codeLoc = CodeLoc(terminal->getSymbol(), fileName); throw err->get(codeLoc, NUMBER_OUT_OF_RANGE, "You tried to parse '" + input + "' as an integer, but it was no integer"); } } \ No newline at end of file diff --git a/src/symbol/SymbolTable.cpp b/src/symbol/SymbolTable.cpp index dc2b5dc0a..c1d2ff962 100644 --- a/src/symbol/SymbolTable.cpp +++ b/src/symbol/SymbolTable.cpp @@ -336,13 +336,13 @@ void SymbolTable::insertFunction(const Function &function, ErrorFactory *err) { // Check if function is already substantiated if (function.hasSubstantiatedArgs()) { - insertSubstantiatedFunction(function, err, codeLoc); + insertSubstantiatedFunction(function, codeLoc); return; } // Substantiate the function and insert the substantiated instances for (const auto &fct : function.substantiateOptionalArgs()) - insertSubstantiatedFunction(fct, err, codeLoc); + insertSubstantiatedFunction(fct, codeLoc); } /** @@ -433,7 +433,7 @@ Function *SymbolTable::matchFunction(SymbolTable *currentScope, const std::strin // Duplicate function Function newFunction = f.substantiateGenerics(argList, callThisType, concreteGenericTypes); if (!getChild(newFunction.getSignature())) { // Insert function - insertSubstantiatedFunction(newFunction, err, f.getDeclCodeLoc()); + insertSubstantiatedFunction(newFunction, f.getDeclCodeLoc()); copyChildBlock(f.getSignature(), newFunction.getSignature()); // Insert symbols for generic type names with concrete types into the child block @@ -513,10 +513,9 @@ Function *SymbolTable::getFunctionAccessPointer(const CodeLoc &codeLoc) { * an exception will be thrown * * @param function Substantiated function - * @param err Error factory * @param codeLoc Code location */ -void SymbolTable::insertSubstantiatedFunction(const Function &function, ErrorFactory *err, const CodeLoc &codeLoc) { +void SymbolTable::insertSubstantiatedFunction(const Function &function, const CodeLoc &codeLoc) { if (!function.hasSubstantiatedArgs()) throw std::runtime_error("Internal compiler error: Expected substantiated function"); diff --git a/src/symbol/SymbolTable.h b/src/symbol/SymbolTable.h index f755ba135..f09ae2ee8 100644 --- a/src/symbol/SymbolTable.h +++ b/src/symbol/SymbolTable.h @@ -78,7 +78,7 @@ class SymbolTable { [[nodiscard]] std::map *getFunctionManifestations(const CodeLoc &defCodeLoc) const; void insertFunctionAccessPointer(const CodeLoc &codeLoc, Function *spiceFunc); Function *getFunctionAccessPointer(const CodeLoc &codeLoc); - void insertSubstantiatedFunction(const Function &function, ErrorFactory *err, const CodeLoc &codeLoc); + void insertSubstantiatedFunction(const Function &function, const CodeLoc &codeLoc); void insertStruct(const Struct &s, ErrorFactory *err); Struct *matchStruct(SymbolTable *currentScope, const std::string &structName, const std::vector &templateTypes, diff --git a/src/symbol/SymbolTableEntry.cpp b/src/symbol/SymbolTableEntry.cpp index 4d5ae2cb6..d73658c64 100644 --- a/src/symbol/SymbolTableEntry.cpp +++ b/src/symbol/SymbolTableEntry.cpp @@ -57,12 +57,12 @@ SymbolState SymbolTableEntry::getState() const { return state; } * * @throws SemanticError When trying to re-assign a constant variable * @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 err Error factory * @param codeLoc Code location where the update takes place * @param force Force update. This can only be used compiler-internal */ -void SymbolTableEntry::updateState(SymbolState newState, const ErrorFactory *err, const CodeLoc &codeLoc, bool force) { +void SymbolTableEntry::updateState(SymbolState newState, const CodeLoc &codeLoc, bool force) { // Check if this is a constant variable and is already initialized if (state == INITIALIZED && specifiers.isConst() && !force) throw ErrorFactory::get(codeLoc, REASSIGN_CONST_VARIABLE, "Not re-assignable variable '" + name + "'"); diff --git a/src/symbol/SymbolTableEntry.h b/src/symbol/SymbolTableEntry.h index 9e568e65c..4c59dd434 100644 --- a/src/symbol/SymbolTableEntry.h +++ b/src/symbol/SymbolTableEntry.h @@ -37,7 +37,7 @@ class SymbolTableEntry { [[nodiscard]] SymbolTable *getScope() const; [[nodiscard]] SymbolSpecifiers getSpecifiers() const; [[nodiscard]] SymbolState getState() const; - void updateState(SymbolState newState, const ErrorFactory *errorFactory, const CodeLoc &codeLoc, bool force = false); + void updateState(SymbolState newState, const CodeLoc &codeLoc, bool force = false); [[nodiscard]] const CodeLoc &getDeclCodeLoc() const; [[nodiscard]] llvm::Type *getStructLLVMType() const; void setStructLLVMType(llvm::Type *newStructType); diff --git a/src/util/CodeLoc.cpp b/src/util/CodeLoc.cpp index e94c2299b..b7fd32272 100644 --- a/src/util/CodeLoc.cpp +++ b/src/util/CodeLoc.cpp @@ -2,8 +2,27 @@ #include "CodeLoc.h" +/** + * Returns the code location as a string for using it as a map key or similar + * + * @return Code location string + */ std::string CodeLoc::toString() const { return "L" + std::to_string(line) + "C" + std::to_string(col); } -std::string CodeLoc::toPrettyString() const { return sourceFilePath + ":" + std::to_string(line) + ":" + std::to_string(col); } +/** + * Returns the code location in a pretty form + * + * @return Pretty code location + */ +std::string CodeLoc::toPrettyString() const { + if (sourceFilePath.empty()) + return std::to_string(line) + ":" + std::to_string(col); + return sourceFilePath + ":" + std::to_string(line) + ":" + std::to_string(col); +} +/** + * Returns the line number in a pretty form + * + * @return Pretty line number + */ std::string CodeLoc::toPrettyLine() const { return "l" + std::to_string(line); } \ No newline at end of file diff --git a/src/util/CodeLoc.h b/src/util/CodeLoc.h index 0a8afb3d5..114c87998 100644 --- a/src/util/CodeLoc.h +++ b/src/util/CodeLoc.h @@ -10,10 +10,10 @@ struct CodeLoc { public: // Constructors - CodeLoc(std::string sourceFilePath, size_t line, size_t col) - : sourceFilePath(std::move(sourceFilePath)), line(line), col(col) {} - explicit CodeLoc(std::string sourceFilePath, const antlr4::Token *token) - : sourceFilePath(std::move(sourceFilePath)), line(token->getLine()), col(token->getCharPositionInLine() + 1) {} + CodeLoc(size_t line, size_t col, std::string sourceFilePath = "") + : line(line), col(col), sourceFilePath(std::move(sourceFilePath)) {} + explicit CodeLoc(const antlr4::Token *token, std::string sourceFilePath = "") + : line(token->getLine()), col(token->getCharPositionInLine() + 1), sourceFilePath(std::move(sourceFilePath)) {} // Public members std::string sourceFilePath; diff --git a/std/net/http.spice b/std/net/http.spice new file mode 100644 index 000000000..3a67352d9 --- /dev/null +++ b/std/net/http.spice @@ -0,0 +1,44 @@ +import "socket_linux" as sock; + +const string SERVER_IDENT = "Spice HTTP Server/0.0.0"; +const unsigned int CONNECTIONS_LIMIT = 50; + +public const string ADDR_LOCAL = "localhost"; +public const string ADDR_INET = "0.0.0.0"; + +public const unsigned short HTTP_PORT_DEFAULT = 80s; +public const unsigned short HTTP_PORT_FALLBACK = 8080s; +public const unsigned short HTTPS_PORT_DEFAULT = 443s; + +/** + * Struct, representing a simple HTTP server + */ +public type HttpServer struct { + sock::Socket socket // Underlying TCP socket + unsigned short port // Exposed port + bool initialized // true if the server was initialized +} + +/** + * Used to initialize a HTTP server instance, listening on a specific port for incoming requests + */ +public p HttpServer.ctor(unsigned short port = HTTP_PORT_DEFAULT) { + this.port = port; + initialized = true; +} + +/** + * + */ +public f HttpServer.start() { + // Check if the server is initialized + if !this.initialized { return false; } + + // Setup TCP socket + this.socket = sock.openServerSocket(port, CONNECTIONS_LIMIT); + +} + +public f HttpServer.serve(string path, string htmlContent) { + +} \ No newline at end of file diff --git a/std/net/socket_linux.spice b/std/net/socket_linux.spice index c135b13e7..1cf92b168 100644 --- a/std/net/socket_linux.spice +++ b/std/net/socket_linux.spice @@ -39,6 +39,10 @@ ext htons(short); // Fairly simple to re-implement in Spice ext inet_addr(string); ext connect(int, SockAddrIn*, int); +public p Socket.dtor() { + this.close(); +} + /** * Accept an incoming connection to the socket and save the connection file desceiptor * to the socket object. diff --git a/std/net/socket_windows.spice b/std/net/socket_windows.spice index 2f9fd86a9..80835cf1e 100644 --- a/std/net/socket_windows.spice +++ b/std/net/socket_windows.spice @@ -50,6 +50,10 @@ ext close(long); ext htonl(int); // Fairly simple to re-implement in Spice ext htons(short); // Fairly simple to re-implement in Spice +public p Socket.dtor() { + this.close(); +} + /** * Accept an incoming connection to the socket and save the connection file desceiptor * to the socket object. diff --git a/test/test-files/analyzer/lexer/error-lexing-error/exception.out b/test/test-files/analyzer/lexer/error-lexing-error/exception.out index f194c10fe..85ec2ba7a 100644 --- a/test/test-files/analyzer/lexer/error-lexing-error/exception.out +++ b/test/test-files/analyzer/lexer/error-lexing-error/exception.out @@ -1 +1 @@ -Error in :1:0: Tokenizing failed: token recognition error at: '"test' \ No newline at end of file +Error in 1:0: Tokenizing failed: token recognition error at: '"test' \ No newline at end of file diff --git a/test/test-files/analyzer/parser/error-parsing-error/exception.out b/test/test-files/analyzer/parser/error-parsing-error/exception.out index 045c458f4..86fdfc2ae 100644 --- a/test/test-files/analyzer/parser/error-parsing-error/exception.out +++ b/test/test-files/analyzer/parser/error-parsing-error/exception.out @@ -1 +1 @@ -Error in :1:1: Parsing failed: no viable alternative at input 'f' \ No newline at end of file +Error in 1:1: Parsing failed: no viable alternative at input 'f' \ No newline at end of file diff --git a/test/test-files/analyzer/threads/error-invalid-tid/exception.out b/test/test-files/analyzer/threads/error-invalid-tid/exception.out index fe496c5bb..5d92ec748 100644 --- a/test/test-files/analyzer/threads/error-invalid-tid/exception.out +++ b/test/test-files/analyzer/threads/error-invalid-tid/exception.out @@ -1 +1 @@ -Error in :2:11: Parsing failed: no viable alternative at input 'thread"non-integer"' \ No newline at end of file +Error in 2:11: Parsing failed: no viable alternative at input 'thread"non-integer"' \ No newline at end of file diff --git a/test/test-files/generator/structs/success-struct-in-place/cout.out b/test/test-files/generator/structs/success-struct-in-place/cout.out index 5f41d3337..70548b2cd 100644 --- a/test/test-files/generator/structs/success-struct-in-place/cout.out +++ b/test/test-files/generator/structs/success-struct-in-place/cout.out @@ -1 +1,2 @@ -Shopping cart item 1: Rice \ No newline at end of file +Shopping cart item 1: Rice +Another cart item 2 unit: pcs diff --git a/test/test-files/generator/structs/success-struct-in-place/disabled b/test/test-files/generator/structs/success-struct-in-place/disabled deleted file mode 100644 index e69de29bb..000000000 diff --git a/test/test-files/generator/structs/success-struct-in-place/ir-code.ll b/test/test-files/generator/structs/success-struct-in-place/ir-code.ll index e69de29bb..04c798978 100644 --- a/test/test-files/generator/structs/success-struct-in-place/ir-code.ll +++ b/test/test-files/generator/structs/success-struct-in-place/ir-code.ll @@ -0,0 +1,150 @@ +; ModuleID = 'source.spice' +source_filename = "source.spice" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%_s__ShoppingCart__string_ShoppingItemarray = type { ptr, [3 x %_s__ShoppingItem__string_double_string] } +%_s__ShoppingItem__string_double_string = type { ptr, double, ptr } + +@0 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1 +@1 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1 +@2 = private unnamed_addr constant [10 x i8] c"Spaghetti\00", align 1 +@3 = private unnamed_addr constant [2 x i8] c"g\00", align 1 +@4 = private unnamed_addr constant [5 x i8] c"Rice\00", align 1 +@5 = private unnamed_addr constant [2 x i8] c"g\00", align 1 +@6 = private unnamed_addr constant [9 x i8] c"Doughnut\00", align 1 +@7 = private unnamed_addr constant [4 x i8] c"pcs\00", align 1 +@8 = private unnamed_addr constant [14 x i8] c"Shopping Cart\00", align 1 +@9 = private unnamed_addr constant [10 x i8] c"Spaghetti\00", align 1 +@10 = private unnamed_addr constant [2 x i8] c"g\00", align 1 +@11 = private unnamed_addr constant [5 x i8] c"Rice\00", align 1 +@12 = private unnamed_addr constant [2 x i8] c"g\00", align 1 +@13 = private unnamed_addr constant [9 x i8] c"Doughnut\00", align 1 +@14 = private unnamed_addr constant [4 x i8] c"pcs\00", align 1 +@15 = private unnamed_addr constant [13 x i8] c"Another Cart\00", align 1 +@16 = private unnamed_addr constant [26 x i8] c"Shopping cart item 1: %s\0A\00", align 1 +@17 = private unnamed_addr constant [30 x i8] c"Another cart item 2 unit: %s\0A\00", align 1 + +define internal %_s__ShoppingCart__string_ShoppingItemarray @_f__void__newShoppingCart() { +entry.l14: + %result = alloca %_s__ShoppingCart__string_ShoppingItemarray, align 8 + %0 = alloca %_s__ShoppingItem__string_double_string, align 8 + %1 = getelementptr inbounds %_s__ShoppingItem__string_double_string, ptr %0, i32 0, i32 0 + store ptr @0, ptr %1, align 8 + %2 = getelementptr inbounds %_s__ShoppingItem__string_double_string, ptr %0, i32 0, i32 1 + store double 0.000000e+00, ptr %2, align 8 + %3 = getelementptr inbounds %_s__ShoppingItem__string_double_string, ptr %0, i32 0, i32 2 + store ptr @1, ptr %3, align 8 + %items = alloca [3 x %_s__ShoppingItem__string_double_string], align 8 + store [3 x %_s__ShoppingItem__string_double_string] [%_s__ShoppingItem__string_double_string { ptr @0, double 0.000000e+00, ptr @1 }, %_s__ShoppingItem__string_double_string { ptr @0, double 0.000000e+00, ptr @1 }, %_s__ShoppingItem__string_double_string { ptr @0, double 0.000000e+00, ptr @1 }], ptr %items, align 8 + %4 = alloca %_s__ShoppingItem__string_double_string, align 8 + %5 = getelementptr inbounds %_s__ShoppingItem__string_double_string, ptr %4, i32 0, i32 0 + store ptr @2, ptr %5, align 8 + %6 = getelementptr inbounds %_s__ShoppingItem__string_double_string, ptr %4, i32 0, i32 1 + store double 1.000000e+02, ptr %6, align 8 + %7 = getelementptr inbounds %_s__ShoppingItem__string_double_string, ptr %4, i32 0, i32 2 + store ptr @3, ptr %7, align 8 + %8 = load %_s__ShoppingItem__string_double_string, ptr %4, align 8 + %9 = getelementptr inbounds [3 x %_s__ShoppingItem__string_double_string], ptr %items, i32 0, i32 0 + store %_s__ShoppingItem__string_double_string %8, ptr %9, align 8 + %10 = alloca %_s__ShoppingItem__string_double_string, align 8 + %11 = getelementptr inbounds %_s__ShoppingItem__string_double_string, ptr %10, i32 0, i32 0 + store ptr @4, ptr %11, align 8 + %12 = getelementptr inbounds %_s__ShoppingItem__string_double_string, ptr %10, i32 0, i32 1 + store double 1.255000e+02, ptr %12, align 8 + %13 = getelementptr inbounds %_s__ShoppingItem__string_double_string, ptr %10, i32 0, i32 2 + store ptr @5, ptr %13, align 8 + %14 = load %_s__ShoppingItem__string_double_string, ptr %10, align 8 + %15 = getelementptr inbounds [3 x %_s__ShoppingItem__string_double_string], ptr %items, i32 0, i32 1 + store %_s__ShoppingItem__string_double_string %14, ptr %15, align 8 + %16 = alloca %_s__ShoppingItem__string_double_string, align 8 + %17 = getelementptr inbounds %_s__ShoppingItem__string_double_string, ptr %16, i32 0, i32 0 + store ptr @6, ptr %17, align 8 + %18 = getelementptr inbounds %_s__ShoppingItem__string_double_string, ptr %16, i32 0, i32 1 + store double 6.000000e+00, ptr %18, align 8 + %19 = getelementptr inbounds %_s__ShoppingItem__string_double_string, ptr %16, i32 0, i32 2 + store ptr @7, ptr %19, align 8 + %20 = load %_s__ShoppingItem__string_double_string, ptr %16, align 8 + %21 = getelementptr inbounds [3 x %_s__ShoppingItem__string_double_string], ptr %items, i32 0, i32 2 + store %_s__ShoppingItem__string_double_string %20, ptr %21, align 8 + %22 = alloca %_s__ShoppingCart__string_ShoppingItemarray, align 8 + %23 = getelementptr inbounds %_s__ShoppingCart__string_ShoppingItemarray, ptr %22, i32 0, i32 0 + store ptr @8, ptr %23, align 8 + %24 = load [3 x %_s__ShoppingItem__string_double_string], ptr %items, align 8 + %25 = getelementptr inbounds %_s__ShoppingCart__string_ShoppingItemarray, ptr %22, i32 0, i32 1 + store [3 x %_s__ShoppingItem__string_double_string] %24, ptr %25, align 8 + %26 = load %_s__ShoppingCart__string_ShoppingItemarray, ptr %22, align 8 + ret %_s__ShoppingCart__string_ShoppingItemarray %26 +} + +define internal %_s__ShoppingCart__string_ShoppingItemarray @_f__void__anotherShoppingCart() { +entry.l22: + %result = alloca %_s__ShoppingCart__string_ShoppingItemarray, align 8 + %0 = alloca %_s__ShoppingItem__string_double_string, align 8 + %1 = getelementptr inbounds %_s__ShoppingItem__string_double_string, ptr %0, i32 0, i32 0 + store ptr @9, ptr %1, align 8 + %2 = getelementptr inbounds %_s__ShoppingItem__string_double_string, ptr %0, i32 0, i32 1 + store double 1.000000e+02, ptr %2, align 8 + %3 = getelementptr inbounds %_s__ShoppingItem__string_double_string, ptr %0, i32 0, i32 2 + store ptr @10, ptr %3, align 8 + %4 = load %_s__ShoppingItem__string_double_string, ptr %0, align 8 + %5 = alloca %_s__ShoppingItem__string_double_string, align 8 + %6 = getelementptr inbounds %_s__ShoppingItem__string_double_string, ptr %5, i32 0, i32 0 + store ptr @11, ptr %6, align 8 + %7 = getelementptr inbounds %_s__ShoppingItem__string_double_string, ptr %5, i32 0, i32 1 + store double 1.255000e+02, ptr %7, align 8 + %8 = getelementptr inbounds %_s__ShoppingItem__string_double_string, ptr %5, i32 0, i32 2 + store ptr @12, ptr %8, align 8 + %9 = load %_s__ShoppingItem__string_double_string, ptr %5, align 8 + %10 = alloca %_s__ShoppingItem__string_double_string, align 8 + %11 = getelementptr inbounds %_s__ShoppingItem__string_double_string, ptr %10, i32 0, i32 0 + store ptr @13, ptr %11, align 8 + %12 = getelementptr inbounds %_s__ShoppingItem__string_double_string, ptr %10, i32 0, i32 1 + store double 6.000000e+00, ptr %12, align 8 + %13 = getelementptr inbounds %_s__ShoppingItem__string_double_string, ptr %10, i32 0, i32 2 + store ptr @14, ptr %13, align 8 + %14 = load %_s__ShoppingItem__string_double_string, ptr %10, align 8 + %15 = alloca [3 x %_s__ShoppingItem__string_double_string], align 8 + %16 = getelementptr inbounds [3 x %_s__ShoppingItem__string_double_string], ptr %15, i32 0, i32 0 + store %_s__ShoppingItem__string_double_string %4, ptr %16, align 8 + %17 = getelementptr inbounds [3 x %_s__ShoppingItem__string_double_string], ptr %15, i32 0, i32 1 + store %_s__ShoppingItem__string_double_string %9, ptr %17, align 8 + %18 = getelementptr inbounds [3 x %_s__ShoppingItem__string_double_string], ptr %15, i32 0, i32 2 + store %_s__ShoppingItem__string_double_string %14, ptr %18, align 8 + %19 = alloca %_s__ShoppingCart__string_ShoppingItemarray, align 8 + %20 = getelementptr inbounds %_s__ShoppingCart__string_ShoppingItemarray, ptr %19, i32 0, i32 0 + store ptr @15, ptr %20, align 8 + %21 = load [3 x %_s__ShoppingItem__string_double_string], ptr %15, align 8 + %22 = getelementptr inbounds %_s__ShoppingCart__string_ShoppingItemarray, ptr %19, i32 0, i32 1 + store [3 x %_s__ShoppingItem__string_double_string] %21, ptr %22, align 8 + %23 = load %_s__ShoppingCart__string_ShoppingItemarray, ptr %19, align 8 + ret %_s__ShoppingCart__string_ShoppingItemarray %23 +} + +define i32 @main() { +entry.l31: + %result = alloca i32, align 4 + store i32 0, ptr %result, align 4 + %0 = call %_s__ShoppingCart__string_ShoppingItemarray @_f__void__newShoppingCart() + %1 = alloca %_s__ShoppingCart__string_ShoppingItemarray, align 8 + store %_s__ShoppingCart__string_ShoppingItemarray %0, ptr %1, align 8 + %2 = getelementptr inbounds %_s__ShoppingCart__string_ShoppingItemarray, ptr %1, i32 0, i32 1 + %3 = getelementptr inbounds [3 x %_s__ShoppingItem__string_double_string], ptr %2, i32 0, i32 1 + %4 = getelementptr inbounds %_s__ShoppingItem__string_double_string, ptr %3, i32 0, i32 0 + %5 = load ptr, ptr %4, align 8 + %6 = call i32 (ptr, ...) @printf(ptr @16, ptr %5) + %7 = call %_s__ShoppingCart__string_ShoppingItemarray @_f__void__anotherShoppingCart() + %8 = alloca %_s__ShoppingCart__string_ShoppingItemarray, align 8 + store %_s__ShoppingCart__string_ShoppingItemarray %7, ptr %8, align 8 + %9 = load %_s__ShoppingCart__string_ShoppingItemarray, ptr %8, align 8 + store %_s__ShoppingCart__string_ShoppingItemarray %9, ptr %1, align 8 + %10 = getelementptr inbounds %_s__ShoppingCart__string_ShoppingItemarray, ptr %1, i32 0, i32 1 + %11 = getelementptr inbounds [3 x %_s__ShoppingItem__string_double_string], ptr %10, i32 0, i32 2 + %12 = getelementptr inbounds %_s__ShoppingItem__string_double_string, ptr %11, i32 0, i32 2 + %13 = load ptr, ptr %12, align 8 + %14 = call i32 (ptr, ...) @printf(ptr @17, ptr %13) + %15 = load i32, ptr %result, align 4 + ret i32 %15 +} + +declare i32 @printf(ptr, ...) diff --git a/test/test-files/std/examples/game-of-life/cout.out b/test/test-files/std/examples/game-of-life/cout.out index 134138768..1ba5b4f29 100644 --- a/test/test-files/std/examples/game-of-life/cout.out +++ b/test/test-files/std/examples/game-of-life/cout.out @@ -1,115 +1,115 @@ Initial state: ╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮ -│ 1 ││ 0 ││ 1 ││ 1 ││ 1 ││ 1 ││ 0 ││ 0 ││ 1 ││ 1 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 0 ││ 1 ││ 0 ││ 1 ││ 1 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 1 ││ 0 ││ 1 ││ 1 ││ 0 ││ 0 ││ 0 ││ 1 ││ 1 ││ 1 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 1 ││ 0 ││ 0 ││ 0 ││ 1 ││ 1 ││ 1 ││ 0 ││ 1 ││ 0 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 1 ││ 1 ││ 1 ││ 1 ││ 0 ││ 1 ││ 0 ││ 0 ││ 1 ││ 0 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 1 ││ 0 ││ 1 ││ 0 ││ 0 ││ 1 ││ 0 ││ 0 ││ 0 ││ 1 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 1 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 1 ││ 1 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 0 ││ 1 ││ 0 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 1 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 1 ││ 0 ││ 1 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 0 ││ 0 ││ 0 ││ 0 ││ 1 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 │ ╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯ Next generation: ╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮ -│ 0 ││ 1 ││ 1 ││ 0 ││ 0 ││ 1 ││ 0 ││ 0 ││ 0 ││ 0 │ +│ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 1 ││ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 0 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 1 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 1 ││ 0 ││ 1 ││ 0 ││ 0 ││ 0 ││ 1 ││ 1 ││ 1 ││ 1 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 1 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 1 ││ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 1 ││ 0 ││ 0 ││ 0 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 1 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 1 ││ 0 ││ 1 ││ 1 ││ 0 ││ 0 ││ 0 ││ 1 ││ 1 ││ 1 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 1 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 1 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 1 ││ 0 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 1 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 0 ││ 1 ││ 0 ││ 0 ││ 0 ││ 1 ││ 0 ││ 0 ││ 0 ││ 0 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 1 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 1 ││ 1 ││ 1 ││ 0 ││ 1 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 1 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 0 │ +│ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 │ ╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯ Next generation: ╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮ -│ 0 ││ 1 ││ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 0 ││ 0 ││ 0 │ +│ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 1 ││ 0 ││ 1 ││ 0 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 0 │ +│ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 1 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 1 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 0 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 0 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 1 ││ 0 ││ 1 ││ 1 ││ 0 ││ 1 ││ 0 ││ 0 ││ 0 ││ 0 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 0 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 0 ││ 1 ││ 0 ││ 0 ││ 1 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 0 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 0 ││ 1 ││ 1 ││ 1 ││ 0 ││ 0 ││ 0 ││ 1 ││ 0 ││ 1 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 0 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 0 ││ 0 ││ 0 ││ 0 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 0 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 0 ││ 0 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 0 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 1 ││ 1 ││ 1 ││ 1 ││ 0 │ +│ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 1 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 1 ││ 1 ││ 1 ││ 0 │ +│ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 │ ╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯ Next generation: ╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮ -│ 0 ││ 1 ││ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 0 ││ 0 ││ 0 │ +│ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 1 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 1 ││ 0 ││ 0 │ +│ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 1 ││ 0 ││ 1 ││ 1 ││ 1 ││ 0 ││ 1 ││ 0 ││ 0 ││ 0 │ +│ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 0 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 1 ││ 0 ││ 1 ││ 1 ││ 0 ││ 1 ││ 1 ││ 0 ││ 1 ││ 0 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 1 ││ 0 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 1 ││ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 0 ││ 0 ││ 0 ││ 0 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 1 ││ 0 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 0 ││ 1 ││ 1 ││ 1 ││ 0 ││ 1 ││ 0 ││ 0 ││ 0 ││ 0 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 1 ││ 0 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 0 ││ 0 ││ 1 ││ 0 ││ 0 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 1 ││ 0 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 0 ││ 0 ││ 1 ││ 1 ││ 0 │ +│ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 0 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 │ +│ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 0 ││ 0 ││ 0 ││ 1 ││ 0 │ +│ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 │ ╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯ Next generation: ╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮╭─────╮ -│ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 1 ││ 0 ││ 0 │ +│ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 1 ││ 0 ││ 1 ││ 1 ││ 0 ││ 0 ││ 1 ││ 1 ││ 0 ││ 0 │ +│ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 │ +│ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 1 ││ 0 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 1 ││ 0 ││ 1 ││ 0 ││ 0 ││ 0 ││ 1 ││ 1 ││ 0 ││ 0 │ +│ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 1 ││ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 0 ││ 0 ││ 0 ││ 0 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 0 ││ 0 ││ 1 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 0 ││ 1 ││ 1 ││ 1 ││ 1 ││ 1 ││ 1 ││ 0 ││ 0 ││ 0 │ +│ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 0 ││ 0 ││ 1 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 0 ││ 1 ││ 1 ││ 0 ││ 1 ││ 1 ││ 1 ││ 0 ││ 1 ││ 0 │ +│ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 0 ││ 0 ││ 0 ││ 1 ││ 0 ││ 1 ││ 0 ││ 1 ││ 1 ││ 0 │ +│ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 1 ││ 1 ││ 0 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ -│ 0 ││ 0 ││ 0 ││ 1 ││ 1 ││ 1 ││ 0 ││ 1 ││ 1 ││ 0 │ +│ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 │ ├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤├─────┤ │ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 ││ 0 │ ╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯╰─────╯ diff --git a/test/test-files/std/examples/game-of-life/source.spice b/test/test-files/std/examples/game-of-life/source.spice index 07a447ad3..ca0c2574f 100644 --- a/test/test-files/std/examples/game-of-life/source.spice +++ b/test/test-files/std/examples/game-of-life/source.spice @@ -1,9 +1,14 @@ -import "std/math/rand" as rand; - const int row = 10; const int col = 10; const int generationsToCalculate = 5; +int randCount = 0; + +f genFakeRandInt() { + randCount++; + return randCount % 2; +} + p rowLineTop() { printf("\n"); for int i = 0; i < col; i++ { printf("╭─────╮"); } @@ -58,7 +63,7 @@ f main() { // Generate matrix canvas with random values (live and dead cells) for int i = 0; i < row; i++ { for int j = 0; j < col; j++ { - a[i][j] = rand.randInt(0, 1); + a[i][j] = genFakeRandInt(); } } printGeneration("Initial state", a); diff --git a/test/test-files/std/examples/graph-coloring/cout.out b/test/test-files/std/examples/graph-coloring/cout.out new file mode 100644 index 000000000..e1fccc56e --- /dev/null +++ b/test/test-files/std/examples/graph-coloring/cout.out @@ -0,0 +1,3 @@ +Solution Exists: +Following are the assigned colors: + 1 2 3 2 diff --git a/test/test-files/std/examples/graph-coloring/source.spice b/test/test-files/std/examples/graph-coloring/source.spice new file mode 100644 index 000000000..0c4afd7b3 --- /dev/null +++ b/test/test-files/std/examples/graph-coloring/source.spice @@ -0,0 +1,78 @@ +const int VERTEX_COUNT = 4; + +p printSolution(int[] color) { + printf("Solution Exists:\nFollowing are the assigned colors:\n"); + for int i = 0; i < VERTEX_COUNT; i++ { + printf(" %d ", color[i]); + } + printf("\n"); +} + +f isSafe(bool[VERTEX_COUNT][VERTEX_COUNT] graph, int[] color) { + for int i = 0; i < VERTEX_COUNT; i++ { + for int j = i + 1; j < VERTEX_COUNT; j++ { + if graph[i][j] && color[j] == color[i] { + return false; + } + } + } + return true; +} + +f graphColoring( + bool[VERTEX_COUNT][VERTEX_COUNT] graph, + int m, + int i, + int[VERTEX_COUNT] color +) { + // If current index reached the end + if i == VERTEX_COUNT { + // If coloring is safe + if isSafe(graph, color) { + printSolution(color); + return true; + } + return false; + } + + for int j = 1; j <= m; j++ { + color[i] = j; + + // Recur of the rest vertices + if graphColoring(graph, m, i + 1, color) { + return true; + } + + color[i] = 0; + } + + return false; +} + +f main() { + /* Create following graph and + test whether it is 3 colorable + (3)---(2) + | / | + | / | + | / | + (0)---(1) + */ + bool[VERTEX_COUNT][VERTEX_COUNT] graph = { + { false, true, true, true }, + { true, false, true, false }, + { true, true, false, true }, + { true, false, true, false } + }; + int m = 3; // Number of colors + + // Initialize all color values as 0. + int[VERTEX_COUNT] color; + for int i = 0; i < VERTEX_COUNT; i++ { + color[i] = 0; + } + + if !graphColoring(graph, m, 0, color) { + printf("Solution does not exist"); + } +} \ No newline at end of file diff --git a/test/test-files/std/examples/rule-110/cout.out b/test/test-files/std/examples/rule-110/cout.out index f3a9a52b4..6feb987ae 100644 --- a/test/test-files/std/examples/rule-110/cout.out +++ b/test/test-files/std/examples/rule-110/cout.out @@ -1,98 +1,78 @@ - * - ** - *** - ** * - ***** - ** * - *** ** - ** * *** - ******* * - ** *** - *** ** * - ** * ***** - ***** ** * - ** * *** ** - *** **** * *** - ** * ** ***** * - ******** ** *** - ** **** ** * - *** ** * ***** - ** * *** **** * - ***** ** *** * ** - ** * ***** * ** *** - *** ** ** ******** * - ** * ****** ** *** - ******* * *** ** * - ** * **** * ***** - *** ** ** *** ** * - ** * *** *** ** * *** ** - ***** ** *** ****** ** * *** - ** * ***** *** ******** * - *** **** *** * ** *** - ** * ** * ** *** *** ** * - ******** ** ***** * ** * ***** - ** ****** ******** ** * - *** ** * ** * *** ** - ** * *** ** *** ** ** * *** - ***** ** * ***** * ********** * - ** * ***** ** *** ** *** - *** ** ** **** ** * *** ** * - ** * ****** ** * ***** ** * ***** - ******* * *** **** ****** ** * - ** * **** *** * ** * *** ** - *** ** ** *** * ** *** ** ** * *** - ** * *** *** ** ******** * *** ******* * - ***** ** *** ****** *** ** * ** *** - ** * ***** *** * ** ********* ** * - *** **** *** * ** ***** * ***** - ** * ** * ** *** *** ** * ** ** * - ******** ** ***** * ** * *** ** *** *** ** - ** ****** ******** ** * *** ** *** * *** - *** ** * ** ******** * ***** ***** * - ** * *** ** *** ** *** ** *** *** - ***** ** * ***** * *** ** * *** ** * ** * - ** * ***** ** *** ** * ******* * ***** ***** - *** ** ** **** ** * ***** ** ***** *** * - ** * ****** ** * ***** ** * *** ** * ** * ** - ******* * *** **** **** ** ** * *** ** ***** *** - ** * **** *** * ** * ******** ** * ***** *** * - *** ** ** *** * ** *** **** * ******* * ** *** - ** * *** *** ** ******** *** * **** * ** ***** * - ***** ** *** ****** *** * ** ** * ** ***** *** - ** * ***** *** * ** ****** *** ** ***** * ** * - *** **** *** * ** ***** * ** **** ** * ** ***** - ** * ** * ** *** *** ** * ** ***** * *** ** ***** * - ******** ** ***** * ** * *** ** ***** * **** * ***** * ** - ** ****** ******** ** * *** ** * **** ***** * ** *** - *** ** * ** ******** **** ** ** * ** * ** ***** * - ** * *** ** *** ** *** * ****** ***** ** ***** *** - ***** ** * ***** * *** ** * **** *** * ***** * ** * - ** * ***** ** *** ** * ******* * ** * **** * ** ***** - *** ** ** **** ** * ***** ** * ** ***** ** * ** ***** * - ** * ****** ** * ***** ** * *** ***** ** **** ** ***** * ** - ******* * *** **** **** ** ** * ** **** ** ****** * ** *** - ** * **** *** * ** * ******** *** ** * *** ** * ** ***** * - *** ** ** *** * ** *** **** * ** * *** **** **** ** ***** *** - ** * *** *** ** ******** *** * ********* *** *** * ***** * ** * - ***** ** *** ****** *** * ** ** *** * ** * ** ** * ** ***** - ** * ***** *** * ** ****** *** ** ************** ** ***** * - *** **** *** * ** ***** * ** * ***** * ***** * ** - ** * ** * ** *** *** ** * ** ***** ** * **** * ** *** - ******** ** ***** * ** * *** ** ***** * *** ** ** * ** ***** * - ** ****** ******** ** * *** ** * ** ** * *** *** ** ***** *** - *** ** * ** ******** **** ** *** ******* * ** ****** * ** * - ** * *** ** *** ** *** * ***** *** *** ***** * ** ***** - ***** ** * ***** * *** ** * **** *** * ** * ** * ** ***** * - ** * ***** ** *** ** * ******* * ** *** ***** *** ** ***** * ** - *** ** ** **** ** * ***** ** * ** ***** * ** * ** * *** ** * ** *** - ** * ****** ** * ***** ** * *** ******* *** *** ** ******* **** ** ***** * - ******* * *** **** **** ** ** * ** * ** *** * *** ** *** * ***** *** - ** * **** *** * ** * ******** *** ** ***** ***** * *** ** * **** * ** * - *** ** ** *** * ** *** **** * ** * ***** *** ***** * ******* * ** ***** - ** * *** *** ** ******** *** * ******* ** * ** * ** *** ** * ** ***** * - ***** ** *** ****** *** * ** ** * *** ** ***** *** ** * *** ******* * ** - ** * ***** *** * ** ****** *** **** * ***** *** * ******* * ** * ** *** - *** **** *** * ** ***** * ** * ** ***** * ** ***** *** *** ** ***** * - ** * ** * ** *** *** ** * ** ***** *** ** * ** ***** * ** * ** * ***** *** - ******** ** ***** * ** * *** ** ***** * ** **** ** ***** * ** ********** ** * ** * - ** ****** ******** ** * *** ** * ******* * ***** * ** *** ** * *** ** ***** + * + ** + *** + ** * + ***** + ** * + *** ** + ** * *** + ******* * + ** *** + *** ** * + ** * ***** + ***** ** * + ** * *** ** + *** **** * *** + ** * ** ***** * + ******** ** *** + ** **** ** * + *** ** * ***** + ** * *** **** * + ***** ** *** * ** + ** * ***** * ** *** + *** ** ** ******** * + ** * ****** ** *** + ******* * *** ** * + ** * **** * ***** + *** ** ** *** ** * + ** * *** *** ** * *** ** + ***** ** *** ****** ** * *** + ** * ***** *** ******** * + *** **** *** * ** *** + ** * ** * ** *** *** ** * + ******** ** ***** * ** * ***** + ** ****** ******** ** * + *** ** * ** * *** ** + ** * *** ** *** ** ** * *** + ***** ** * ***** * ********** * + ** * ***** ** *** ** *** + *** ** ** **** ** * *** ** * + ** * ****** ** * ***** ** * ***** + ******* * *** **** ****** ** * + ** * **** *** * ** * *** ** + *** ** ** *** * ** *** ** ** * *** + ** * *** *** ** ******** * *** ******* * + ***** ** *** ****** *** ** * ** *** + ** * ***** *** * ** ********* ** * + *** **** *** * ** ***** * ***** + ** * ** * ** *** *** ** * ** ** * + ******** ** ***** * ** * *** ** *** *** ** + ** ****** ******** ** * *** ** *** * *** + *** ** * ** ******** * ***** ***** * + ** * *** ** *** ** *** ** *** *** + ***** ** * ***** * *** ** * *** ** * ** * + ** * ***** ** *** ** * ******* * ***** ***** + *** ** ** **** ** * ***** ** ***** *** * + ** * ****** ** * ***** ** * *** ** * ** * ** + ******* * *** **** **** ** ** * *** ** ***** *** + ** * **** *** * ** * ******** ** * ***** *** * + *** ** ** *** * ** *** **** * ******* * ** *** + ** * *** *** ** ******** *** * **** * ** ***** * + ***** ** *** ****** *** * ** ** * ** ***** *** + ** * ***** *** * ** ****** *** ** ***** * ** * + *** **** *** * ** ***** * ** **** ** * ** ***** + ** * ** * ** *** *** ** * ** ***** * *** ** ***** * + ******** ** ***** * ** * *** ** ***** * **** * ***** * ** + ** ****** ******** ** * *** ** * **** ***** * ** *** + *** ** * ** ******** **** ** ** * ** * ** ***** * + ** * *** ** *** ** *** * ****** ***** ** ***** *** + ***** ** * ***** * *** ** * **** *** * ***** * ** * + ** * ***** ** *** ** * ******* * ** * **** * ** ***** + *** ** ** **** ** * ***** ** * ** ***** ** * ** ***** * + ** * ****** ** * ***** ** * *** ***** ** **** ** ***** * ** + ******* * *** **** **** ** ** * ** **** ** ****** * ** *** + ** * **** *** * ** * ******** *** ** * *** ** * ** ***** * + *** ** ** *** * ** *** **** * ** * *** **** **** ** ***** *** + ** * *** *** ** ******** *** * ********* *** *** * ***** * ** * + ***** ** *** ****** *** * ** ** *** * ** * ** ** * ** ***** + ** * ***** *** * ** ****** *** ** ************** ** ***** * diff --git a/test/test-files/std/examples/rule-110/source.spice b/test/test-files/std/examples/rule-110/source.spice index bc8733cf7..c91ae99ab 100644 --- a/test/test-files/std/examples/rule-110/source.spice +++ b/test/test-files/std/examples/rule-110/source.spice @@ -1,8 +1,8 @@ // Can be adjusted, but the array size below needs to be the same number -const int CAP = 100; +const int CAP = 80; f main() { - int[100] board; + int[CAP] board; // Initialize board for int i = 0; i < CAP; i++ { diff --git a/test/test-files/std/examples/sudoku/cout.out b/test/test-files/std/examples/sudoku/cout.out new file mode 100644 index 000000000..6b2c14567 --- /dev/null +++ b/test/test-files/std/examples/sudoku/cout.out @@ -0,0 +1,9 @@ +3 1 6 5 7 8 4 9 2 +5 2 9 1 3 4 7 6 8 +4 8 7 6 2 9 5 3 1 +2 6 3 4 1 5 9 8 7 +9 7 4 8 6 3 1 2 5 +8 5 1 7 9 2 6 4 3 +1 3 8 9 4 7 2 5 6 +6 9 2 3 5 1 8 7 4 +7 4 5 2 8 6 3 1 9 diff --git a/test/test-files/std/examples/sudoku/source.spice b/test/test-files/std/examples/sudoku/source.spice new file mode 100644 index 000000000..ec2260123 --- /dev/null +++ b/test/test-files/std/examples/sudoku/source.spice @@ -0,0 +1,88 @@ +const int size = 9; + +p print(int[size][size] grid) { + for int i = 0; i < size; i++ { + for int j = 0; j < size; j++ { + printf("%d ", grid[i][j]); + } + printf("\n"); + } +} + +f isSafe(int[size][size] grid, int row, int col, int num) { + // Check if we find the same num in the similar row -> return false + for int x = 0; x <= size - 1; x++ { + if grid[row][x] == num { + return false; + } + } + + // Check if we find the same num in the similar column -> return false + for int x = 0; x <= size - 1; x++ { + if grid[x][col] == num { + return false; + } + } + + // Check if we find the same num in the particular 3*3 matrix -> return false + int startRow = row - row % 3; + int startCol = col - col % 3; + + for int i = 0; i < 3; i++ { + for int j = 0; j < 3; j++ { + if grid[i + startRow][j + startCol] == num { + return false; + } + } + } + + return true; +} + +f solveSudoku(int[size][size] grid, int row, int col) { + // Check if we have reached the second last row and the last column. + // We return true to avoid further backtracking + if row == size - 1 && col == size { return true; } + + if col == size { + row++; + col = 0; + } + + if grid[row][col] > 0 { + return solveSudoku(grid, row, col + 1); + } + + for int num = 1; num <= size; num++ { + if isSafe(grid, row, col, num) { + grid[row][col] = num; + + if solveSudoku(grid, row, col + 1) { + return true; + } + } + grid[row][col] = 0; + } + + return false; +} + +f main() { + int[size][size] grid = { + { 3, 0, 6, 5, 0, 8, 4, 0, 0 }, + { 5, 2, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 8, 7, 0, 0, 0, 0, 3, 1 }, + { 0, 0, 3, 0, 1, 0, 0, 8, 0 }, + { 9, 0, 0, 8, 6, 3, 0, 0, 5 }, + { 0, 5, 0, 0, 9, 0, 6, 0, 0 }, + { 1, 3, 0, 0, 0, 0, 2, 5, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 7, 4 }, + { 0, 0, 5, 2, 0, 6, 3, 0, 0 } + }; + + if solveSudoku(grid, 0, 0) { + print(grid); + } else { + printf("No solution was found."); + } +} \ No newline at end of file