feat: Add interpreter operators (getppid, package VERSION, process control, math)#217
Merged
Conversation
Add compilation support for the getppid() operator in the bytecode interpreter. The opcode (135) and execution handler were already implemented in SlowOpcodeHandler.executeGetppid(), this change adds the compiler-side code generation in CompileOperator.java. Format: GETPPID rd Effect: rd = parent process ID Note: Test 143 in op/lex_assign.t still fails due to an unrelated issue with tied variable assignments not calling STORE in the interpreter. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add version variable initialization when package declarations include a version number. This matches the compiler behavior where $Package::VERSION is automatically set when declaring 'package Foo 1.23;'. Implementation: - Check for package version in symbol table during package operator compilation - Set $Package::VERSION using GlobalVariable.getGlobalVariable() - Mirrors EmitOperator.java:761-766 from compiler Test impact: - op/packagev.t: Both compiler and interpreter remain at 218/307 passing - The remaining 89 failures are due to other issues: - Version validation/syntax errors not being detected - version->new() parsing issues - eval return value handling These are shared issues affecting both backends equally. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… getpriority, atan2) Add compiler support for process control and math operators in the interpreter: - getpgrp($pid) - get process group - setpgrp($pid, $pgrp) - set process group - getpriority($which, $who) - get process priority - atan2($y, $x) - arctangent of y/x Implementation: - Opcodes already existed (GETPGRP=136, SETPGRP=137, GETPRIORITY=138, ATAN2=241) - Execution handlers already in SlowOpcodeHandler and ScalarBinaryOpcodeHandler - Added compilation code generation in CompileOperator.java Test impact (with JPERL_EVAL_USE_INTERPRETER=1): - op/lex_assign.t: 320/353 → 323/353 (+3 tests) - Fixes tests that use these operators inside eval blocks Remaining unsupported operators in eval blocks: - qx, each, caller, fileno, getc, chmod, umask, unlink, utime - rename, link, readlink, system, localtime, gmtime, pack, vec, crypt Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix parser error "Increment/decrement operator requires operand" when
incrementing array or hash elements inside eval blocks with interpreter.
Problem:
- `$_[0]++` or `$x[0]++` failed in eval with JPERL_EVAL_USE_INTERPRETER=1
- Error: "Increment/decrement operator requires operand"
- CompileOperator only handled IdentifierNode and simple OperatorNode
Solution:
- Add BinaryOperatorNode handling for array/hash element access
- Compile the lvalue (element access) first
- Apply increment/decrement opcodes to the result
Test fixes (JPERL_EVAL_USE_INTERPRETER=1):
- op/attrs.t: 43/126 → 44/126 (+1 test)
- Fixes test 2: eval '$anon1 = sub : method { $_[0]++ }'
Implementation:
- Handles $x[0]++, $_[0]++, $x{key}++, etc.
- Supports both prefix (++$x[0]) and postfix ($x[0]++)
- Uses existing POST_AUTOINCREMENT/POST_AUTODECREMENT opcodes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Simplify the increment/decrement operator implementation using a
recursive approach while keeping the fast path for lexical variables.
Before: 145 lines with special cases for each node type
After: 45 lines with optimized path + general recursive path
Benefits:
- Reduces CompileOperator.java from 2752 to 2651 lines (-101 lines)
- Handles ALL lvalue types: $x++, $_[0]++, $x{key}++, $obj->{field}++
- Simpler to understand and maintain
- Reduces JVM bytecode size (helps keep method under 8K limit)
Implementation:
- Fast path: simple lexical variable (IdentifierNode)
- General: node.operand.accept() for ANY lvalue
- Apply increment/decrement opcodes to result
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Multiple interpreter improvements to reduce feature gaps when eval blocks use the interpreter (
JPERL_EVAL_USE_INTERPRETER=1):Changes
1. getppid Operator (CompileOperator.java)
GETPPID rd2. Package VERSION Setting (CompileOperator.java)
$Package::VERSIONusing GlobalVariable3. Process Control Operators (CompileOperator.java)
4. Math Operators (CompileOperator.java)
Test Impact
With JPERL_EVAL_USE_INTERPRETER=1 (eval blocks use interpreter):
op/lex_assign.t: 320/353 → 323/353 (+3 tests, 91.5% pass rate)
op/packagev.t: 218/307 (71.0% - same for both backends)
Pure interpreter mode (JPERL_INTERPRETER=1):
op/lex_assign.t: 346/353 (98.0% - same as compiler)
op/packagev.t: 218/307 (71.0% - same as compiler)
Architecture
All fixes follow the compiler pattern:
Remaining Work
For full JPERL_EVAL_USE_INTERPRETER=1 support in op/lex_assign.t, still need:
Missing operators in eval blocks (18 more):
These would improve the pass rate from 91.5% to ~98%.
Related
Part of ongoing work to improve interpreter feature parity when eval blocks are executed in interpreter mode.
🤖 Generated with Claude Code