Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix/ls24005243/checkr factor2 expression #676

Merged
merged 12 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -817,9 +817,9 @@ data class SetgtStmt(

@Serializable
data class CheckStmt(
val comparatorString: Expression, // Factor1
val baseString: Expression,
val start: Int = 1,
var comparatorString: Expression, // Factor1
var baseString: Expression,
var startPosition: Expression?,
val wrongCharPosition: AssignableExpression?,
@Derived val dataDefinition: InStatementDataDefinition? = null,
override val position: Position? = null
Expand All @@ -828,9 +828,10 @@ data class CheckStmt(
get() = "CHECK"

override fun execute(interpreter: InterpreterCore) {
val start = startPosition?.let { interpreter.eval(it).asString().value.toInt() } ?: 1
var baseString = interpreter.eval(this.baseString).asString().value
if (this.baseString is DataRefExpr) {
baseString = baseString.padEnd(this.baseString.size())
baseString = baseString.padEnd((this.baseString as DataRefExpr).size())
}
val charSet = interpreter.eval(comparatorString).asString().value
val wrongIndex = wrongCharPosition
Expand All @@ -854,9 +855,9 @@ data class CheckStmt(

@Serializable
data class CheckrStmt(
val comparatorString: Expression, // Factor1
val baseString: Expression,
val start: Int = 1,
var comparatorString: Expression, // Factor1
lanarimarco marked this conversation as resolved.
Show resolved Hide resolved
var baseString: Expression,
var startPosition: Expression?,
val wrongCharPosition: AssignableExpression?,
@Derived val dataDefinition: InStatementDataDefinition? = null,
override val position: Position? = null
Expand All @@ -865,9 +866,10 @@ data class CheckrStmt(
get() = "CHECKR"

override fun execute(interpreter: InterpreterCore) {
val start = startPosition?.let { interpreter.eval(it).asString().value.toInt() } ?: 1
var baseString = interpreter.eval(this.baseString).asString().value
if (this.baseString is DataRefExpr) {
baseString = baseString.padEnd(this.baseString.size())
baseString = baseString.padEnd((this.baseString as DataRefExpr).size())
}
val charSet = interpreter.eval(comparatorString).asString().value
val wrongIndex = wrongCharPosition
Expand Down Expand Up @@ -2351,10 +2353,10 @@ data class LookupStmt(

@Serializable
data class ScanStmt(
val left: Expression,
val leftLength: Int?,
val right: Expression,
val startPosition: Expression?,
var left: Expression,
var leftLengthExpression: Expression?,
var right: Expression,
var startPosition: Expression?,
val target: AssignableExpression?,
val rightIndicators: WithRightIndicators,
@Derived val dataDefinition: InStatementDataDefinition? = null,
Expand All @@ -2364,6 +2366,7 @@ data class ScanStmt(
get() = "SCAN"

override fun execute(interpreter: InterpreterCore) {
val leftLength = leftLengthExpression?.let { interpreter.eval(it).asString().value.toInt() }
val start = startPosition?.let { interpreter.eval(it).asString().value.toInt() } ?: 1

val stringToSearch = interpreter.eval(left).asString().value.substringOfLength(leftLength)
Expand Down Expand Up @@ -2589,10 +2592,10 @@ data class CloseStmt(
*/
@Serializable
data class XlateStmt(
val from: Expression,
val to: Expression,
val string: Expression,
val startPos: Int,
var from: Expression,
var to: Expression,
var string: Expression,
var startPosition: Expression?,
val target: AssignableExpression,
val rightIndicators: WithRightIndicators,
@Derived val dataDefinition: InStatementDataDefinition? = null,
Expand All @@ -2604,7 +2607,7 @@ data class XlateStmt(
override fun execute(interpreter: InterpreterCore) {
val originalChars = interpreter.eval(from).asString().value
val newChars = interpreter.eval(to).asString().value
val start = startPos
val start = startPosition?.let { interpreter.eval(it).asString().value.toInt() } ?: 1
val s = interpreter.eval(string).asString().value
val pair = s.divideAtIndex(start - 1)
var right = pair.second
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1464,17 +1464,11 @@ internal fun CsSCANContext.toAst(conf: ToAstConfiguration = ToAstConfiguration()
val rightIndicators = cspec_fixed_standard_parts().rightIndicators()
val target = if (result.text.isNotBlank()) result.toAst(conf) else null

val baseExpression = factor2.factorContent(0).toAst(conf)
val positionExpression =
if (factor2.factorContent().size > 1) {
factor2.factorContent(1).toAst(conf)
} else {
null
}
val (baseExpression, positionExpression) = factor2.toIndexedExpression(conf)

return ScanStmt(
left = compareExpression,
leftLength = compareLength,
leftLengthExpression = compareLength,
right = baseExpression,
startPosition = positionExpression,
target = target,
Expand All @@ -1487,7 +1481,7 @@ internal fun CsSCANContext.toAst(conf: ToAstConfiguration = ToAstConfiguration()
internal fun CsCHECKContext.toAst(conf: ToAstConfiguration): Statement {
val position = toPosition(conf.considerPosition)
val factor1 = this.factor1Context()?.content?.toAst(conf) ?: throw UnsupportedOperationException("CHECK operation requires factor 1: ${this.text} - ${position.atLine()}")
val (expression, startPosition) = this.cspec_fixed_standard_parts().factor2.toIndexedExpression(conf)
val (expression, startExpression) = this.cspec_fixed_standard_parts().factor2.toIndexedExpression(conf)

val result = this.cspec_fixed_standard_parts().result
val dataDefinition = this.cspec_fixed_standard_parts().toDataDefinition(result.text, position, conf)
Expand All @@ -1503,7 +1497,7 @@ internal fun CsCHECKContext.toAst(conf: ToAstConfiguration): Statement {
return CheckStmt(
factor1,
expression,
startPosition ?: 1,
startExpression,
wrongCharExpression,
dataDefinition,
position
Expand All @@ -1513,7 +1507,8 @@ internal fun CsCHECKContext.toAst(conf: ToAstConfiguration): Statement {
internal fun CsCHECKRContext.toAst(conf: ToAstConfiguration): Statement {
val position = toPosition(conf.considerPosition)
val factor1 = this.factor1Context()?.content?.toAst(conf) ?: throw UnsupportedOperationException("CHECKR operation requires factor 1: ${this.text} - ${position.atLine()}")
val (expression, startPosition) = this.cspec_fixed_standard_parts().factor2.toIndexedExpression(conf)
val factor2 = this.cspec_fixed_standard_parts().factor2
val (expression, positionExpression) = factor2.toIndexedExpression(conf)

val result = this.cspec_fixed_standard_parts().result
val dataDefinition = this.cspec_fixed_standard_parts().toDataDefinition(result.text, position, conf)
Expand All @@ -1529,13 +1524,24 @@ internal fun CsCHECKRContext.toAst(conf: ToAstConfiguration): Statement {
return CheckrStmt(
factor1,
expression,
startPosition ?: 1,
positionExpression,
wrongCharExpression,
dataDefinition,
position
)
}

private fun FactorContext.toIndexedExpression(conf: ToAstConfiguration): Pair<Expression, Expression?> {
// factor is formed by TEXT:B
// where "TEXT" is the content to be referenced positionally
val expression = this.factorContent(0).toAst(conf)
val positionExpression = if (this.factorContent().size > 1) {
this.factorContent(1).toAst(conf)
} else null

return expression to positionExpression
}

private fun FactorContext.toDoubleExpression(conf: ToAstConfiguration, index: Int): Expression =
if (this.text.contains(":")) this.text.toDoubleExpression(toPosition(conf.considerPosition), index) else this.content.toAst(conf)

Expand All @@ -1554,29 +1560,6 @@ private fun String.toDoubleExpression(position: Position?, index: Int): Expressi
return ret
}

private fun FactorContext.toIndexedExpression(conf: ToAstConfiguration): Pair<Expression, Int?> =
if (this.text.contains(":")) this.text.toIndexedExpression(toPosition(conf.considerPosition)) else this.content.toAst(conf) to null

private fun String.toIndexedExpression(position: Position?): Pair<Expression, Int?> {
val quoteAwareSplitPattern = Regex(""":(?=([^']*'[^']*')*[^']*$)""")
val baseStringTokens = this.split(quoteAwareSplitPattern)

val startPosition =
when (baseStringTokens.size) {
!in 1..2 -> throw UnsupportedOperationException("Wrong base string expression at line ${position?.line()}: $this")
2 -> baseStringTokens[1].toInt()
else -> null
}
val reference = baseStringTokens[0]
return when {
reference.isStringLiteral() -> StringLiteral(reference.trim('\''), position)
reference.contains('(') && reference.endsWith(")") -> {
annidatedReferenceExpression(this, position)
}
else -> DataRefExpr(ReferenceByName(reference), position)
} to startPosition
}

internal fun CsMOVEAContext.toAst(conf: ToAstConfiguration = ToAstConfiguration()): MoveAStmt {
val position = toPosition(conf.considerPosition)
val expression = this.cspec_fixed_standard_parts().factor2Expression(conf) ?: throw UnsupportedOperationException("MOVEA operation requires factor 2: ${this.text} - ${position.atLine()}")
Expand Down Expand Up @@ -2045,17 +2028,7 @@ internal fun CsSUBSTContext.toAst(conf: ToAstConfiguration = ToAstConfiguration(
// Left expression contain length
val length = leftExpr(conf)

// factor2 is formed by TEXT:B
// where "TEXT" is the content to be substringed
val stringExpression = this.cspec_fixed_standard_parts().factor2.factorContent(0).toAst(conf)
// and "B" is the start position to substring, if not specified it returns null
val positionExpression =
if (this.cspec_fixed_standard_parts().factor2.factorContent().size > 1) {
this.cspec_fixed_standard_parts().factor2.factorContent(1).toAst(conf)
} else {
null
}

val (stringExpression, positionExpression) = this.cspec_fixed_standard_parts().factor2.toIndexedExpression(conf)
val result = this.cspec_fixed_standard_parts().result.text
val dataDefinition = this.cspec_fixed_standard_parts().toDataDefinition(result, position, conf)

Expand Down Expand Up @@ -2100,8 +2073,8 @@ internal fun CsXLATEContext.toAst(conf: ToAstConfiguration = ToAstConfiguration(
from = from,
to = to,
string = string,
startPos = startPosition ?: 1,
target = this.cspec_fixed_standard_parts()!!.result!!.toAst(conf),
startPosition = startPosition,
target = this.cspec_fixed_standard_parts().result.toAst(conf),
rightIndicators = rightIndicators,
dataDefinition = dataDefinition,
position = position
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2581,6 +2581,12 @@ Test 6
assertEquals(expected, "PRSLTCALLERDUPLICATE".outputOf())
}

@Test
fun executeFUNCALLMUTABILITY() {
val expected = listOf("ok")
assertEquals(expected, "FUNCALLMUTABILITY".outputOf())
}

@Test
fun missingDefinitionOnPListShouldThrowResolutionError() {
val systemInterface = JavaSystemInterface()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,16 @@ open class MULANGT10BaseCodopTest : MULANGTTest() {
assertEquals(expected, "smeup/MUDRNRAPU00274".outputOf(configuration = smeupConfig))
}

/**
* CHECKR with indexed expression based on a Data Reference
* @see #LS24005243
*/
@Test
fun executeMUDRNRAPU00275() {
val expected = listOf("ok")
assertEquals(expected, "smeup/MUDRNRAPU00275".outputOf(configuration = turnOnZAddLegacyFlagConfig))
}

/**
* Unary expression with '+'
* @see #LS24005278
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
V* ==============================================================
V* 09/12/2024 APU002 Creation
V* ==============================================================
O * PROGRAM GOAL
O * Test various statements accessing array access expression
V* ==============================================================
O * JARIKO ANOMALY
O * Before the fix, jariko throw a mutability error
V* ==============================================================
D* Helper declarations
D £DBG_Str S 2
D ARR S 15 DIM(40)
D I S 5 0
D$A S 2 0
D $LNGSTR S 15
C* Values initialization
C EVAL I=2
C EVAL ARR(I)=2
C EVAL $LNGSTR='long string'
C EVAL $A=2
C* CHECK statement
C ARR(I) CHECK $LNGSTR:$A $A
C $A CHECK $LNGSTR:$A ARR(I)
C* CHECKR statement
C ARR(I) CHECKR $LNGSTR:$A $A
C $A CHECKR $LNGSTR:$A ARR(I)
C* Output
C EVAL £DBG_Str='ok'
C £DBG_Str DSPLY
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
V* ==============================================================
V* 04/12/2024 APU002 Creation
V* ==============================================================
O * PROGRAM GOAL
O * CHECKR with indexed expression based on a Data Reference
V* ==============================================================
O * JARIKO ANOMALY
O * Before the fix, jariko throw a syntax error
V* ============================================================== DA1 S 1
DN2 S 2 0
D T$C5MD S 15
DA1 S 2
C A1 CHECKR T$C5MD:N2 N2
C 'ok' DSPLY
Loading