From 9c7e1c19f194cf508caf824f3b8dbdde5fb99053 Mon Sep 17 00:00:00 2001 From: domenico Date: Mon, 2 Dec 2024 15:13:13 +0100 Subject: [PATCH] Add compile-time error case --- .../smeup/rpgparser/parsing/ast/statements.kt | 17 ++++++++++++----- .../rpgparser/interpreter/JarikoCallbackTest.kt | 12 ++++++++++++ .../src/test/resources/ERROR49.rpgle | 6 ++++++ 3 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 rpgJavaInterpreter-core/src/test/resources/ERROR49.rpgle diff --git a/rpgJavaInterpreter-core/src/main/kotlin/com/smeup/rpgparser/parsing/ast/statements.kt b/rpgJavaInterpreter-core/src/main/kotlin/com/smeup/rpgparser/parsing/ast/statements.kt index d1012c8f3..f778776cc 100644 --- a/rpgJavaInterpreter-core/src/main/kotlin/com/smeup/rpgparser/parsing/ast/statements.kt +++ b/rpgJavaInterpreter-core/src/main/kotlin/com/smeup/rpgparser/parsing/ast/statements.kt @@ -1302,17 +1302,24 @@ data class DefineStmt( get() = "DEFINE" override fun dataDefinition(): List { - // FIXME: If indicator was not priorly SET (SETON or SETOFF), program should error + val containingCU = this.ancestor(CompilationUnit::class.java) + ?: return emptyList() + val indicatorPattern = Regex("\\*IN\\d\\d") - val isIndicator = originalName.trim().uppercase().matches(indicatorPattern) + val normalizedOriginalName = originalName.trim().uppercase() + val isIndicator = normalizedOriginalName.matches(indicatorPattern) if (isIndicator) { + val indicatorKey = normalizedOriginalName.removePrefix("*IN").toIndicatorKey() + val setStatements = containingCU.main.stmts.explode(true).filterIsInstance() + val definedIndicators = setStatements.map { it.indicators }.flatten().filterIsInstance() + val isIndicatorDefined = definedIndicators.any { it.index == indicatorKey } + + if (!isIndicatorDefined) throw Error("Data reference $originalName not resolved") + val newDefinition = InStatementDataDefinition(newVarName, BooleanType, position) return listOf(newDefinition) } - val containingCU = this.ancestor(CompilationUnit::class.java) - ?: return emptyList() - // Search standalone 'D spec' or InStatement definition val originalDataDefinition = containingCU.dataDefinitions.find { it.name == originalName } ?: containingCU.getInStatementDataDefinitions().find { it.name == originalName } diff --git a/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/interpreter/JarikoCallbackTest.kt b/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/interpreter/JarikoCallbackTest.kt index c62ca3767..bcd8887ff 100644 --- a/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/interpreter/JarikoCallbackTest.kt +++ b/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/interpreter/JarikoCallbackTest.kt @@ -1009,6 +1009,18 @@ class JarikoCallbackTest : AbstractTest() { executeSourceLineTest("ERROR48") } + @Test + fun executeERROR49CallBackTest() { + executePgmCallBackTest("ERROR49", SourceReferenceType.Program, "ERROR49", mapOf( + 6 to "Data reference *IN10 not resolved" + )) + } + + @Test + fun executeERROR49SourceLineTest() { + executeSourceLineTest("ERROR49") + } + @Test fun bypassSyntaxErrorTest() { val configuration = Configuration().apply { diff --git a/rpgJavaInterpreter-core/src/test/resources/ERROR49.rpgle b/rpgJavaInterpreter-core/src/test/resources/ERROR49.rpgle new file mode 100644 index 000000000..dc7da975e --- /dev/null +++ b/rpgJavaInterpreter-core/src/test/resources/ERROR49.rpgle @@ -0,0 +1,6 @@ + V* ============================================================== + D* 02/12/24 + D* Purpose: Must fire the following errors during execution of + D* line 6 - Data reference *IN10 not resolved + V* ============================================================== + C *LIKE DEFINE *IN10 XIN10