SIGN IN SIGN UP

fix(interpreter): give a loop left via break/continue status 0 (#417)

* fix(interpreter): give a loop left via break/continue status 0

`break` and `continue` are builtins that return 0, and they are the last
command a loop body runs. All four loop forms kept `exitCode` at the
status of whatever ran before them, so the loop reported that instead:

    while :; do false; break; done; echo $?     # was 1, bash says 0

`handleLoopError` now reports the builtin's own status alongside the
break/continue action, and each loop adopts it. The hand-rolled
break/continue path in a `while` condition resets the status too.

`continue` sets the status without pinning it - a later iteration still
overwrites it - and a loop that ends normally is unchanged.

Reported downstream as ai-ecoverse/slicc#2978.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Lars Trieloff <lars@trieloff.net>

* fix(interpreter): move $? with the status a loop adopts on continue

The previous commit corrected the value a loop returns, but `$?` still
read the command before the `continue`. A `for` loop runs nothing between
the builtin and the next iteration's first command, so the failure stayed
visible there:

    for i in 1 2; do echo "$i:$?"; false; continue; done
    # was 1:0 2:1, bash says 1:0 2:0

New `adoptLoopStatus` sets the loop's exit code and `ctx.state.lastExitCode`
together, and every site that consumes a break/continue goes through it -
the four loop bodies, the while-condition path, and the multi-level
`continue n` that unwinds into an enclosing loop.

`while`/`until` masked the bug because their condition runs between
iterations and resets `$?`; they are covered now too.

The test asserting this previously read `$?` after a `[` command, so it
only ever saw that command's status. It now reads `$?` as the body's first
command, which is the only position that can observe a stale value.

Reported downstream as ai-ecoverse/slicc#2978.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Lars Trieloff <lars@trieloff.net>

---------

Signed-off-by: Lars Trieloff <lars@trieloff.net>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
L
Lars Trieloff committed
017a911d3b687d44bb0e2de707b78f02ec825569
Parent: cc35fab
Committed by GitHub <noreply@github.com> on 9/27/2026, 9:17:21 PM