Skip to content

Fix eval interpreter catchup: 11 bytecode compiler/interpreter fixes#241

Merged
fglock merged 2 commits into
masterfrom
fix-eval-interpreter-catchup
Feb 26, 2026
Merged

Fix eval interpreter catchup: 11 bytecode compiler/interpreter fixes#241
fglock merged 2 commits into
masterfrom
fix-eval-interpreter-catchup

Conversation

@fglock
Copy link
Copy Markdown
Owner

@fglock fglock commented Feb 26, 2026

Summary

Batch of fixes to close the gap between JVM-compiled and bytecode-interpreter execution paths for eval STRING (JPERL_EVAL_USE_INTERPRETER=1).

Fixes in this PR

  • Interpreter PC tracking & #line supportcaller() and stack traces now report correct file/line inside eval strings, honoring #line directives
  • Eval context propagation — eval STRING correctly propagates VOID/SCALAR/LIST/RUNTIME context and eval tracing
  • Logical or/|| in RUNTIME context — LHS uses SCALAR for truthiness, RHS inherits enclosing context
  • $SIG{__DIE__} in eval — exception handling routes through WarnDie.catchEval
  • Lexical scalar assignment — uses SET_SCALAR to preserve lvalue semantics, avoids aliasing bugs
  • Yadayada (...) expression context — parser now correctly errors on expression-context usage
  • local *glob = value — bytecode compiler supports local glob assignment
  • kvhslice scalar contextLIST_TO_SCALAR opcode returns last element instead of count
  • Logical operator context for wantarray — RHS of \|\|/&&/// inherits enclosing context
  • Unary minus in list context — compiles operand in scalar context to avoid ClassCastException on -(42)
  • #line directive trackinggetSourceLocationAccurate() uses original filename so directives don't retroactively change earlier tokens
  • Strict/feature/warning scopingenterScope()/exitScope() now push/pop pragma stacks so {use strict;} is properly block-scoped
  • Non-local loop control in evallast/next/redo LABEL across eval boundaries emits CREATE_LAST + RETURN instead of compile-time error
  • Undefined subroutine error messages — constructs full sub name from code object metadata instead of generic "Not a CODE reference"

Test plan

  • ./gradlew classes testUnitParallel --parallel shadowJar passes
  • All 5 targeted test files now match between normal and interpreter modes:
    • base/lex.t, comp/parser.t, comp/use.t, uni/caller.t, uni/labels.t
  • Previously fixed tests remain green: op/wantarray.t, op/kvhslice.t, comp/fold.t, op/signatures.t
  • No new regressions in uni/gv.t (test 169 diff is pre-existing false positive)

Generated with Devin

fglock and others added 2 commits February 26, 2026 18:41
… strict scoping, non-local control flow, undefined sub errors

- CompileOperator: compile unaryMinus operand in scalar context to avoid
  ClassCastException when negating parenthesized expressions in list context
- ErrorMessageUtil: use originalFileName in getSourceLocationAccurate() so
  #line directives do not retroactively change filename for earlier tokens
- BytecodeCompiler: push/pop strict/feature/warning flags in enterScope/exitScope
  so use strict inside blocks is properly scoped
- BytecodeCompiler: emit CREATE_LAST/NEXT/REDO + RETURN for non-local loop
  control instead of throwing compile-time error (enables last/next/redo
  across eval boundaries)
- RuntimeCode: construct subroutine name from code.packageName/subName when
  subroutineName is empty, fixing Not a CODE reference vs Undefined
  subroutine error messages

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <noreply@cognition.ai>
RuntimeGlob.dynamicSaveState/RestoreState now saves and restores
the actual globalVariables/globalArrays/globalHashes/globalCodeRefs
map entries in addition to calling dynamicSaveState on the slot
objects. This fixes local *glob = \"ref" where aliasGlobalVariable
replaces the map entry: on restore the original entry is put back
before its state is restored, preventing the shared static
dynamicStateStack from corrupting the aliased object.

Fixes uni/gv.t test 169 regression in interpreter mode.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <noreply@cognition.ai>
@fglock fglock force-pushed the fix-eval-interpreter-catchup branch from 380c654 to dd43cc7 Compare February 26, 2026 18:35
@fglock fglock merged commit 4bffe90 into master Feb 26, 2026
2 checks passed
@fglock fglock deleted the fix-eval-interpreter-catchup branch February 26, 2026 18:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant