From 2e576e69e07627a516b568079e047965a9bd8d24 Mon Sep 17 00:00:00 2001 From: Kris Rowe Date: Tue, 16 Aug 2022 15:07:22 -0500 Subject: [PATCH] [bugfix] OKL for loop init statement (#618) --- .../internal/lang/modes/oklForStatement.cpp | 41 +++++++++++++++---- src/occa/internal/lang/variable.cpp | 2 +- tests/src/internal/lang/modes/okl.cpp | 6 +++ 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/src/occa/internal/lang/modes/oklForStatement.cpp b/src/occa/internal/lang/modes/oklForStatement.cpp index d2076a670..578837b59 100644 --- a/src/occa/internal/lang/modes/oklForStatement.cpp +++ b/src/occa/internal/lang/modes/oklForStatement.cpp @@ -52,7 +52,7 @@ namespace occa { if (!(0 < loop_range)) { valid = false; if(printErrors_) - forSmnt_.printError("OKL for loop is empty or infinite!"); + forSmnt_.printError("OKL for loop range is empty or infinite!"); } } delete loop_range_node; @@ -75,27 +75,52 @@ namespace occa { bool oklForStatement::hasValidInit() { statement_t &initSmnt = *(forSmnt.init); - // Check for declaration - if (initSmnt.type() != statementType::declaration) { - if (printErrors) { - initSmnt.printError(sourceStr() + "Expected a declaration statement"); - } + const auto init_statement_type = initSmnt.type(); + + if(statementType::empty == init_statement_type) { + if(printErrors) + initSmnt.printError(sourceStr() + + "OKL for loop init-statement cannot be be a null statement"); + return false; + } + + if(statementType::declaration != init_statement_type) { + if(printErrors) + initSmnt.printError(sourceStr() + + "OKL for loop init-statement must be a simple declaration with initializer"); return false; } + // Can only have one declaration declarationStatement &declSmnt = (declarationStatement&) initSmnt; + if (declSmnt.declarations.size() > 1) { if (printErrors) { declSmnt.declarations[1].printError( - sourceStr() + "Can only have 1 iterator variable" + sourceStr() + "OKL for loops can only have 1 iterator variable" ); } return false; } + // Get iterator and value variableDeclaration &decl = declSmnt.declarations[0]; iterator = &decl.variable(); + if(!(iterator->isNamed())) { + if(printErrors) + declSmnt.printError(sourceStr() + + "OKL for loop variable does not have a name."); + return false; + } + + if(!decl.hasValue()) { + if(printErrors) + decl.printError(sourceStr() + + "OKL for loop variable is not initialized."); + return false; + } initValue = decl.value; + // Valid types: {char, short, int, long} const type_t *type = iterator->vartype.flatten().type; if (!type || @@ -103,7 +128,7 @@ namespace occa { (*type != short_) && (*type != int_))) { if (printErrors) { - iterator->printError(sourceStr() + "Iterator variable needs to be of type" + iterator->printError(sourceStr() + "OKL for loop iterator variable needs to be of type" " [char, short, int, long]"); } return false; diff --git a/src/occa/internal/lang/variable.cpp b/src/occa/internal/lang/variable.cpp index 02604bc32..7dcbaaedf 100644 --- a/src/occa/internal/lang/variable.cpp +++ b/src/occa/internal/lang/variable.cpp @@ -49,7 +49,7 @@ namespace occa { } bool variable_t::isNamed() const { - return source->value.size(); + return !(this->name().empty()); } std::string& variable_t::name() { diff --git a/tests/src/internal/lang/modes/okl.cpp b/tests/src/internal/lang/modes/okl.cpp index 005e8b035..09acc4f65 100644 --- a/tests/src/internal/lang/modes/okl.cpp +++ b/tests/src/internal/lang/modes/okl.cpp @@ -97,6 +97,9 @@ void testProperOKLLoops() { parseBadOKLSource(oStart + "for (int o = 0; o < 2;; @outer) {" + oMid + "}" + oEnd); parseBadOKLSource(oStart + "for (int o = 0; o < 2; o *= 2; @outer) {" + oMid + "}" + oEnd); parseBadOKLSource(oStart + "for (int o = 0; o < 2; ++j; @outer) {" + oMid + "}" + oEnd); + parseBadOKLSource(oStart + "for (int o; o < 2; ++o; @outer) {" + oMid + "}" + oEnd); + parseBadOKLSource(oStart + "for (int; o < 2; ++o; @outer) {" + oMid + "}" + oEnd); + parseBadOKLSource(oStart + "for ( ; o < 2; ++o; @outer) {" + oMid + "}" + oEnd); parseBadOKLSource(iStart + "for (i = 0;;; @inner) {}" + iEnd); parseBadOKLSource(iStart + "for (float i = 0;;; @inner) {}" + iEnd); @@ -107,6 +110,9 @@ void testProperOKLLoops() { parseBadOKLSource(iStart + "for (int i = 0; i < 2;; @inner) {}" + iEnd); parseBadOKLSource(iStart + "for (int i = 0; i < 2; i *= 2; @inner) {}" + iEnd); parseBadOKLSource(iStart + "for (int i = 0; i < 2; ++j; @inner) {}" + iEnd); + parseBadOKLSource(iStart + "for (int i; i < 2; ++i; @inner) {}" + iEnd); + parseBadOKLSource(iStart + "for (int; i < 2; ++i; @inner) {}" + iEnd); + parseBadOKLSource(iStart + "for ( ; i < 2; ++i; @inner) {}" + iEnd); // No double @outer + @inner parseBadOKLSource(