Skip to content

feat: Add interpreter operators (getppid, package VERSION, process control, math)#217

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

feat: Add interpreter operators (getppid, package VERSION, process control, math)#217
fglock merged 5 commits into
masterfrom
fix/test-regressions

Conversation

@fglock
Copy link
Copy Markdown
Owner

@fglock fglock commented Feb 20, 2026

Summary

Multiple interpreter improvements to reduce feature gaps when eval blocks use the interpreter (JPERL_EVAL_USE_INTERPRETER=1):

  1. getppid operator - Get parent process ID
  2. Package VERSION - Automatically set $Package::VERSION for versioned packages
  3. Process control operators - getpgrp, setpgrp, getpriority
  4. Math operators - atan2

Changes

1. getppid Operator (CompileOperator.java)

./jperl --interpreter -E 'say getppid'  # Works
  • Emits GETPPID opcode (135)
  • Format: GETPPID rd

2. Package VERSION Setting (CompileOperator.java)

package Foo 1.23; say $Foo::VERSION;  # Prints 1.23
  • Check for package version in symbol table
  • Set $Package::VERSION using GlobalVariable
  • Mirrors compiler behavior

3. Process Control Operators (CompileOperator.java)

getpgrp($pid)           # Get process group  
setpgrp($pid, $pgrp)    # Set process group
getpriority($which, $who)  # Get process priority
  • Opcodes: GETPGRP=136, SETPGRP=137, GETPRIORITY=138
  • Handlers already in SlowOpcodeHandler

4. Math Operators (CompileOperator.java)

atan2($y, $x)  # Arctangent of y/x
  • Opcode: ATAN2=241
  • Handler already in ScalarBinaryOpcodeHandler

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)

  • Fixes tests 57, 144, 145, 146
  • Remaining 30 failures need more operator implementations

op/packagev.t: 218/307 (71.0% - same for both backends)

  • $VERSION now set correctly in interpreter

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:

  • Direct opcode emission for operators
  • GlobalVariable for package VERSION
  • Consistent behavior between interpreter and compiler modes

Remaining Work

For full JPERL_EVAL_USE_INTERPRETER=1 support in op/lex_assign.t, still need:

Missing operators in eval blocks (18 more):

  • File ops: chmod, umask, unlink, utime, rename, link, readlink
  • I/O: qx (backticks), getc, fileno
  • System: system, caller
  • Hash: each
  • String/data: pack, vec, crypt
  • Time: localtime, gmtime

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

fglock and others added 2 commits February 20, 2026 14:37
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>
@fglock fglock changed the title feat: Add interpreter support for getppid operator feat: Add interpreter improvements (getppid, package VERSION) Feb 20, 2026
… 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>
@fglock fglock changed the title feat: Add interpreter improvements (getppid, package VERSION) feat: Add interpreter operators (getppid, package VERSION, process control, math) Feb 20, 2026
fglock and others added 2 commits February 20, 2026 15:25
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>
@fglock fglock merged commit d3e22c6 into master Feb 20, 2026
2 checks passed
@fglock fglock deleted the fix/test-regressions branch February 20, 2026 14:49
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