.cognition/skills/debugger/SKILL.md
# Perl Debugger Implementation Skill ## ⚠️⚠️⚠️ CRITICAL: NEVER USE `git stash` ⚠️⚠️⚠️ **DANGER: Changes are SILENTLY LOST when using git stash/stash pop!** - NEVER use `git stash` to temporarily revert changes - INSTEAD: Commit to a WIP branch or use `git diff > backup.patch` - This warning exists because completed work was lost during debugging ## Overview Continue implementing the Perl debugger (`-d` flag) for PerlOnJava. The debugger uses DEBUG opcodes injected at statement boundaries in
npx skillsauth add fglock/perlonjava .cognition/skills/debuggerInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
git stash ⚠️⚠️⚠️DANGER: Changes are SILENTLY LOST when using git stash/stash pop!
git stash to temporarily revert changesgit diff > backup.patchContinue implementing the Perl debugger (-d flag) for PerlOnJava. The debugger uses DEBUG opcodes injected at statement boundaries in the bytecode interpreter.
IMPORTANT: Never push directly to master. Always use feature branches and PRs.
IMPORTANT: Always commit or stash changes BEFORE switching branches. If git stash pop has conflicts, uncommitted changes may be lost.
git checkout -b feature/debugger-improvement
# ... make changes ...
git push origin feature/debugger-improvement
gh pr create --title "Debugger: description" --body "Details"
dev/design/perl_debugger.mdperldoc perldebug - User documentation for Perl debuggerperldoc perldebguts - Internal implementation details (key reference!)perldoc perldebtut - Tutorialperl5/lib/perl5db.pl - The standard Perl debugger (~10,000 lines)Branch: implement-perl-debugger
Opcodes.java-d flag in ArgumentParser.java sets debugMode=true, forces interpreterBytecodeCompiler emits DEBUG at statement boundaries when debugMode=trueBytecodeInterpreter handles DEBUG opcode, calls DebugHooks.debug()DebugState.java - global debug flags, breakpoints, source storageDebugHooks.java - command loop with n/s/c/q/l/b/B/L/h commandsErrorMessageUtil.extractSourceLines())l command shows source with ==> current line markeruse/no) correctly skipped via compileTimeOnly annotationskipDebug annotation| Command | Description |
|---------|-------------|
| n | Next (step over) |
| s | Step into (shows subroutine name, e.g., main::foo(file:line)) |
| r | Return (step out of current subroutine) |
| c [line] | Continue (optionally to line) |
| q | Quit |
| l [range] | List source (l 10-20 or l 15) |
| . | Show current line |
| b [line] | Set breakpoint |
| B [line] | Delete breakpoint (B * = all) |
| L | List breakpoints |
| T | Stack trace |
| p expr | Print expression (supports lexical variables) |
| x expr | Dump expression with Data::Dumper (supports lexical variables) |
| h | Help |
Tested side-by-side with perl -d:
| Feature | jperl | System perl | Status |
|---------|-------|-------------|--------|
| Start line | First runtime stmt | First runtime stmt | Match |
| n (next) | Works | Works | Match |
| s (step) | Works | Works | Match |
| c (continue) | Works | Works | Match |
| b (breakpoint) | Works, confirms | Works, silent | OK |
| L (list bp) | Simple list | Shows code + condition | Different |
| l (list) | Shows context around line | Shows current line only | Different |
| q (quit) | Works | Works | Match |
| Package prefix | Missing | Shows main:: | TODO |
| Prompt counter | DB<0> (0-indexed) | DB<1> (1-indexed) | TODO |
| Loading message | None | Shows perl5db.pl version | OK (intentional) |
main:: (or current package) to location display~~ DONEDB<1>) to match Perl~~ DONEl command: Perl shows current line, subsequent l shows next 10 lines| File | Purpose |
|------|---------|
| src/main/java/org/perlonjava/runtime/debugger/DebugState.java | Global flags, breakpoints, source storage |
| src/main/java/org/perlonjava/runtime/debugger/DebugHooks.java | Debug hook called by DEBUG opcode, command loop |
| src/main/java/org/perlonjava/backend/bytecode/Opcodes.java | DEBUG = 376 |
| src/main/java/org/perlonjava/backend/bytecode/BytecodeCompiler.java | Emits DEBUG opcodes, checks skipDebug |
| src/main/java/org/perlonjava/backend/bytecode/BytecodeInterpreter.java | Handles DEBUG opcode |
| src/main/java/org/perlonjava/app/cli/ArgumentParser.java | -d flag handling |
| src/main/java/org/perlonjava/frontend/parser/StatementParser.java | Marks use/no as compileTimeOnly |
| src/main/java/org/perlonjava/frontend/parser/SpecialBlockParser.java | Marks BEGIN infrastructure as skipDebug |
| src/main/java/org/perlonjava/runtime/runtimetypes/ErrorMessageUtil.java | extractSourceLines() for source display |
main::foo(file:line))@{"_<$filename"} magical array%{"_<$filename"} for breakpoint storage$DB::single, $DB::trace, $DB::signal synced from Java$DB::filename, $DB::line set by DEBUG opcode@DB::args support in caller()%DB::sub for subroutine location trackingp expr - print expression valuex expr - dump expression (Data::Dumper style)BEGIN { require 'perl5db.pl' } when -d usedDB::sub() routing for subroutine tracingALWAYS use make commands. NEVER use raw mvn/gradlew commands.
| Command | What it does |
|---------|--------------|
| make | Build + run all unit tests (use before committing) |
| make dev | Build only, skip tests (for quick iteration during debugging) |
make dev # Quick build after changes (no tests)
# Test basic stepping
echo 'n
n
q' | ./jperl -d /tmp/test.pl
# Test source listing
echo 'l
l 1-10
q' | ./jperl -d -e 'print 1; print 2; print 3;'
# Test breakpoints
echo 'b 3
c
q' | ./jperl -d /tmp/test.pl
# Compare with system perl
perl -d /tmp/test.pl
The debugger can be tested interactively - send commands and observe responses.
ErrorMessageUtil.extractSourceLines() rebuilds sourcecompileTimeOnly and skipDebug annotationsDebugHooks.executeCommand()handleXxx() methodtrue to resume execution, false to stay in command loophandleHelp() with new commandTo expose $DB::single etc. to Perl code:
DebugState fieldsGlobalVariable.java for examples of special variablesAlready working via DebugState.stepOverDepth:
n sets stepOverDepth = callDepthcallDepth > stepOverDepthDebugHooks.enterSubroutine()/exitSubroutine() on sub entry/exitcompileTimeOnly - skips entire statement compilation (for use/no results)skipDebug - skips only DEBUG opcode emission (for infrastructure nodes)DebugState.sourceLines is populatedcallDepth tracking is correctskipDebug on internal nodesdevelopment
# PerlOnJava Debugging Skills and Architecture Knowledge This document captures key knowledge about PerlOnJava internals learned during debugging sessions. ## Variable Storage and Scoping ### Three Types of Variable Declarations 1. **`my` variables** - Lexical scope - Stored in JVM local variable slots during normal execution - When captured by closures: stored as closure fields or in GlobalVariable with IDs - Symbol table entry: `decl = "my"`, has `index` (JVM slot number) 2. **`o
development
# PerlOnJava Interpreter Developer Guide - name all test files /tmp/test.pl ## Quick Reference **Performance:** 46.84M ops/sec (1.75x slower than compiler ✓) **Opcodes:** 0-157 (contiguous) for JVM tableswitch optimization **Runtime:** 100% API compatibility with compiler (zero duplication) ### Testing Modes **JPERL_EVAL_USE_INTERPRETER=1** - Forces all eval STRING to use the interpreter - Used for testing interpreter implementation of operators in eval context - Compiler still used for mai
development
# Profile PerlOnJava ## ⚠️⚠️⚠️ CRITICAL: NEVER USE `git stash` ⚠️⚠️⚠️ **DANGER: Changes are SILENTLY LOST when using git stash/stash pop!** - NEVER use `git stash` to temporarily revert changes - INSTEAD: Commit to a WIP branch or use `git diff > backup.patch` - This warning exists because completed work was lost during debugging Profile and optimize PerlOnJava runtime performance using Java Flight Recorder. ## Git Workflow **IMPORTANT: Never push directly to master. Always use feature bra
development
# Port CPAN Module to PerlOnJava ## ⚠️⚠️⚠️ CRITICAL: NEVER USE `git stash` ⚠️⚠️⚠️ **DANGER: Changes are SILENTLY LOST when using git stash/stash pop!** - NEVER use `git stash` to temporarily revert changes - INSTEAD: Commit to a WIP branch or use `git diff > backup.patch` - This warning exists because completed work was lost during debugging This skill guides you through porting a CPAN module with XS/C components to PerlOnJava using Java implementations. ## When to Use This Skill - User as