diff --git a/rpgJavaInterpreter-core/src/main/kotlin/com/smeup/rpgparser/interpreter/data_definitions.kt b/rpgJavaInterpreter-core/src/main/kotlin/com/smeup/rpgparser/interpreter/data_definitions.kt index 0b4a65cc3..060a1ae5e 100644 --- a/rpgJavaInterpreter-core/src/main/kotlin/com/smeup/rpgparser/interpreter/data_definitions.kt +++ b/rpgJavaInterpreter-core/src/main/kotlin/com/smeup/rpgparser/interpreter/data_definitions.kt @@ -409,6 +409,8 @@ data class FieldDefinition( } } + fun isCompileTimeArray() = type is ArrayType && type.compileTimeArray() + fun toDataStructureValue(value: Value) = type.toDataStructureValue(value) /** diff --git a/rpgJavaInterpreter-core/src/main/kotlin/com/smeup/rpgparser/interpreter/internal_interpreter.kt b/rpgJavaInterpreter-core/src/main/kotlin/com/smeup/rpgparser/interpreter/internal_interpreter.kt index bb8504ad9..014fdf413 100644 --- a/rpgJavaInterpreter-core/src/main/kotlin/com/smeup/rpgparser/interpreter/internal_interpreter.kt +++ b/rpgJavaInterpreter-core/src/main/kotlin/com/smeup/rpgparser/interpreter/internal_interpreter.kt @@ -300,6 +300,14 @@ open class InternalInterpreter( } } } + is FieldDefinition -> { + if (it.isCompileTimeArray()) { + value = toArrayValue( + compilationUnit.compileTimeArray(index++), + (it.type as ArrayType) + ) + } + } is InStatementDataDefinition -> { value = if (it.parent is PlistParam) { when (it.name) { diff --git a/rpgJavaInterpreter-core/src/main/kotlin/com/smeup/rpgparser/parsing/parsetreetoast/data_definitions.kt b/rpgJavaInterpreter-core/src/main/kotlin/com/smeup/rpgparser/parsing/parsetreetoast/data_definitions.kt index f8e090a90..acc03bae0 100644 --- a/rpgJavaInterpreter-core/src/main/kotlin/com/smeup/rpgparser/parsing/parsetreetoast/data_definitions.kt +++ b/rpgJavaInterpreter-core/src/main/kotlin/com/smeup/rpgparser/parsing/parsetreetoast/data_definitions.kt @@ -639,7 +639,8 @@ data class FieldInfo( var explicitElementType: Type? = null, val initializationValue: Expression? = null, val descend: Boolean = false, - val position: Position? + val position: Position?, + val compileTimeRecordsPerLine: Int? = null ) { var startOffset: Int? = explicitStartOffset // these are mutable as they can be calculated using next @@ -672,7 +673,7 @@ data class FieldInfo( return if (arraySizeDeclared == null) { elementType } else { - ArrayType(elementType, arraySizeDeclared!!) + ArrayType(elementType, arraySizeDeclared!!, compileTimeRecordsPerLine) } } @@ -871,6 +872,23 @@ private fun RpgParser.Parm_fixedContext.toFieldInfo( // Set the SORTA order val descend = this.keyword().find { it.keyword_descend() != null } != null + // Set the CTDATA flag + val compileTimeArray = this.keyword().find { it.keyword_ctdata() != null } != null + + // Set the PERRCD flag + val elementsPerLineExpression = this.keyword().find { it.keyword_perrcd() != null }.let { it?.keyword_perrcd()?.simpleExpression()?.toAst(conf) } + + // Calculating compile time records per line + var compileTimeRecordsPerLine: Int? = null + if (compileTimeArray) { + if (elementsPerLineExpression != null) { + compileTimeRecordsPerLine = conf.compileTimeInterpreter.evaluate(this.rContext(), elementsPerLineExpression).asInt().value.toInt() + } else { + compileTimeRecordsPerLine = 1 + } + require(compileTimeRecordsPerLine > 0) + } + if (overlay != null) { this.name val pos = overlay.keyword_overlay().pos @@ -922,7 +940,9 @@ private fun RpgParser.Parm_fixedContext.toFieldInfo( arraySizeDeclaredOnThisField = this.arraySizeDeclared(conf), initializationValue = initializationValue, descend = descend, - position = this.toPosition(conf.considerPosition)) + position = this.toPosition(conf.considerPosition), + compileTimeRecordsPerLine = compileTimeRecordsPerLine + ) } fun RpgParser.Dcl_dsContext.declaredSize(): Int? { diff --git a/rpgJavaInterpreter-core/src/main/kotlin/com/smeup/rpgparser/parsing/parsetreetoast/misc.kt b/rpgJavaInterpreter-core/src/main/kotlin/com/smeup/rpgparser/parsing/parsetreetoast/misc.kt index e85351147..32fd03eab 100644 --- a/rpgJavaInterpreter-core/src/main/kotlin/com/smeup/rpgparser/parsing/parsetreetoast/misc.kt +++ b/rpgJavaInterpreter-core/src/main/kotlin/com/smeup/rpgparser/parsing/parsetreetoast/misc.kt @@ -484,13 +484,12 @@ private fun Dcl_dsContext.useExtName(): Boolean { } internal fun EndSourceContext.toAst(conf: ToAstConfiguration = ToAstConfiguration()): CompileTimeArray { - - fun cName(s: String) = - if (s.contains("**CTDATA")) { - s.substringAfter("**CTDATA ").replace("\\s".toRegex(), "") - } else { - s.replace(s, "") - } + fun cName(s: String) = + if (s.trim().matches(Regex("^\\*\\*[\\s]*(CTDATA)*([\\s]+[\\S]+)\$"))) { + s.substringAfter("**").trim().substringAfter("CTDATA").trim() + } else { + s.replace(s, "") + } return CompileTimeArray( cName(this.endSourceHead().text), // TODO: change grammar to get **CTDATA name diff --git a/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/MULANGT02ConstAndDSpecTest.kt b/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/MULANGT02ConstAndDSpecTest.kt index 46b2fc38e..adf3aecd4 100644 --- a/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/MULANGT02ConstAndDSpecTest.kt +++ b/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/MULANGT02ConstAndDSpecTest.kt @@ -693,4 +693,54 @@ open class MULANGT02ConstAndDSpecTest : MULANGTTest() { val expected = listOf("10.000000") assertEquals(expected, "smeup/MUDRNRAPU00132".outputOf(configuration = smeupConfig)) } + + /** + * DS field declared as Array and CTDATA. In this case between CTDATA and its name there is more space. + * @see #LS24004654 + */ + @Test + fun executeMUDRNRAPU00150() { + val expected = listOf("*SCPAccesso da script 00S") + assertEquals(expected, "smeup/MUDRNRAPU00150".outputOf(configuration = smeupConfig)) + } + + /** + * DS field declared as Array and CTDATA. In this case there isn't CTDATA but more space between name and stars. + * @see #LS24004654 + */ + @Test + fun executeMUDRNRAPU00151() { + val expected = listOf("*SCPAccesso da script 00S") + assertEquals(expected, "smeup/MUDRNRAPU00151".outputOf(configuration = smeupConfig)) + } + + /** + * DS field declared as Array and CTDATA. In this case there is only CTDATA. + * @see #LS24004654 + */ + @Test + fun executeMUDRNRAPU00152() { + val expected = listOf("*SCPAccesso da script 00S") + assertEquals(expected, "smeup/MUDRNRAPU00152".outputOf(configuration = smeupConfig)) + } + + /** + * DS field declared as Array and CTDATA. In this case there is only the name. + * @see #LS24004654 + */ + @Test + fun executeMUDRNRAPU00153() { + val expected = listOf("*SCPAccesso da script 00S") + assertEquals(expected, "smeup/MUDRNRAPU00153".outputOf(configuration = smeupConfig)) + } + + /** + * DS field declared as Array and CTDATA. In this case there are only the stars. + * @see #LS24004654 + */ + @Test + fun executeMUDRNRAPU00154() { + val expected = listOf("*SCPAccesso da script 00S") + assertEquals(expected, "smeup/MUDRNRAPU00154".outputOf(configuration = smeupConfig)) + } } diff --git a/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/MULANGT15BaseBif1Test.kt b/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/MULANGT15BaseBif1Test.kt index d5ba8552f..d03dd2bc5 100644 --- a/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/MULANGT15BaseBif1Test.kt +++ b/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/MULANGT15BaseBif1Test.kt @@ -124,4 +124,14 @@ open class MULANGT15BaseBif1Test : MULANGTTest() { val expected = listOf("10000", "10000", "10000", "10000") assertEquals(expected, "smeup/MUDRNRAPU00253".outputOf(configuration = smeupConfig)) } + + /** + * DS field declared as Array and CTDATA. In this case the error is manifested as side effect of `%LOOKUP`. + * @see #LS24004654 + */ + @Test + fun executeMUDRNRAPU00149() { + val expected = listOf("1", "*SCP") + assertEquals(expected, "smeup/MUDRNRAPU00149".outputOf(configuration = smeupConfig)) + } } diff --git a/rpgJavaInterpreter-core/src/test/resources/smeup/MUDRNRAPU00149.rpgle b/rpgJavaInterpreter-core/src/test/resources/smeup/MUDRNRAPU00149.rpgle new file mode 100644 index 000000000..a4209395a --- /dev/null +++ b/rpgJavaInterpreter-core/src/test/resources/smeup/MUDRNRAPU00149.rpgle @@ -0,0 +1,38 @@ + V* ============================================================== + V* 30/10/2024 APU001 Creation + V* 31/10/2024 APU001 Edited PROGRAM GOAL + V* 06/11/2024 APU001 Edited PROGRAM GOAL + V* ============================================================== + O * PROGRAM GOAL + O * DS field declared as Array and CTDATA. In this case the error + O * is manifested as side effect of `%LOOKUP`. + V* ============================================================== + O * JARIKO ANOMALY + O * Before the fix, the error occurred was + O * `Failed requirement' + V* ============================================================== + D £IQ5D DS 5000 + D £IQ5DCD 15 + + D DS + DIQ5 42 DIM(3) CTDATA PERRCD(1) + D IQ5CD 4 OVERLAY(IQ5:1) + D IQ5DE 30 OVERLAY(IQ5:*NEXT) + D IQ5PG 2 OVERLAY(IQ5:*NEXT) + + D$X S 5 0 + DNQ5 S 5 0 INZ(3) + DA4 S 4 + + C EVAL A4='*SCP' + C EVAL $X=%LOOKUP(A4:IQ5CD:1:NQ5) + C $X DSPLY + C EVAL £IQ5DCD=IQ5CD($X) #Failed requirement. Depends from %LOOKUP result + C £IQ5DCD DSPLY + + C SETON LR + +** Descrizione PgPref.D +*SCPAccesso da script 00S +*IQ2Accesso da Pgm £IQ2 18Q +*SETAccesso da SCP_NAV 17T \ No newline at end of file diff --git a/rpgJavaInterpreter-core/src/test/resources/smeup/MUDRNRAPU00150.rpgle b/rpgJavaInterpreter-core/src/test/resources/smeup/MUDRNRAPU00150.rpgle new file mode 100644 index 000000000..673739723 --- /dev/null +++ b/rpgJavaInterpreter-core/src/test/resources/smeup/MUDRNRAPU00150.rpgle @@ -0,0 +1,18 @@ + V* ============================================================== + V* 31/10/2024 APU001 Creation + V* 06/11/2024 APU001 Simplification + V* ============================================================== + O * PROGRAM GOAL + O * DS field declared as Array and CTDATA. In this case between + O * CTDATA and its name there is more space. + V* ============================================================== + D DS + DIQ5 37 DIM(3) CTDATA PERRCD(1) + + C IQ5(1) DSPLY + C SETON LR + +** CTDATA IQ5 +*SCPAccesso da script 00S +*IQ2Accesso da Pgm £IQ2 18Q +*SETAccesso da SCP_NAV 17T \ No newline at end of file diff --git a/rpgJavaInterpreter-core/src/test/resources/smeup/MUDRNRAPU00151.rpgle b/rpgJavaInterpreter-core/src/test/resources/smeup/MUDRNRAPU00151.rpgle new file mode 100644 index 000000000..20795b293 --- /dev/null +++ b/rpgJavaInterpreter-core/src/test/resources/smeup/MUDRNRAPU00151.rpgle @@ -0,0 +1,18 @@ + V* ============================================================== + V* 31/10/2024 APU001 Creation + V* 06/11/2024 APU001 Simplification + V* ============================================================== + O * PROGRAM GOAL + O * DS field declared as Array and CTDATA. In this case there + O * isn't CTDATA but more space between name and stars. + V* ============================================================== + D DS + DIQ5 37 DIM(3) CTDATA PERRCD(1) + + C IQ5(1) DSPLY + C SETON LR + +** IQ5 +*SCPAccesso da script 00S +*IQ2Accesso da Pgm £IQ2 18Q +*SETAccesso da SCP_NAV 17T \ No newline at end of file diff --git a/rpgJavaInterpreter-core/src/test/resources/smeup/MUDRNRAPU00152.rpgle b/rpgJavaInterpreter-core/src/test/resources/smeup/MUDRNRAPU00152.rpgle new file mode 100644 index 000000000..6e7b258c3 --- /dev/null +++ b/rpgJavaInterpreter-core/src/test/resources/smeup/MUDRNRAPU00152.rpgle @@ -0,0 +1,18 @@ + V* ============================================================== + V* 31/10/2024 APU001 Creation + V* 06/11/2024 APU001 Simplification + V* ============================================================== + O * PROGRAM GOAL + O * DS field declared as Array and CTDATA. In this case there + O * is only CTDATA. + V* ============================================================== + D DS + DIQ5 37 DIM(3) CTDATA PERRCD(1) + + C IQ5(1) DSPLY + C SETON LR + +** CTDATA +*SCPAccesso da script 00S +*IQ2Accesso da Pgm £IQ2 18Q +*SETAccesso da SCP_NAV 17T \ No newline at end of file diff --git a/rpgJavaInterpreter-core/src/test/resources/smeup/MUDRNRAPU00153.rpgle b/rpgJavaInterpreter-core/src/test/resources/smeup/MUDRNRAPU00153.rpgle new file mode 100644 index 000000000..757b711e6 --- /dev/null +++ b/rpgJavaInterpreter-core/src/test/resources/smeup/MUDRNRAPU00153.rpgle @@ -0,0 +1,18 @@ + V* ============================================================== + V* 31/10/2024 APU001 Creation + V* 06/11/2024 APU001 Simplification + V* ============================================================== + O * PROGRAM GOAL + O * DS field declared as Array and CTDATA. In this case there is + O * only the name. + V* ============================================================== + D DS + DIQ5 37 DIM(3) CTDATA PERRCD(1) + + C IQ5(1) DSPLY + C SETON LR + +** IQ5 +*SCPAccesso da script 00S +*IQ2Accesso da Pgm £IQ2 18Q +*SETAccesso da SCP_NAV 17T \ No newline at end of file diff --git a/rpgJavaInterpreter-core/src/test/resources/smeup/MUDRNRAPU00154.rpgle b/rpgJavaInterpreter-core/src/test/resources/smeup/MUDRNRAPU00154.rpgle new file mode 100644 index 000000000..65bfe0977 --- /dev/null +++ b/rpgJavaInterpreter-core/src/test/resources/smeup/MUDRNRAPU00154.rpgle @@ -0,0 +1,18 @@ + V* ============================================================== + V* 31/10/2024 APU001 Creation + V* 06/11/2024 APU001 Simplification + V* ============================================================== + O * PROGRAM GOAL + O * DS field declared as Array and CTDATA. In this case there are + O * only the stars + V* ============================================================== + D DS + DIQ5 37 DIM(3) CTDATA PERRCD(1) + + C IQ5(1) DSPLY + C SETON LR + +** +*SCPAccesso da script 00S +*IQ2Accesso da Pgm £IQ2 18Q +*SETAccesso da SCP_NAV 17T \ No newline at end of file