Skip to content

Interpreter: fix eval STRING strictures, glob assign, and open my $fh#229

Merged
fglock merged 2 commits intomasterfrom
fix-interpreter-strictures
Feb 24, 2026
Merged

Interpreter: fix eval STRING strictures, glob assign, and open my $fh#229
fglock merged 2 commits intomasterfrom
fix-interpreter-strictures

Conversation

@fglock
Copy link
Owner

@fglock fglock commented Feb 24, 2026

Summary

Fixes interpreter feature gaps revealed under JPERL_EVAL_USE_INTERPRETER=1.

Test Results

Test Before After JVM baseline
op/signatures.t 597/597 597/597 597/597
op/require_gh20577.t 2/9 7/9 7/9
comp/use.t 34/87 40/87 40/87

All results now match the JVM baseline. Remaining failures are pre-existing in both modes.

Changes

Strict refs/vars for symbolic dereferences

New opcodes DEREF_SCALAR_STRICT (335) and DEREF_SCALAR_NONSTRICT (336) mirror the JVM path (scalarDeref() / scalarDerefNonStrict(pkg)) for ${block} and $$var reads and assignments. Added shouldBlockGlobalUnderStrictVars() check in compileVariableReference() for bare $identifier global access under use strict 'vars'. Fixes comp/use.t tests 21, 25–31.

Symbolic typeglob assignment

New opcode LOAD_GLOB_DYNAMIC (334) loads a glob by its runtime name, enabling *{"pkg::name"} = \&sub inside eval STRING. Required for FatPacked-style @INC hooks that install INC methods via glob assignment.

open my $fh lexical filehandle propagation

RuntimeArray.push() copies scalars via new RuntimeScalar(this), so IOOperator.open()'s in-place fileHandle.set(glob) was mutating the copy, losing the filehandle in the original lexical register. Fix: after emitting OPEN, retrieve args[0] from the array and SET_SCALAR it back into the $fh register. Fixes op/require_gh20577.t tests 4, 5, 8, 9.

1. Strict refs for ${block} scalar deref (BytecodeCompiler + CompileAssignment):
   - Add DEREF_SCALAR_STRICT (335) and DEREF_SCALAR_NONSTRICT (336) opcodes
   - BytecodeCompiler: emit DEREF_SCALAR_STRICT when strict refs enabled,
     DEREF_SCALAR_NONSTRICT (with pkg) when disabled — matches JVM path in
     EmitVariable.java case "$"
   - CompileAssignment: same for ${block}=value and $$var=value assignment
   - SlowOpcodeHandler: implement via scalarDeref()/scalarDerefNonStrict(pkg)

2. Strict vars for $identifier global access (BytecodeCompiler):
   - Add shouldBlockGlobalUnderStrictVars() check in compileVariableReference()
     for the global variable load path — was previously unchecked

3. Typeglob symbolic assignment *{"name"} = sub (CompileAssignment):
   - Add LOAD_GLOB_DYNAMIC (334) opcode for runtime glob-by-name loading
   - Handle BlockNode operand for * assignment, matching no-strict-refs symref
   - Fixes op/require_gh20577.t glob assign in eval STRING

4. DEREF_GLOB (333) + LOAD_GLOB_DYNAMIC disassembler support (InterpretedCode)

Fixes comp/use.t: reduces interpreter-specific failures from -6 to -1 (test 23
is a pre-existing issue in both JVM and interpreter paths).
Fixes op/require_gh20577.t: glob assign works; @inc hook dispatch remains.
op/signatures.t baseline: 597/597.
IOOperator.open() calls fileHandle.set(glob) on the first argument,
but RuntimeArray.push() copies the scalar via new RuntimeScalar(this),
so the mutation was lost on the original lexical register.

Fix in CompileOperator.java: after emitting OPEN, retrieve element 0
from the args array (which IOOperator.open() mutated) and SET_SCALAR
it back into the fh lexical register.

Fixes op/require_gh20577.t: now 7/9 (matching JVM baseline).
Tests 6/7 remain pre-existing failures in both JVM and interpreter.
op/signatures.t baseline: 597/597.
@fglock fglock merged commit e51c462 into master Feb 24, 2026
2 checks passed
@fglock fglock deleted the fix-interpreter-strictures branch February 24, 2026 13:43
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