Skip to content

Commit

Permalink
Merged develop
Browse files Browse the repository at this point in the history
  • Loading branch information
davidepalladino-apuliasoft committed Mar 20, 2024
2 parents a5fb94d + 0d8c161 commit 17e1230
Show file tree
Hide file tree
Showing 25 changed files with 593 additions and 54 deletions.
4 changes: 2 additions & 2 deletions rpgJavaInterpreter-core/src/main/antlr/RpgParser.g4
Original file line number Diff line number Diff line change
Expand Up @@ -1496,8 +1496,8 @@ csMULT:
csMVR:
CS_FIXED
BlankIndicator
BlankFlag
BlankIndicator
(BlankFlag | NoFlag)
(BlankIndicator | GeneralIndicator)
CS_BlankFactor
operation=OP_MVR
cspec_fixed_standard_parts;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,21 +206,19 @@ class ExpressionEvaluation(

override fun eval(expression: CharExpr): Value {
val value = expression.value.evalWith(this)
return if (expression.value is DivExpr) {
// are always return 10 decimal digits
// fill with 0 if necessary
if (value.asDecimal().value.scale() != 0) {
val numeDecimals = value.asDecimal().value.scale()
if (numeDecimals < 10) {
StringValue(value.stringRepresentation(expression.format) + "0".repeat(10 - numeDecimals))
} else {
StringValue(value.stringRepresentation(expression.format).trim())
}
} else {
StringValue(value.stringRepresentation(expression.format) + ".0000000000")
}
} else {
StringValue(value.stringRepresentation(expression.format))
val representation = value.stringRepresentation(expression.format)

if (expression.value !is DivExpr) {
return StringValue(representation)
}

// Decimals are always returned with 10 decimal digits
// fill with 0 if necessary
val numDecimals = value.asDecimal().value.scale()
return when {
numDecimals == 0 -> StringValue("$representation.0000000000")
numDecimals < 10 -> StringValue(representation + "0".repeat(10 - numDecimals))
else -> StringValue(representation.trim())
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,17 @@ class CasOtherExecutionLogEntry(programName: String, val other: CaseOtherClause,
}
}

class MonitorExecutionLogEntry(programName: String, val statement: MonitorStmt) : LogEntry(programName) {
override fun toString(): String {
return "executing MONITOR"
}

override fun renderStatement(channel: String, filename: String, sep: String): String {
val data = "MONITOR"
return renderHeader(channel, filename, statement.startLine(), sep) + data
}
}

class IfExecutionLogEntry(programName: String, val statement: IfStmt, val result: Value) : LogEntry(programName) {
override fun toString(): String {
return "executing IF"
Expand Down Expand Up @@ -442,6 +453,16 @@ class ElseExecutionLogEntry(programName: String, val statement: ElseClause, val
}
}

class OnErrorExecutionLogEntry(programName: String, val statement: OnErrorClause) : LogEntry(programName) {
override fun toString(): String {
return "executing ON-ERROR"
}
override fun renderStatement(channel: String, filename: String, sep: String): String {
val data = "ON-ERROR"
return renderHeader(channel, filename, statement.startLine(), sep) + data
}
}

class EvaluationLogEntry(programName: String, val statement: EvalStmt, val value: Value?) : LogEntry(programName) {
override fun toString(): String {
return "evaluating $statement as $value"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,10 @@ data class IntValue(val value: Long) : NumberValue() {
return StringValue(render())
}

override fun asBoolean(): BooleanValue {
return BooleanValue(value > 0)
}

operator fun plus(other: IntValue) = IntValue(this.bigDecimal.plus(other.bigDecimal).longValueExact())

operator fun minus(other: IntValue) = IntValue(this.bigDecimal.minus(other.bigDecimal).longValueExact())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ private val modules = SerializersModule {
subclass(LeaveSrStmt::class)
subclass(LeaveStmt::class)
subclass(LookupStmt::class)
subclass(MonitorStmt::class)
subclass(MoveAStmt::class)
subclass(MoveLStmt::class)
subclass(MoveStmt::class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,62 @@ private constructor(val name: String, val fields: List<String>, override val pos
}
}

@Serializable
data class MonitorStmt(
@SerialName("body")
val monitorBody: List<Statement>,
val onErrorClauses: List<OnErrorClause> = emptyList(),
override val position: Position? = null
) : Statement(position), CompositeStatement {

// Since that this property is a collection achieved from thenBody + elseIfClauses + elseClause, this annotation
// is necessary to avoid that the same node is processed more than ones, thing that it would cause that the same
// ErrorEvent is fired more times
@Derived
@Transient
override val body: List<Statement> = mutableListOf<Statement>().apply {
addAll(monitorBody)
onErrorClauses.forEach { addAll(it.body) }
}

override fun accept(mutes: MutableMap<Int, MuteParser.MuteLineContext>, start: Int, end: Int): MutableList<MuteAnnotationResolved> {
// check if the annotation is just before the ELSE
val muteAttached: MutableList<MuteAnnotationResolved> = mutableListOf()

// Process the body statements
muteAttached.addAll(
acceptBody(monitorBody, mutes, this.position!!.start.line, this.position.end.line)
)

// Process the ON ERROR
onErrorClauses.forEach {
muteAttached.addAll(
acceptBody(it.body, mutes, it.position!!.start.line, it.position.end.line)
)
}

return muteAttached
}

override fun execute(interpreter: InterpreterCore) {
interpreter.log {
MonitorExecutionLogEntry(
interpreter.getInterpretationContext().currentProgramName,
this
)
}

try {
interpreter.execute(this.monitorBody)
} catch (_: Exception) {
onErrorClauses.forEach {
interpreter.log { OnErrorExecutionLogEntry(interpreter.getInterpretationContext().currentProgramName, it) }
interpreter.execute(it.body)
}
}
}
}

@Serializable
data class IfStmt(
val condition: Expression,
Expand Down Expand Up @@ -889,6 +945,9 @@ data class IfStmt(
}
}

@Serializable
data class OnErrorClause(override val body: List<Statement>, override val position: Position? = null) : Node(position), CompositeStatement

@Serializable
data class ElseClause(override val body: List<Statement>, override val position: Position? = null) : Node(position), CompositeStatement

Expand Down Expand Up @@ -1061,7 +1120,7 @@ data class DefineStmt(
} else {
val inStatementDataDefinition =
containingCU.main.stmts
.filterIsInstance(StatementThatCanDefineData::class.java)
.filterIsInstance<StatementThatCanDefineData>()
.filter { it != this }
.asSequence()
.map(StatementThatCanDefineData::dataDefinition)
Expand Down Expand Up @@ -1719,21 +1778,23 @@ data class ScanStmt(
val left: Expression,
val leftLength: Int?,
val right: Expression,
val startPosition: Int,
val startPosition: Expression?,
val target: AssignableExpression?,
val rightIndicators: WithRightIndicators,
@Derived val dataDefinition: InStatementDataDefinition? = null,
override val position: Position? = null
) : Statement(position), WithRightIndicators by rightIndicators, StatementThatCanDefineData {

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

val stringToSearch = interpreter.eval(left).asString().value.substringOfLength(leftLength)
val searchInto = interpreter.eval(right).asString().value.substring(startPosition - 1)
val searchInto = interpreter.eval(right).asString().value.substring(start - 1)
val occurrences = mutableListOf<Value>()
var index = -1
do {
index = searchInto.indexOf(stringToSearch, index + 1)
if (index >= 0) occurrences.add(IntValue((index + startPosition).toLong()))
if (index >= 0) occurrences.add(IntValue((index + start).toLong()))
} while (index >= 0)
if (occurrences.isEmpty()) {
interpreter.setIndicators(this, BooleanValue.FALSE, BooleanValue.FALSE, BooleanValue.FALSE)
Expand Down Expand Up @@ -1968,22 +2029,27 @@ data class XlateStmt(
@Serializable
data class ResetStmt(
val name: String,
@Derived val dataDefinition: InStatementDataDefinition? = null,
override val position: Position? = null
) : Statement(position) {
) : Statement(position), StatementThatCanDefineData {

override fun execute(interpreter: InterpreterCore) {
val dataDefinition = interpreter.dataDefinitionByName(name)
require(dataDefinition != null) {
this.error("Data definition $name not found")
}
require(dataDefinition is DataDefinition) {
this.error("Data definition $name is not an instance of DataDefinition")
}
require(dataDefinition.defaultValue != null) {
this.error("Data definition $name has no default value")
when (val dataDefinition = interpreter.dataDefinitionByName(name)) {
null -> this.error("Data definition $name not found")
is DataDefinition -> {
require(dataDefinition.defaultValue != null) {
this.error("Data definition $name has no default value")
}
interpreter.assign(dataDefinition, dataDefinition.defaultValue!!)
}
is InStatementDataDefinition -> {
interpreter.assign(dataDefinition, dataDefinition.type.blank())
}
else -> this.error("Data definition $name is not a valid instance of DataDefinition")
}
interpreter.assign(dataDefinition, dataDefinition.defaultValue!!)
}

override fun dataDefinition(): List<InStatementDataDefinition> = dataDefinition?.let { listOf(it) } ?: emptyList()
}

@Serializable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1031,10 +1031,10 @@ internal fun ResultTypeContext.toAst(conf: ToAstConfiguration = ToAstConfigurati
// what kind of expression is this
val position = toPosition(conf.considerPosition)

if (text.contains('.')) {
return handleParsingOfTargets(text, position)
return if (text.contains('.')) {
handleParsingOfTargets(text, position)
} else {
return annidatedReferenceExpression(text, position)
annidatedReferenceExpression(text, position)
}
}

Expand Down Expand Up @@ -1121,10 +1121,7 @@ internal fun Cspec_fixed_standard_partsContext.toDataDefinition(
position: Position?,
conf: ToAstConfiguration
): InStatementDataDefinition? {
val len = this.len.asInt()
if (len == null) {
return null
}
val len = this.len.asInt() ?: return null
val decimals = this.decimalPositions.asInt()
val initialValue = this.factor2Expression(conf)
return InStatementDataDefinition(name, dataType(len, decimals), position, initializationValue = initialValue)
Expand Down Expand Up @@ -1316,20 +1313,30 @@ internal fun CsDELETEContext.toAst(conf: ToAstConfiguration): Statement {

internal fun CsSCANContext.toAst(conf: ToAstConfiguration = ToAstConfiguration()): ScanStmt {
val position = toPosition(conf.considerPosition)

val (compareExpression, compareLength) = this.factor1Context().toIndexedExpression(conf)
val (baseExpression, startPosition) = this.cspec_fixed_standard_parts().factor2.toIndexedExpression(conf)

val factor2 = this.cspec_fixed_standard_parts().factor2

val result = this.cspec_fixed_standard_parts().result
val dataDefinition = this.cspec_fixed_standard_parts().toDataDefinition(result.text, position, conf)

val rightIndicators = cspec_fixed_standard_parts().rightIndicators()
val result = this.cspec_fixed_standard_parts().result.text
val dataDefinition = this.cspec_fixed_standard_parts().toDataDefinition(result, position, conf)
val target = when {
result.isNotBlank() -> this.cspec_fixed_standard_parts()!!.result!!.toAst(conf)
else -> null
}
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
}

return ScanStmt(
left = compareExpression,
leftLength = compareLength,
right = baseExpression,
startPosition = startPosition ?: 1,
startPosition = positionExpression,
target = target,
rightIndicators = rightIndicators,
dataDefinition = dataDefinition,
Expand All @@ -1345,11 +1352,19 @@ internal fun CsCHECKContext.toAst(conf: ToAstConfiguration): Statement {
val result = this.cspec_fixed_standard_parts().result
val dataDefinition = this.cspec_fixed_standard_parts().toDataDefinition(result.text, position, conf)

val eqIndicator = this.cspec_fixed_standard_parts().resultIndicator(2)?.text

val wrongCharExpression = when {
result != null && result.text.isNotBlank() -> result.toAst(conf)
!eqIndicator.isNullOrBlank() -> IndicatorExpr(eqIndicator.toIndicatorKey(), position)
else -> null
}

return CheckStmt(
factor1,
expression,
startPosition ?: 1,
this.cspec_fixed_standard_parts()?.result?.toAst(conf),
wrongCharExpression,
dataDefinition,
position
)
Expand Down Expand Up @@ -1378,8 +1393,6 @@ private fun FactorContext.toIndexedExpression(conf: ToAstConfiguration): Pair<Ex
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?> {
fun String.isLiteral(): Boolean { return (startsWith('\'') && endsWith('\'')) }

val baseStringTokens = this.split(":")
val startPosition =
when (baseStringTokens.size) {
Expand All @@ -1389,7 +1402,10 @@ private fun String.toIndexedExpression(position: Position?): Pair<Expression, In
}
val reference = baseStringTokens[0]
return when {
reference.isLiteral() -> StringLiteral(reference.trim('\''), position)
reference.isStringLiteral() -> StringLiteral(reference.trim('\''), position)
reference.contains('(') && reference.endsWith(")") -> {
annidatedReferenceExpression(this, position)
}
else -> DataRefExpr(ReferenceByName(reference), position)
} to startPosition
}
Expand Down Expand Up @@ -1940,6 +1956,7 @@ internal fun CsCLOSEContext.toAst(conf: ToAstConfiguration = ToAstConfiguration(

internal fun CsRESETContext.toAst(conf: ToAstConfiguration = ToAstConfiguration()): Statement {
val position = toPosition(conf.considerPosition)

require(this.cspec_fixed_standard_parts().factor().text.isEmptyTrim()) {
"RESET operation does not support factor1"
}
Expand All @@ -1950,8 +1967,12 @@ internal fun CsRESETContext.toAst(conf: ToAstConfiguration = ToAstConfiguration(
require(!result.isEmptyTrim()) {
"RESET operation requires result"
}

val dataDefinition = this.cspec_fixed_standard_parts().toDataDefinition(result, position, conf)

return ResetStmt(
name = result,
dataDefinition = dataDefinition,
position = position
)
}
Expand Down Expand Up @@ -2037,3 +2058,5 @@ private fun <T : AbstractDataDefinition> List<T>.removeUnnecessaryRecordFormat()
dataDef.type is RecordFormatType && this.any { it.type is DataStructureType && it.name.uppercase() == dataDef.name.uppercase() }
}
}

private fun String.isStringLiteral(): Boolean = startsWith('\'') && endsWith('\'')
Loading

0 comments on commit 17e1230

Please sign in to comment.