Skip to content

Interpreter improvements: Additional fixes and tie operator support#216

Merged
fglock merged 2 commits into
masterfrom
fix/test-regressions
Feb 20, 2026
Merged

Interpreter improvements: Additional fixes and tie operator support#216
fglock merged 2 commits into
masterfrom
fix/test-regressions

Conversation

@fglock
Copy link
Copy Markdown
Owner

@fglock fglock commented Feb 20, 2026

Summary

This PR continues the interpreter improvements with additional bug fixes and implements tie/untie/tied operator support. Following the merge of PR #215, this PR addresses remaining test failures and achieves 100% pass rate on multiple test files.

Key Achievements

op/assignwarn.t: 100% pass rate (116/116) with interpreter - matches compiler
re/regexp.t: 80.8% pass rate (1786/2210) - maintained from previous PR
op/decl-refs.t: 66.7% pass rate (272/408) - 2 tests better than compiler
Implemented tie/untie/tied operators - full Perl tie semantics support

Changes

1. Scalar Reference Dereference Fixes (#ebc92fa, #7f14e66)

Problem: The ${\...} syntax (inline scalar reference dereference) wasn't working in eval STRING with the interpreter.

Solution:

  • Implemented proper DEREF opcode behavior by calling scalarDeref()
  • Fixed LOAD_SYMBOLIC_SCALAR to check if block result is a REFERENCE type
  • Added type checking to handle RuntimeList in DEREF (prevents ClassCastException)

Impact:

  • re/regexp.t: Fixed test #1459 using ${\(defined($1)?1:0)}
  • op/decl-refs.t: Fixed crash with declared reference lists like my (\$f, $g)
  • Interpreter now matches or exceeds compiler on both tests

2. Error Message Cleanup (#ad5807d)

Problem: Interpreter was adding "Interpreter error in (eval N) line X (pc=Y):" prefix to exceptions from eval'd code, breaking tests that check $@ error messages.

Solution:

  • Detect when code is running inside eval STRING context (sourceName starts with "(eval ")
  • Pass exceptions through without wrapping when in eval context
  • Preserves clean error messages in $@ that match compiler behavior

Impact:

  • re/regexp.t: +47 tests (1738 → 1785 passing)

3. matchRegex Fix (#c7920c1)

Problem: When using $string =~ m/pattern/ with interpreter, it returned the regex object instead of performing the match.

Solution:

  • Fixed matchRegex handler in CompileOperator.java to check if string is provided via =~ binding
  • If string provided (args.elements.size() > 2), emit MATCH_REGEX opcode to perform the match
  • If no string, return regex object (for qr/pattern/ cases)

Impact:

  • re/regexp.t: +1391 tests (395 → 1786 passing)

4. Bitwise AND Warning Fix (#8aed892)

Problem: Interpreter's &= operator wasn't warning about uninitialized values.

Solution:

  • Changed executeBitwiseAndAssign() to call BitwiseOperators.bitwiseAnd() instead of bitwiseAndBinary()
  • bitwiseAnd() includes uninitialized value warning check (lines 32-39)
  • bitwiseAndBinary() skips the check for performance

Impact:

  • op/assignwarn.t: +2 tests (75 → 77 passing)

5. Tie/Untie/Tied Operators (#571d939)

Problem: Tie operators weren't implemented in the interpreter, causing 39 test failures.

Solution:

  • Added TIE, UNTIE, TIED opcodes (238, 239, 240)
  • Updated LASTOP to 240
  • Added handlers in CompileOperator.java
  • Added execution logic in BytecodeInterpreter.java that calls TieOperators

Features:

  • tie($var, $classname, @args) - Bind variable to package class
  • untie($var) - Break binding between variable and class
  • tied($var) - Return object underlying tied variable

Impact:

  • op/assignwarn.t: +39 tests (77 → 116 passing, 100%)

Testing

  • ✅ All unit tests pass (make test)
  • op/assignwarn.t: 116/116 (100.0%) with interpreter (was 75/116)
  • re/regexp.t: 1786/2210 (80.8%) with interpreter (maintained)
  • op/decl-refs.t: 272/408 (66.7%) with interpreter vs 270/408 with compiler (+2 tests better!)
  • ✅ No regressions in existing tests

Detailed Impact

op/assignwarn.t - Progressive Improvement

Initial state:           75/116 (64.7%)
After &= warning fix:    77/116 (66.4%)
After tie support:      116/116 (100.0%) ✓

re/regexp.t - Maintained Excellence

After matchRegex fix:   1786/2210 (80.8%)
After error cleanup:    1786/2210 (80.8%)
After DEREF fixes:      1786/2210 (80.8%) ✓

op/decl-refs.t - Surpassing Compiler

Compiler:               270/408 (66.2%)
After DEREF fix:        272/408 (66.7%) +2 tests better! ✓

Technical Notes

Opcode Additions

The tie operators were added as manually-assigned opcodes (238-240) before the GENERATED_OPCODES region, following the project's convention. LASTOP was updated to 240.

Pattern Consistency

The implementation follows the established pattern of:

  1. Compiling arguments as a list
  2. Passing to runtime operator class with context
  3. Handling result registration

This ensures consistency with other operators and maintains the separation between compilation and execution logic.

🤖 Generated with Claude Code

fglock and others added 2 commits February 20, 2026 11:38
The interpreter was calling BitwiseOperators.bitwiseAndBinary() which skips
the uninitialized value warning check. Changed to call bitwiseAnd() which
includes the proper warning for using undefined values in bitwise AND operations.

This matches the JVM compiler behavior and aligns with Perl semantics where
bitwise AND (&) should warn about uninitialized values, while bitwise OR (|)
and XOR (^) should not.

Impact on perl5_t/t/op/assignwarn.t with JPERL_EVAL_USE_INTERPRETER=1:
- Before: 75/116 passing (64.7%)
- After: 77/116 passing (66.4%)
- Fixed: +2 tests (tests 28 and 58 for $x &= 1 and $x &= 'x' warnings)

Remaining 39 failures are due to 'tie' operator not being implemented yet.

Compiler still passes: 116/116 (100.0%)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Added support for Perl's tie(), untie(), and tied() built-in functions in
the bytecode interpreter. These operators allow binding variables to package
classes that provide custom implementations.

Implementation:
1. Added TIE, UNTIE, TIED opcodes (238, 239, 240) to Opcodes.java
2. Updated LASTOP to 240
3. Added handlers in CompileOperator.java for "tie", "untie", "tied"
4. Added execution logic in BytecodeInterpreter.java that calls TieOperators

The implementation follows the same pattern as other operators that call
runtime classes, compiling arguments as a list and passing them to the
appropriate TieOperators method along with the calling context.

Impact on perl5_t/t/op/assignwarn.t with JPERL_EVAL_USE_INTERPRETER=1:
- Before: 77/116 passing (66.4%) - tie not implemented, 39 tests failing
- After: 116/116 passing (100.0%) ✓ All tests pass!
- Fixed: +39 tests

Compiler still passes: 116/116 (100.0%) ✓

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@fglock fglock merged commit 181ed7f into master Feb 20, 2026
2 checks passed
@fglock fglock deleted the fix/test-regressions branch February 20, 2026 10:53
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