Skip to content

Interpreter Phase 4: Eval Block Support with die/return/ListNode#187

Merged
fglock merged 3 commits intomasterfrom
feature/interpreter-phase1-core
Feb 12, 2026
Merged

Interpreter Phase 4: Eval Block Support with die/return/ListNode#187
fglock merged 3 commits intomasterfrom
feature/interpreter-phase1-core

Conversation

@fglock
Copy link
Copy Markdown
Owner

@fglock fglock commented Feb 12, 2026

Summary

Implement complete eval block support for the interpreter, including exception handling, die/return operators, and high-performance ListNode operations. This enables the interpreter to handle real-world Perl eval blocks with proper error handling.

Changes

1. Eval Block Infrastructure (b3fa767)

  • New Opcodes:
    • EVAL_TRY (83): Set up exception handler, clear $@
    • EVAL_CATCH (84): Handle exceptions, store undef
    • EVAL_END (85): Clear $@ on success
  • TokenIndex Tracking: Map bytecode PC to AST tokenIndex for error reporting
  • Exception Handling: Eval stack to track catch handlers

2. Return and Die Operators (95ec9ae)

  • return: Emits RETURN opcode with expression or undef
  • die: Emits DIE opcode, calls WarnDie.die() throwing PerlDieException
  • warn: Emits WARN opcode for completeness
  • Both track tokenIndex for accurate error messages

3. High-Performance ListNode Support (591cdac)

  • New Opcode:
    • CREATE_LIST (86): Optimized list creation
      • Fast path for empty lists (count=0)
      • Optimized path for single element (count=1)
      • Efficient bulk add for multiple elements (count>1)
  • Array Variables: Support for @_ (register 1)
  • Subroutine Calls: Support for -> operator (eval blocks)
  • Auto-conversion: RuntimeList to RuntimeArray in CALL_SUB

Performance Optimizations

  1. ListNode Fast Paths: Specialized code for common cases
  2. Direct Register Operations: No intermediate object allocations
  3. Minimal Boxing: Reduce object creation overhead
  4. Inline Evaluation: List elements evaluated directly into registers

Architecture

Eval Block Flow:

  1. EVAL_TRY pushes catch handler onto stack, clears $@
  2. Block executes normally
  3. On exception: Catch handler pops stack, sets $@, returns empty list
  4. On success: EVAL_END clears $@, pops handler

List Operations:

  • ListNode creates RuntimeList with all elements
  • CALL_SUB auto-converts RuntimeList to RuntimeArray
  • Eval exceptions return empty list (Perl semantics)

Test Results

All InterpreterTest cases pass:

✅ Test 1: my $x = 5 - OK
✅ Test 2: my $x = 10 + 20 - OK
✅ Test 3: eval { die 'error' } - OK (sets $@, returns undef)
✅ Test 4: eval { return 42 } - OK (clears $@, returns value)

Standard Perl test suite also passes:

use Test::More tests => 4;

my $result1 = eval { die "test error" };
is($result1, undef, "eval block returns undef on die");
like($@, qr/test error/, "eval block sets \$@ on die");

my $result2 = eval { return 42 };
is($result2, 42, "eval block returns value on return");
is($@, '', "eval block clears \$@ on success");

Documentation Updates

  • Updated BYTECODE_DOCUMENTATION.md with opcodes 83-86
  • Added eval block architecture documentation
  • Documented performance optimizations

Related Issues

Closes requirements for:

  • Eval block exception handling
  • die/return operator support
  • ListNode operations
  • Dynamic code evaluation

Next Steps

With eval blocks working, the interpreter is ready for:

  1. Array operations (global arrays beyond @_)
  2. Hash operations (%, global hashes)
  3. More builtin operators
  4. Control flow (last/next/redo beyond eval)

🤖 Generated with Claude Code (claude.ai/code)

fglock and others added 3 commits February 12, 2026 10:43
Implement opcodes and infrastructure for eval blocks with exception
handling. This lays the groundwork for full eval block support including
die/return handling and $@ error variable management.

Changes:
- Add EVAL_TRY (83), EVAL_CATCH (84), EVAL_END (85) opcodes
- Add tokenIndex tracking (pcToTokenIndex map) for error reporting
- Implement eval block bytecode emission in BytecodeCompiler
- Add exception handling stack in BytecodeInterpreter
- Update InterpretedCode constructor to accept tokenIndex map
- Add disassembler support for eval opcodes
- Document eval opcodes in BYTECODE_DOCUMENTATION.md

Architecture:
- EVAL_TRY pushes catch handler PC onto eval stack, clears $@
- Block bytecode executes normally
- EVAL_END pops catch handler, clears $@ on success
- If exception: outer catch checks eval stack, calls WarnDie.catchEval(),
  jumps to catch PC, executes EVAL_CATCH to store undef
- Matches compiler's useTryCatch implementation semantics

Note: Full testing requires die/return operator support which will be
added in follow-up commits. Current implementation provides the
infrastructure and opcode framework.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add support for `return` and `die` operators in the bytecode compiler
and interpreter. These are essential for eval block functionality.

Changes:
- Add `return` operator handler in BytecodeCompiler.visit(OperatorNode)
- Add `die` operator handler in BytecodeCompiler.visit(OperatorNode)
- Implement DIE (73) and WARN (74) opcodes in BytecodeInterpreter
- Add disassembler support for DIE and WARN opcodes
- Update InterpreterTest with eval block tests (die/return)

Implementation:
- return: Emits RETURN opcode with expression or undef
- die: Emits DIE opcode with message, calls WarnDie.die()
- Both track tokenIndex for error reporting
- DIE throws PerlDieException which is caught by eval blocks

Note: Full testing blocked by ListNode support (die/return operands
are wrapped in ListNode by parser). Will be implemented in follow-up.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add complete ListNode implementation enabling eval blocks, subroutine
calls, and list operations in the interpreter. This unblocks die/return
operators and enables full eval block functionality.

New Opcode:
- CREATE_LIST (86): Highly optimized list creation
  * count=0: Empty list (fast path)
  * count=1: Single element (optimized path)
  * count>1: Pre-allocated bulk add

Changes:
- Implement ListNode visitor with performance optimizations
- Add "@" operator support for array variables (@_)
- Add "->" operator support for subroutine application
- Enhance CALL_SUB to handle RuntimeList arguments
- Simplify eval exception handling (return empty list on die)
- Remove complex catch block bytecode execution
- Add CREATE_LIST disassembler support

Performance Optimizations:
1. Fast paths for empty and single-element lists
2. Direct register-to-list population (no intermediate objects)
3. Minimal boxing/unboxing
4. Inline evaluation of list elements

Architecture:
- ListNode creates RuntimeList with all elements
- CALL_SUB converts RuntimeList to RuntimeArray automatically
- Eval exceptions caught and return empty list (Perl semantics)
- $@ set by WarnDie.catchEval()

Test Results:
✅ eval { die 'error' } - Works correctly
✅ eval { return 42 } - Works correctly
✅ All InterpreterTest cases pass

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@fglock fglock merged commit ef743b5 into master Feb 12, 2026
2 checks passed
@fglock fglock deleted the feature/interpreter-phase1-core branch February 12, 2026 10:22
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