Skip to content

Commit

Permalink
Merge pull request #666 from smeup/bugfix/LS24005012/goto-in-call
Browse files Browse the repository at this point in the history
Bugfix/ls24005012/goto in call
  • Loading branch information
lanarimarco authored Nov 25, 2024
2 parents 334aad3 + 8e8c96c commit 48c6aa6
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 15 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.smeup.rpgparser.interpreter

import com.smeup.rpgparser.execution.MainExecutionContext
import com.smeup.rpgparser.parsing.ast.Statement
import com.smeup.rpgparser.utils.indexOfTag
import com.smeup.rpgparser.utils.runIfNotEmpty
Expand Down Expand Up @@ -44,15 +43,6 @@ class GotoException private constructor(val tag: String) : ControlFlowException(
internal fun indexOfTaggedStatement(statements: List<Statement>) = statements.indexOfTag(tag)
}

/**
* Produce a scoped goto exception
*/
internal fun produceGotoInCurrentScope(tag: String): ControlFlowException {
val shouldLookupTopLevel = MainExecutionContext.getSubroutineStack().isEmpty()
val normalizedTag = tag.lowercase()
return if (shouldLookupTopLevel) GotoTopLevelException(normalizedTag) else GotoException(normalizedTag)
}

class InterpreterTimeoutException(val programName: String, val elapsed: Long, val expected: Long) : ControlFlowException() {
fun ratio(): Double = if (elapsed <= 0) 0.0 else elapsed.toDouble() / expected.toDouble()
override fun toString(): String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import com.smeup.rpgparser.parsing.facade.SourceReference
import com.smeup.rpgparser.parsing.facade.dumpSource
import com.smeup.rpgparser.parsing.facade.relative
import com.smeup.rpgparser.parsing.parsetreetoast.RpgType
import com.smeup.rpgparser.parsing.parsetreetoast.error
import com.smeup.rpgparser.parsing.parsetreetoast.resolveAndValidate
import com.smeup.rpgparser.parsing.parsetreetoast.todo
import com.smeup.rpgparser.utils.ComparisonOperator.*
Expand Down Expand Up @@ -427,10 +428,15 @@ open class InternalInterpreter(
val unwrappedStatement = main.stmts.explode(true)

// Recursive deal with top level goto flow
while (throwable is GotoTopLevelException) {
while (throwable is GotoTopLevelException || throwable is GotoException) {
// We need to know the statement unwrapped in order to jump directly into a nested tag
val offset = throwable.indexOfTaggedStatement(unwrappedStatement)
require(0 <= offset && offset < unwrappedStatement.size) { "Offset $offset is not valid." }
val (offset, tag) = when (throwable) {
is GotoException -> Pair(throwable.indexOfTaggedStatement(unwrappedStatement), throwable.tag)
is GotoTopLevelException -> Pair(throwable.indexOfTaggedStatement(unwrappedStatement), throwable.tag)
else -> Pair(-1, "")
}
if (unwrappedStatement.size <= offset || offset < 0)
main.error("GOTO offset $offset is not valid. Cannot find TAG '$tag'")
throwable = kotlin.runCatching {
executeUnwrappedAt(unwrappedStatement, offset)
}.exceptionOrNull()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1911,7 +1911,7 @@ data class GotoStmt(val tag: String, override val position: Position? = null) :
get() = "GOTO"

override fun execute(interpreter: InterpreterCore) {
throw produceGotoInCurrentScope(tag)
throw GotoException(tag)
}
}

Expand All @@ -1935,7 +1935,7 @@ data class CabStmt(
SMALLER -> interpreter.setIndicators(this, BooleanValue.FALSE, BooleanValue.TRUE, BooleanValue.FALSE)
else -> interpreter.setIndicators(this, BooleanValue.FALSE, BooleanValue.FALSE, BooleanValue.TRUE)
}
if (comparisonResult.isVerified) throw produceGotoInCurrentScope(tag)
if (comparisonResult.isVerified) throw GotoException(tag)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1399,6 +1399,12 @@ Test 6
assertEquals(expected, outputOf("GOTOTST9"))
}

@Test
fun executeGOTOTST10() {
val expected = listOf("ok", "ok")
assertEquals(expected, outputOf("GOTOTST10"))
}

@Test
fun executeGotoENDSR() {
assertEquals(listOf("1", "2", "3"), outputOf("GOTOENDSR"))
Expand Down
13 changes: 13 additions & 0 deletions rpgJavaInterpreter-core/src/test/resources/GOTOTST10.rpgle
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
V* ==============================================================
V* 25/11/2024 APU002 Creation
V* ==============================================================
O * PROGRAM GOAL
O * Execute a subroutine with a CALL to a program performing a top-level GOTO
V* ==============================================================
C EXSR SR1
C SETON LR

C SR1 BEGSR
C CALL 'GOTOTST10B'
C 'ok' DSPLY
C ENDSR
10 changes: 10 additions & 0 deletions rpgJavaInterpreter-core/src/test/resources/GOTOTST10B.rpgle
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
V* ==============================================================
V* 25/11/2024 APU002 Creation
V* ==============================================================
O * PROGRAM GOAL
O * Being called by 'GOTOTST10.rpgle'
V* ==============================================================
C GOTO TAG1
C 'ko' DSPLY
C TAG1 TAG
C 'ok' DSPLY

0 comments on commit 48c6aa6

Please sign in to comment.