diff --git a/rpgJavaInterpreter-core/src/main/kotlin/com/smeup/rpgparser/interpreter/SymbolTable.kt b/rpgJavaInterpreter-core/src/main/kotlin/com/smeup/rpgparser/interpreter/SymbolTable.kt index afbafda3b..6773f53c6 100644 --- a/rpgJavaInterpreter-core/src/main/kotlin/com/smeup/rpgparser/interpreter/SymbolTable.kt +++ b/rpgJavaInterpreter-core/src/main/kotlin/com/smeup/rpgparser/interpreter/SymbolTable.kt @@ -36,7 +36,25 @@ class SymbolTable : ISymbolTable { if (MainExecutionContext.isLoggingEnabled) getWithLogging(dataName) else getInternal(dataName) override fun dataDefinitionByName(dataName: String): AbstractDataDefinition? { - return names[dataName.uppercase()] ?: parentSymbolTable?.let { (parentSymbolTable as SymbolTable).names[dataName.uppercase()] } + /* + * In order, try to resolve a Data Definition, by its name and by finding it: + * 1. in root because might be a Data Definition; + * 2. in DS declared as not `QUALIFIED` because might be a Field Definition with access without dot notation. In this + * case will be added in `names` if found. + * 3. in parent Symbol Table. + */ + return names.compute(dataName.uppercase()) { key, value -> + value ?: names + .asSequence() + .filter { name -> + name.value.type is DataStructureType && + !(name.value.type as AbstractDataStructureType).isQualified && + name.value is DataDefinition + } + .map { it.value } + .flatMap { dataStructure -> (dataStructure as DataDefinition).fields } + .firstOrNull { field -> field.name.equals(key, ignoreCase = true) } as AbstractDataDefinition? + } ?: parentSymbolTable?.let { (parentSymbolTable as SymbolTable).names[dataName.uppercase()] } } override operator fun set(data: AbstractDataDefinition, value: Value): Value? { 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 cc544d4c0..fc0eae208 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 @@ -141,7 +141,9 @@ private fun List.getDataDefinition( fileDefinitions = fileDefinitions ) } - dataDefinitionProviders.addAll(firstPassProviders) + dataDefinitionProviders + .removeFileFieldsDefinedInDs(firstPassProviders) + .addAll(firstPassProviders) // Second pass, everything, I mean everything val secondPassProviders = sortedStatements.getValidDataDefinitionHolders( @@ -156,6 +158,27 @@ private fun List.getDataDefinition( return Pair(dataDefinitionProviders, knownDataDefinitions) } +/** + * Removes file fields from the root of the `dataDefinitionProviders` when they are also defined in a data structure (DS) + * that uses `EXTNAME` in RPG, ensuring that field manipulations apply to both the file and the DS. + * + * The function scans through `firstPassProviders`, extracts the fields, filters out those not of `RecordFormatType`, + * and removes corresponding file fields from the mutable list to avoid redundancy and potential conflicts. + * + * @param firstPassProviders a list of `DataDefinitionProvider` objects from the first pass to extract fields from + * @return the updated mutable list with the file fields removed, ensuring only the DS manages those fields + */ +private fun MutableList.removeFileFieldsDefinedInDs(firstPassProviders: List): MutableList { + firstPassProviders + .flatMap { provider -> provider.toDataDefinition().fields } + .filter { field -> field.type !is RecordFormatType } + .forEach { field -> + this.removeIf { provider -> provider.toDataDefinition().name.equals(field.name, ignoreCase = true) } + } + + return this +} + private fun List.getValidDataDefinitionHolders( conf: ToAstConfiguration = ToAstConfiguration(), knownDataDefinitions: KnownDataDefinitionInstance, diff --git a/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/evaluation/MuteExecutionTest.kt b/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/evaluation/MuteExecutionTest.kt index e65e3abda..3ba8f0ab0 100644 --- a/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/evaluation/MuteExecutionTest.kt +++ b/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/evaluation/MuteExecutionTest.kt @@ -466,6 +466,7 @@ open class MuteExecutionTest : AbstractTest() { } @Test + @Ignore("Until is improved Encode/Decode to/from Packed") fun executeMUTE13_41() { executePgm("mute/MUTE13_41", configuration = smeupConfig) } 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 d1f987938..45c5d74a7 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 @@ -672,7 +672,7 @@ class JarikoCallbackTest : AbstractTest() { */ @Test fun executeERROR36CallBackTest() { - TABDS01LDbMock().usePopulated { + TABDS01LDbMock().usePopulated({ executePgmCallBackTest( pgm = "ERROR36", sourceReferenceType = SourceReferenceType.Program, @@ -680,7 +680,7 @@ class JarikoCallbackTest : AbstractTest() { lines = listOf(6), reloadConfig = it.createReloadConfig() ) - } + }) } @Test diff --git a/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/interpreter/SymbolTableTest.kt b/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/interpreter/SymbolTableTest.kt new file mode 100644 index 000000000..120327730 --- /dev/null +++ b/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/interpreter/SymbolTableTest.kt @@ -0,0 +1,152 @@ +package com.smeup.rpgparser.interpreter + +import com.smeup.rpgparser.AbstractTest +import com.smeup.rpgparser.PerformanceTest +import com.smeup.rpgparser.parsing.ast.CompilationUnit +import org.junit.experimental.categories.Category +import kotlin.test.* +import kotlin.time.DurationUnit +import kotlin.time.measureTime + +/** + * The purpose of this test suite is to validate the behaviour around Symbol Table. + * The resources about this suite starts with `ST` (Symbol Table), followed by any string which describes the purpose. + */ +class SymbolTableTest : AbstractTest() { + /** + * Performance test for accessing standalone fields and data structure fields in a symbol table. + * + * This test measures the execution time required to perform repeated lookups of standalone fields and + * data structure fields in a symbol table created from an Abstract Syntax Tree (AST). It verifies that + * the AST can be produced successfully and evaluates the performance of symbol table lookups for + * specific fields. + * + * Steps: + * 1. Produce an AST from the specified example program (`symboltable/ST_PERFORMANCE_ACCESS01`). + * 2. Create a symbol table (`ISymbolTable`) from the AST. + * 3. Perform 1,000,000 lookups for the standalone field `VAR1`. + * 4. Perform 1,000,000 lookups for the last field of the data structure `DS10_FLD50`. + * 5. Measure and log the total execution time for these operations. + * + * The goal is to evaluate the efficiency of symbol table lookups and ensure performance is within an acceptable range. + * + * @throws TimeoutException if the test does not complete within 6 seconds + * @see ISymbolTable + */ + @Test + @Category(PerformanceTest::class) + fun executeST_F_WITH_DS_UNQUALIFIED1_PERFORMANCE() { + assertASTCanBeProduced( + exampleName = "symboltable/ST_PERFORMANCE_ACCESS01", + afterAstCreation = { ast -> + val symbolTable: ISymbolTable = ast.createSymbolTable() + + val timeVAR1 = measureTime { + for (i in 1..1_000_000) { + symbolTable.dataDefinitionByName("VAR1") + } + }.also { time -> + println("Time execution during the resolution of VAR1: $time") + } + + val timeDS10_FLD50 = measureTime { + for (i in 1..1_000_000) { + symbolTable.dataDefinitionByName("DS10_FLD50") + } + }.also { time -> + println("Time execution during the resolution of DS10_FLD50: $time") + } + + println("Ratio execution during the resolution of Standalone and DS field: ${timeVAR1 / timeDS10_FLD50}") + + assertTrue((timeVAR1 + timeDS10_FLD50).toLong(DurationUnit.MILLISECONDS) < 3000) + } + ) + } + + /** + * Test for validating symbol table lookups of standalone fields and data structure fields. + * + * This test verifies the correctness of symbol table entries for: + * 1. A standalone field (`VAR1`). + * 2. Fields within a data structure (`DS10_FLD50` and `DS10_FLD51`). + * + * Steps: + * 1. Produce an Abstract Syntax Tree (AST) from the example program `symboltable/ST_PERFORMANCE_ACCESS01`. + * 2. Create a symbol table (`ISymbolTable`) from the AST. + * 3. Perform lookups for: + * - `VAR1`: A standalone field expected to be found as a `DataDefinition`. + * - `DS10_FLD50`: A field in the data structure `DS1`, expected to be found as a `FieldDefinition`. + * - `DS10_FLD51`: Another field, expected not to exist in the symbol table (returns `null`). + * 4. Assert the types and properties of the retrieved definitions: + * - Verify `VAR1` is a `DataDefinition`. + * - Verify `DS10_FLD50` is a `FieldDefinition` and belongs to the parent data structure `DS1`. + * - Verify `DS10_FLD51` is not found in the symbol table (`null`). + * + * Assertions: + * - The type and parent relationships of the retrieved definitions are validated. + * - The name of the parent data structure for `DS10_FLD50` is confirmed as `DS1`. + * - It is asserted that `DS10_FLD51` does not exist in the symbol table. + * + * @see ISymbolTable + * @see DataDefinition + * @see FieldDefinition + */ + @Test + fun executeST_F_WITH_DS_UNQUALIFIED1() { + assertASTCanBeProduced( + exampleName = "symboltable/ST_PERFORMANCE_ACCESS01", + afterAstCreation = { ast -> + val symbolTable: ISymbolTable = ast.createSymbolTable() + + val dataDefinition = symbolTable.dataDefinitionByName("VAR1") + val fieldDefinition1 = symbolTable.dataDefinitionByName("DS10_FLD50") + val fieldDefinition2 = symbolTable.dataDefinitionByName("DS10_FLD51") + + assertIs(dataDefinition) + assertIs(fieldDefinition1) + assertIs(fieldDefinition1.parent) + assertEquals("DS10", (fieldDefinition1.parent as DataDefinition).name, "DS10_FLD50 is field DS1.") + assertNull(fieldDefinition2, "DS10_FLD51 field not found.") + } + ) + } + + /** + * Creates a symbol table for the current `CompilationUnit`, mapping each `DataDefinition` to its corresponding `Value`. + * + * The symbol table (`ISymbolTable`) acts as a container for `DataDefinition`-to-`Value` mappings. + * For each `DataDefinition` in the `CompilationUnit`, this function generates a pair consisting of: + * - The `DataDefinition` as the key. + * - The associated `Value`, which is either the default value of the `DataDefinition` or a blank value based on its type. + * + * @return an `ISymbolTable` containing mappings of all `DataDefinition` objects in the `CompilationUnit` + */ + private fun CompilationUnit.createSymbolTable(): ISymbolTable { + val symbolTable: ISymbolTable = SymbolTable() + for (pair in this.dataDefinitions.map { dataDefinition -> makePairDataDefinitionValue(dataDefinition) }) { + symbolTable[pair.first] = pair.second + } + + return symbolTable + } + + /** + * Creates a key-value pair for a `DataDefinition` and its associated `Value`. + * + * This function takes a `DataDefinition` and generates a pair consisting of: + * - The `DataDefinition` itself as the key. + * - The associated `Value`, which is determined as follows: + * - If the `DataDefinition` has a `defaultValue`, that is used. + * - Otherwise, a blank value is generated based on the `DataDefinition`'s type. + * + * @param dataDefinition the `DataDefinition` for which the key-value pair is created + * @return a `Pair` where the key is the `DataDefinition` and the value is the associated `Value` + */ + private fun makePairDataDefinitionValue(dataDefinition: DataDefinition): Pair { + return Pair( + dataDefinition, + dataDefinition.defaultValue ?: dataDefinition.type.blank() + ) + } +} \ No newline at end of file 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 e6cb28a7a..1e4f4b200 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 @@ -201,13 +201,13 @@ open class MULANGT02ConstAndDSpecTest : MULANGTTest() { */ @Test fun executeMUDRNRAPU00101() { - MULANGTLDbMock().usePopulated { + MULANGTLDbMock().usePopulated({ val expected = listOf("HELLO THERE") assertEquals( expected = expected, "smeup/MUDRNRAPU00101".outputOf(configuration = smeupConfig) ) - } + }) } /** @@ -269,10 +269,10 @@ open class MULANGT02ConstAndDSpecTest : MULANGTTest() { @Test fun executeMUDRNRAPU00202() { - MULANGTLDbMock().usePopulated { + MULANGTLDbMock().usePopulated({ val expected = listOf("ok") assertEquals(expected, "smeup/MUDRNRAPU00202".outputOf(configuration = smeupConfig)) - } + }) } /** @@ -861,6 +861,20 @@ open class MULANGT02ConstAndDSpecTest : MULANGTTest() { assertEquals(expected, "smeup/MUDRNRAPU00171".outputOf(configuration = turnOnZAddLegacyFlagConfig)) } + /** + * Writing on a field of DS which use `EXTNAME` of a file. + * @see #LS25000142 + */ + @Test + fun executeMUDRNRAPU00189() { + MULANGTLDbMock().usePopulated({ + val expected = listOf("IBMI", "", "IBMI", "MULANGT00", "", "", "IBMI", "MULANGT00") + assertEquals(expected, "smeup/MUDRNRAPU00189".outputOf(configuration = smeupConfig)) + }, + listOf(mapOf("MLSYST" to "IBMI", "MLPROG" to "MULANGT00")) + ) + } + /** * Reading from a field of DS with dot notation. This DS have the same fields of another. * @see #LS25000142 diff --git a/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/MULANGT10BaseCodopTest.kt b/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/MULANGT10BaseCodopTest.kt index ecd6aae67..966557903 100644 --- a/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/MULANGT10BaseCodopTest.kt +++ b/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/MULANGT10BaseCodopTest.kt @@ -421,9 +421,9 @@ open class MULANGT10BaseCodopTest : MULANGTTest() { @Test fun executeMUDRNRAPU00272() { val expected = listOf("ok", "ok", "ok", "ok") - C5ADFF9LDbMock().usePopulated { + C5ADFF9LDbMock().usePopulated({ assertEquals(expected, "smeup/MUDRNRAPU00272".outputOf(configuration = smeupConfig)) - } + }) } /** diff --git a/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/MULANGT50FileAccess1Test.kt b/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/MULANGT50FileAccess1Test.kt index 53ac9dd73..98382a033 100644 --- a/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/MULANGT50FileAccess1Test.kt +++ b/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/MULANGT50FileAccess1Test.kt @@ -71,9 +71,9 @@ open class MULANGT50FileAccess1Test : MULANGTTest() { @Test fun executeMUDRNRAPU00254() { - MULANGTLDbMock().usePopulated { + MULANGTLDbMock().usePopulated({ val expected = listOf("1.000000000") assertEquals(expected, "smeup/MUDRNRAPU00254".outputOf(configuration = smeupConfig)) - } + }) } } diff --git a/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/dbmock/C5ADFF9LDbMock.kt b/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/dbmock/C5ADFF9LDbMock.kt index c9296e329..f1d45681d 100644 --- a/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/dbmock/C5ADFF9LDbMock.kt +++ b/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/dbmock/C5ADFF9LDbMock.kt @@ -17,6 +17,7 @@ package com.smeup.rpgparser.smeup.dbmock import com.smeup.rpgparser.interpreter.FileMetadata +import com.smeup.rpgparser.utils.DbMock import java.io.File class C5ADFF9LDbMock : DbMock { diff --git a/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/dbmock/MULANGTLDbMock.kt b/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/dbmock/MULANGTLDbMock.kt index c3250742d..3146f21aa 100644 --- a/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/dbmock/MULANGTLDbMock.kt +++ b/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/dbmock/MULANGTLDbMock.kt @@ -1,6 +1,7 @@ package com.smeup.rpgparser.smeup.dbmock import com.smeup.rpgparser.interpreter.FileMetadata +import com.smeup.rpgparser.utils.DbMock import java.io.File class MULANGTLDbMock : DbMock { diff --git a/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/dbmock/TABDS01LDbMock.kt b/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/dbmock/TABDS01LDbMock.kt index e3198b56d..87e863657 100644 --- a/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/dbmock/TABDS01LDbMock.kt +++ b/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/dbmock/TABDS01LDbMock.kt @@ -1,6 +1,7 @@ package com.smeup.rpgparser.smeup.dbmock import com.smeup.rpgparser.interpreter.FileMetadata +import com.smeup.rpgparser.utils.DbMock import java.io.File class TABDS01LDbMock : DbMock { diff --git a/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/dbmock/DbMock.kt b/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/utils/DbMock.kt similarity index 57% rename from rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/dbmock/DbMock.kt rename to rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/utils/DbMock.kt index f0b8dfece..055efed8d 100644 --- a/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/smeup/dbmock/DbMock.kt +++ b/rpgJavaInterpreter-core/src/test/kotlin/com/smeup/rpgparser/utils/DbMock.kt @@ -1,4 +1,4 @@ -package com.smeup.rpgparser.smeup.dbmock +package com.smeup.rpgparser.utils import com.smeup.dbnative.ConnectionConfig import com.smeup.dbnative.DBNativeAccessConfig @@ -16,7 +16,8 @@ interface DbMock : AutoCloseable { """.trimIndent() fun dropTable(): String = "DROP TABLE IF EXISTS ${metadata.tableName}" - fun populateTable(): String = buildDefaultPopulationQuery() + + fun populateTable(values: List>): String = if (values.isEmpty()) buildDefaultPopulationQuery() else buildPopulationQuery(values) fun createConnectionConfig(): ConnectionConfig = ConnectionConfig( fileName = "*", @@ -44,10 +45,13 @@ interface DbMock : AutoCloseable { ) } - fun usePopulated(predicate: (DbMock) -> R) = this.use { - val queries = listOf(it.createTable(), it.populateTable()) + fun usePopulated( + testExecution: (DbMock) -> R, + values: List> = emptyList() + ) = this.use { + val queries = listOf(it.createTable(), it.populateTable(values)) execute(queries) - predicate(it) + testExecution(it) } override fun close() { @@ -81,6 +85,17 @@ interface DbMock : AutoCloseable { val names = metadata.fields.joinToString { "\"${it.fieldName}\"" } val values = metadata.fields.joinToString { it.type.getDefault() } + return madeInsertStatement(names, values) + } + + private fun buildPopulationQuery(mockedValues: List>): String { + val names = metadata.fields.joinToString { "\"${it.fieldName}\"" } + val values = mockedValues.getFromValues(metadata.fields) + + return madeInsertStatement(names, values) + } + + private fun madeInsertStatement(names: String, values: String): String { return """ INSERT INTO ${metadata.tableName}($names) VALUES ($values) @@ -92,4 +107,41 @@ interface DbMock : AutoCloseable { is NumberType -> if (this.integer) "1" else "1.0" else -> TODO("Implement default value for type ${this.javaClass.simpleName}") // Add more defaults } + + /** + * Constructs a string representation of values from a list of maps, formatted as tuples of database fields. + * + * This function iterates over a list of maps, where each map represents a row of data with field names as keys. + * For each map, it constructs a tuple string by matching the fields from the provided list of `DbField` objects. + * If the value for a field is non-null and the field type is `StringType`, the value is wrapped in single quotes. + * Otherwise, the field's default value is used. + * + * The resulting string is a comma-separated list of tuples, suitable for use in SQL insert statements. + * + * @param values a list of `DbField` objects representing the database fields to extract values for + * @return a string representing the formatted values, each row enclosed in parentheses and separated by commas + */ + private fun List>.getFromValues(values: List): String { + var result = "" + this.forEachIndexed { index, value -> + result += "(" + result += values + .map { field -> + var valueSearched = value.get(field.fieldName) + if (valueSearched != null && field.type is StringType) { + valueSearched = "'$valueSearched'" + valueSearched + } else { + field.type.getDefault() + } + } + .joinToString(", ") + result += ")" + + if (index < this.size - 1) { + result += ", " + } + } + return result + } } \ No newline at end of file diff --git a/rpgJavaInterpreter-core/src/test/resources/smeup/MUDRNRAPU00189.rpgle b/rpgJavaInterpreter-core/src/test/resources/smeup/MUDRNRAPU00189.rpgle new file mode 100644 index 000000000..0ee3d5773 --- /dev/null +++ b/rpgJavaInterpreter-core/src/test/resources/smeup/MUDRNRAPU00189.rpgle @@ -0,0 +1,18 @@ + V* ============================================================== + V* 13/01/2025 APU001 Creation + V* 13/01/2025 BENMAR Improvements + V* ============================================================== + O * PROGRAM GOAL + O * Writing on a field of DS which use `EXTNAME` of a file. + V* ============================================================== + O * JARIKO ANOMALY + O * Program called doesn't have new value. + V* ============================================================== + D PGM_NAME S 17 INZ('MUDRNRAPU00189_P1') + D MULANGDS E DS EXTNAME(MULANGTL) INZ + + C EVAL MLSYST='IBMI' + C CALL PGM_NAME + C PARM MULANGDS + + C SETON LR \ No newline at end of file diff --git a/rpgJavaInterpreter-core/src/test/resources/smeup/MUDRNRAPU00189_P1.rpgle b/rpgJavaInterpreter-core/src/test/resources/smeup/MUDRNRAPU00189_P1.rpgle new file mode 100644 index 000000000..1397b8d10 --- /dev/null +++ b/rpgJavaInterpreter-core/src/test/resources/smeup/MUDRNRAPU00189_P1.rpgle @@ -0,0 +1,35 @@ + V* ============================================================== + V* 13/01/2025 APU001 Creation + V* 13/01/2025 BENMAR Improvements + V* 15/01/2025 APU001 Clean code for more readable. + V* ============================================================== + O * PROGRAM GOAL + O * This program is used by 'MUDRNRAPU00189' for its purpose. + V* ============================================================== + FMULANGTL IF E K DISK + D ML E DS EXTNAME(MULANGTL) INZ + D MLL DS LIKEDS(ML) + + D DS0002 S LIKE(ML) + * + C MLSYST DSPLY + C MLPROG DSPLY + + C MLSYST CHAIN MULANGTL + + C MLSYST DSPLY + C MLPROG DSPLY + C MLL.MLSYST DSPLY + C MLL.MLPROG DSPLY + + C EVAL MLL=ML + + C MLL.MLSYST DSPLY + C MLL.MLPROG DSPLY + + C SETON LR + + C *INZSR BEGSR + C *ENTRY PLIST + C ML PARM ML DS0002 + C ENDSR \ No newline at end of file diff --git a/rpgJavaInterpreter-core/src/test/resources/symboltable/ST_PERFORMANCE_ACCESS01.rpgle b/rpgJavaInterpreter-core/src/test/resources/symboltable/ST_PERFORMANCE_ACCESS01.rpgle new file mode 100644 index 000000000..d3297abd3 --- /dev/null +++ b/rpgJavaInterpreter-core/src/test/resources/symboltable/ST_PERFORMANCE_ACCESS01.rpgle @@ -0,0 +1,536 @@ + V* ============================================================== + V* 27/11/2024 APU001 Creation + V* ============================================================== + O * PROGRAM GOAL + O * This test measures the execution time required to perform + O * repeated lookups of standalone fields and data structure + O * fields in a symbol table created from an Abstract + O * Syntax Tree (AST). + O * It verifies that the AST can be produced successfully and + O * evaluates the performance of symbol table lookups for + O * specific fields. + O * The goal is to evaluate the efficiency of symbol table lookups + O * and ensure performance is within an acceptable range. + V* ============================================================== + D VAR1 S 10 + D DS1 DS + D DS1_FLD1 50 + D DS1_FLD2 50 + D DS1_FLD3 50 + D DS1_FLD4 50 + D DS1_FLD5 50 + D DS1_FLD6 50 + D DS1_FLD7 50 + D DS1_FLD8 50 + D DS1_FLD9 50 + D DS1_FLD10 50 + D DS1_FLD11 50 + D DS1_FLD12 50 + D DS1_FLD13 50 + D DS1_FLD14 50 + D DS1_FLD15 50 + D DS1_FLD16 50 + D DS1_FLD17 50 + D DS1_FLD18 50 + D DS1_FLD19 50 + D DS1_FLD20 50 + D DS1_FLD21 50 + D DS1_FLD22 50 + D DS1_FLD23 50 + D DS1_FLD24 50 + D DS1_FLD25 50 + D DS1_FLD26 50 + D DS1_FLD27 50 + D DS1_FLD28 50 + D DS1_FLD29 50 + D DS1_FLD30 50 + D DS1_FLD31 50 + D DS1_FLD32 50 + D DS1_FLD33 50 + D DS1_FLD34 50 + D DS1_FLD35 50 + D DS1_FLD36 50 + D DS1_FLD37 50 + D DS1_FLD38 50 + D DS1_FLD39 50 + D DS1_FLD40 50 + D DS1_FLD41 50 + D DS1_FLD42 50 + D DS1_FLD43 50 + D DS1_FLD44 50 + D DS1_FLD45 50 + D DS1_FLD46 50 + D DS1_FLD47 50 + D DS1_FLD48 50 + D DS1_FLD49 50 + D DS1_FLD50 50 + + D DS2 DS + D DS2_FLD1 50 + D DS2_FLD2 50 + D DS2_FLD3 50 + D DS2_FLD4 50 + D DS2_FLD5 50 + D DS2_FLD6 50 + D DS2_FLD7 50 + D DS2_FLD8 50 + D DS2_FLD9 50 + D DS2_FLD10 50 + D DS2_FLD11 50 + D DS2_FLD12 50 + D DS2_FLD13 50 + D DS2_FLD14 50 + D DS2_FLD15 50 + D DS2_FLD16 50 + D DS2_FLD17 50 + D DS2_FLD18 50 + D DS2_FLD19 50 + D DS2_FLD20 50 + D DS2_FLD21 50 + D DS2_FLD22 50 + D DS2_FLD23 50 + D DS2_FLD24 50 + D DS2_FLD25 50 + D DS2_FLD26 50 + D DS2_FLD27 50 + D DS2_FLD28 50 + D DS2_FLD29 50 + D DS2_FLD30 50 + D DS2_FLD31 50 + D DS2_FLD32 50 + D DS2_FLD33 50 + D DS2_FLD34 50 + D DS2_FLD35 50 + D DS2_FLD36 50 + D DS2_FLD37 50 + D DS2_FLD38 50 + D DS2_FLD39 50 + D DS2_FLD40 50 + D DS2_FLD41 50 + D DS2_FLD42 50 + D DS2_FLD43 50 + D DS2_FLD44 50 + D DS2_FLD45 50 + D DS2_FLD46 50 + D DS2_FLD47 50 + D DS2_FLD48 50 + D DS2_FLD49 50 + D DS2_FLD50 50 + + D DS3 DS + D DS3_FLD1 50 + D DS3_FLD2 50 + D DS3_FLD3 50 + D DS3_FLD4 50 + D DS3_FLD5 50 + D DS3_FLD6 50 + D DS3_FLD7 50 + D DS3_FLD8 50 + D DS3_FLD9 50 + D DS3_FLD10 50 + D DS3_FLD11 50 + D DS3_FLD12 50 + D DS3_FLD13 50 + D DS3_FLD14 50 + D DS3_FLD15 50 + D DS3_FLD16 50 + D DS3_FLD17 50 + D DS3_FLD18 50 + D DS3_FLD19 50 + D DS3_FLD20 50 + D DS3_FLD21 50 + D DS3_FLD22 50 + D DS3_FLD23 50 + D DS3_FLD24 50 + D DS3_FLD25 50 + D DS3_FLD26 50 + D DS3_FLD27 50 + D DS3_FLD28 50 + D DS3_FLD29 50 + D DS3_FLD30 50 + D DS3_FLD31 50 + D DS3_FLD32 50 + D DS3_FLD33 50 + D DS3_FLD34 50 + D DS3_FLD35 50 + D DS3_FLD36 50 + D DS3_FLD37 50 + D DS3_FLD38 50 + D DS3_FLD39 50 + D DS3_FLD40 50 + D DS3_FLD41 50 + D DS3_FLD42 50 + D DS3_FLD43 50 + D DS3_FLD44 50 + D DS3_FLD45 50 + D DS3_FLD46 50 + D DS3_FLD47 50 + D DS3_FLD48 50 + D DS3_FLD49 50 + D DS3_FLD50 50 + + D DS4 DS + D DS4_FLD1 50 + D DS4_FLD2 50 + D DS4_FLD3 50 + D DS4_FLD4 50 + D DS4_FLD5 50 + D DS4_FLD6 50 + D DS4_FLD7 50 + D DS4_FLD8 50 + D DS4_FLD9 50 + D DS4_FLD10 50 + D DS4_FLD11 50 + D DS4_FLD12 50 + D DS4_FLD13 50 + D DS4_FLD14 50 + D DS4_FLD15 50 + D DS4_FLD16 50 + D DS4_FLD17 50 + D DS4_FLD18 50 + D DS4_FLD19 50 + D DS4_FLD20 50 + D DS4_FLD21 50 + D DS4_FLD22 50 + D DS4_FLD23 50 + D DS4_FLD24 50 + D DS4_FLD25 50 + D DS4_FLD26 50 + D DS4_FLD27 50 + D DS4_FLD28 50 + D DS4_FLD29 50 + D DS4_FLD30 50 + D DS4_FLD31 50 + D DS4_FLD32 50 + D DS4_FLD33 50 + D DS4_FLD34 50 + D DS4_FLD35 50 + D DS4_FLD36 50 + D DS4_FLD37 50 + D DS4_FLD38 50 + D DS4_FLD39 50 + D DS4_FLD40 50 + D DS4_FLD41 50 + D DS4_FLD42 50 + D DS4_FLD43 50 + D DS4_FLD44 50 + D DS4_FLD45 50 + D DS4_FLD46 50 + D DS4_FLD47 50 + D DS4_FLD48 50 + D DS4_FLD49 50 + D DS4_FLD50 50 + + D DS5 DS + D DS5_FLD1 50 + D DS5_FLD2 50 + D DS5_FLD3 50 + D DS5_FLD4 50 + D DS5_FLD5 50 + D DS5_FLD6 50 + D DS5_FLD7 50 + D DS5_FLD8 50 + D DS5_FLD9 50 + D DS5_FLD10 50 + D DS5_FLD11 50 + D DS5_FLD12 50 + D DS5_FLD13 50 + D DS5_FLD14 50 + D DS5_FLD15 50 + D DS5_FLD16 50 + D DS5_FLD17 50 + D DS5_FLD18 50 + D DS5_FLD19 50 + D DS5_FLD20 50 + D DS5_FLD21 50 + D DS5_FLD22 50 + D DS5_FLD23 50 + D DS5_FLD24 50 + D DS5_FLD25 50 + D DS5_FLD26 50 + D DS5_FLD27 50 + D DS5_FLD28 50 + D DS5_FLD29 50 + D DS5_FLD30 50 + D DS5_FLD31 50 + D DS5_FLD32 50 + D DS5_FLD33 50 + D DS5_FLD34 50 + D DS5_FLD35 50 + D DS5_FLD36 50 + D DS5_FLD37 50 + D DS5_FLD38 50 + D DS5_FLD39 50 + D DS5_FLD40 50 + D DS5_FLD41 50 + D DS5_FLD42 50 + D DS5_FLD43 50 + D DS5_FLD44 50 + D DS5_FLD45 50 + D DS5_FLD46 50 + D DS5_FLD47 50 + D DS5_FLD48 50 + D DS5_FLD49 50 + D DS5_FLD50 50 + + D DS6 DS + D DS6_FLD1 50 + D DS6_FLD2 50 + D DS6_FLD3 50 + D DS6_FLD4 50 + D DS6_FLD5 50 + D DS6_FLD6 50 + D DS6_FLD7 50 + D DS6_FLD8 50 + D DS6_FLD9 50 + D DS6_FLD10 50 + D DS6_FLD11 50 + D DS6_FLD12 50 + D DS6_FLD13 50 + D DS6_FLD14 50 + D DS6_FLD15 50 + D DS6_FLD16 50 + D DS6_FLD17 50 + D DS6_FLD18 50 + D DS6_FLD19 50 + D DS6_FLD20 50 + D DS6_FLD21 50 + D DS6_FLD22 50 + D DS6_FLD23 50 + D DS6_FLD24 50 + D DS6_FLD25 50 + D DS6_FLD26 50 + D DS6_FLD27 50 + D DS6_FLD28 50 + D DS6_FLD29 50 + D DS6_FLD30 50 + D DS6_FLD31 50 + D DS6_FLD32 50 + D DS6_FLD33 50 + D DS6_FLD34 50 + D DS6_FLD35 50 + D DS6_FLD36 50 + D DS6_FLD37 50 + D DS6_FLD38 50 + D DS6_FLD39 50 + D DS6_FLD40 50 + D DS6_FLD41 50 + D DS6_FLD42 50 + D DS6_FLD43 50 + D DS6_FLD44 50 + D DS6_FLD45 50 + D DS6_FLD46 50 + D DS6_FLD47 50 + D DS6_FLD48 50 + D DS6_FLD49 50 + D DS6_FLD50 50 + + D DS7 DS + D DS7_FLD1 50 + D DS7_FLD2 50 + D DS7_FLD3 50 + D DS7_FLD4 50 + D DS7_FLD5 50 + D DS7_FLD6 50 + D DS7_FLD7 50 + D DS7_FLD8 50 + D DS7_FLD9 50 + D DS7_FLD10 50 + D DS7_FLD11 50 + D DS7_FLD12 50 + D DS7_FLD13 50 + D DS7_FLD14 50 + D DS7_FLD15 50 + D DS7_FLD16 50 + D DS7_FLD17 50 + D DS7_FLD18 50 + D DS7_FLD19 50 + D DS7_FLD20 50 + D DS7_FLD21 50 + D DS7_FLD22 50 + D DS7_FLD23 50 + D DS7_FLD24 50 + D DS7_FLD25 50 + D DS7_FLD26 50 + D DS7_FLD27 50 + D DS7_FLD28 50 + D DS7_FLD29 50 + D DS7_FLD30 50 + D DS7_FLD31 50 + D DS7_FLD32 50 + D DS7_FLD33 50 + D DS7_FLD34 50 + D DS7_FLD35 50 + D DS7_FLD36 50 + D DS7_FLD37 50 + D DS7_FLD38 50 + D DS7_FLD39 50 + D DS7_FLD40 50 + D DS7_FLD41 50 + D DS7_FLD42 50 + D DS7_FLD43 50 + D DS7_FLD44 50 + D DS7_FLD45 50 + D DS7_FLD46 50 + D DS7_FLD47 50 + D DS7_FLD48 50 + D DS7_FLD49 50 + D DS7_FLD50 50 + + D DS8 DS + D DS8_FLD1 50 + D DS8_FLD2 50 + D DS8_FLD3 50 + D DS8_FLD4 50 + D DS8_FLD5 50 + D DS8_FLD6 50 + D DS8_FLD7 50 + D DS8_FLD8 50 + D DS8_FLD9 50 + D DS8_FLD10 50 + D DS8_FLD11 50 + D DS8_FLD12 50 + D DS8_FLD13 50 + D DS8_FLD14 50 + D DS8_FLD15 50 + D DS8_FLD16 50 + D DS8_FLD17 50 + D DS8_FLD18 50 + D DS8_FLD19 50 + D DS8_FLD20 50 + D DS8_FLD21 50 + D DS8_FLD22 50 + D DS8_FLD23 50 + D DS8_FLD24 50 + D DS8_FLD25 50 + D DS8_FLD26 50 + D DS8_FLD27 50 + D DS8_FLD28 50 + D DS8_FLD29 50 + D DS8_FLD30 50 + D DS8_FLD31 50 + D DS8_FLD32 50 + D DS8_FLD33 50 + D DS8_FLD34 50 + D DS8_FLD35 50 + D DS8_FLD36 50 + D DS8_FLD37 50 + D DS8_FLD38 50 + D DS8_FLD39 50 + D DS8_FLD40 50 + D DS8_FLD41 50 + D DS8_FLD42 50 + D DS8_FLD43 50 + D DS8_FLD44 50 + D DS8_FLD45 50 + D DS8_FLD46 50 + D DS8_FLD47 50 + D DS8_FLD48 50 + D DS8_FLD49 50 + D DS8_FLD50 50 + + D DS9 DS + D DS9_FLD1 50 + D DS9_FLD2 50 + D DS9_FLD3 50 + D DS9_FLD4 50 + D DS9_FLD5 50 + D DS9_FLD6 50 + D DS9_FLD7 50 + D DS9_FLD8 50 + D DS9_FLD9 50 + D DS9_FLD10 50 + D DS9_FLD11 50 + D DS9_FLD12 50 + D DS9_FLD13 50 + D DS9_FLD14 50 + D DS9_FLD15 50 + D DS9_FLD16 50 + D DS9_FLD17 50 + D DS9_FLD18 50 + D DS9_FLD19 50 + D DS9_FLD20 50 + D DS9_FLD21 50 + D DS9_FLD22 50 + D DS9_FLD23 50 + D DS9_FLD24 50 + D DS9_FLD25 50 + D DS9_FLD26 50 + D DS9_FLD27 50 + D DS9_FLD28 50 + D DS9_FLD29 50 + D DS9_FLD30 50 + D DS9_FLD31 50 + D DS9_FLD32 50 + D DS9_FLD33 50 + D DS9_FLD34 50 + D DS9_FLD35 50 + D DS9_FLD36 50 + D DS9_FLD37 50 + D DS9_FLD38 50 + D DS9_FLD39 50 + D DS9_FLD40 50 + D DS9_FLD41 50 + D DS9_FLD42 50 + D DS9_FLD43 50 + D DS9_FLD44 50 + D DS9_FLD45 50 + D DS9_FLD46 50 + D DS9_FLD47 50 + D DS9_FLD48 50 + D DS9_FLD49 50 + D DS9_FLD50 50 + + D DS10 DS + D DS10_FLD1 50 + D DS10_FLD2 50 + D DS10_FLD3 50 + D DS10_FLD4 50 + D DS10_FLD5 50 + D DS10_FLD6 50 + D DS10_FLD7 50 + D DS10_FLD8 50 + D DS10_FLD9 50 + D DS10_FLD10 50 + D DS10_FLD11 50 + D DS10_FLD12 50 + D DS10_FLD13 50 + D DS10_FLD14 50 + D DS10_FLD15 50 + D DS10_FLD16 50 + D DS10_FLD17 50 + D DS10_FLD18 50 + D DS10_FLD19 50 + D DS10_FLD20 50 + D DS10_FLD21 50 + D DS10_FLD22 50 + D DS10_FLD23 50 + D DS10_FLD24 50 + D DS10_FLD25 50 + D DS10_FLD26 50 + D DS10_FLD27 50 + D DS10_FLD28 50 + D DS10_FLD29 50 + D DS10_FLD30 50 + D DS10_FLD31 50 + D DS10_FLD32 50 + D DS10_FLD33 50 + D DS10_FLD34 50 + D DS10_FLD35 50 + D DS10_FLD36 50 + D DS10_FLD37 50 + D DS10_FLD38 50 + D DS10_FLD39 50 + D DS10_FLD40 50 + D DS10_FLD41 50 + D DS10_FLD42 50 + D DS10_FLD43 50 + D DS10_FLD44 50 + D DS10_FLD45 50 + D DS10_FLD46 50 + D DS10_FLD47 50 + D DS10_FLD48 50 + D DS10_FLD49 50 + D DS10_FLD50 50 + + C SETON LR \ No newline at end of file