=head1 TITLE
API for the Perl 6 debugger.
=head1 VERSION
1
=head2 CURRENT
Maintainer: David Storrs ([EMAIL PROTECTED])
Class: Internals
PDD Number: ?
Version: 1
Status: Developing
Last Modified: August 18, 2001
PDD Format: 1
Language: English
=head2 HISTORY
=over 4
=item Version 1
First version
=back
=head1 CHANGES
None. First version
=head1 ABSTRACT
This PDD describes the API for the Perl6 debugger.
=head1 DESCRIPTION
The following is a simple English-language description of the
functionality that we need. Implementation is described in a later
section. Descriptions are broken out by which major system will need
to provide the functionality (interpreter, optimizer, etc) and the
major systems are arranged in (more or less) the order in which the
code passes through them. Within each section, functionality is
arranged according to (hopefully) logical groupings.
=head2 Compiler
=head3 Generating Code on the Fly
=over 4
=item *
Compile and return the bytecode stream for a given expression. Used
for evals of user-specified code and edit/JIT compiling of source.
Should be able to compile in any specified context (e.g., scalar,
array, etc).
=item *
Show the bytecode stream emitted by a particular expression, either a
part of the source or user-specified. (This is basically just the
above method with a 'print' statement wrapped around it.)
=back # Closes 'Generating Code on the Fly' section
=head2 Optimizer
=head3 Generating and Comparing Optimizations
=over 4
=item *
Optimize a specified bytecode stream in place.
=item *
Return an optimized copy of the specified bytecode stream.
=item *
Show the diffs between two bytecode streams (presumably pre- and
post-optimization versions of the same stream).
=back # Closes 'Generating and Comparing Optimizations' section
=head2 Interpreter
=head3 Manipulating the Bytecode Stream
=over 4
=item *
Display the bytecodes for a particular region.
=item *
Fetch the next bytecode from the indicated stream.
// @@NOTE: from a design perspective, this is nicer than doing
"(*bcs)" everywhere, but we definitely don't want to pay a function
call overhead every time we fetch a bytecode. Can we rely on all
compilers to inline this properly?
=item *
Append/prepend all the bytecodes in 'source_stream' to 'dest_stream'. Used
for things like JIT compilation.
=back # Closes 'Manipulating the Bytecode Stream' section
=head3 Locating Various Points in the Code
=over 4
=item *
Locate the beginning of the next Perl expression in the specified
bytestream (which could be, but is not necessarily, the head of the
stream).
=item *
Locate the beginning of the next Perl source line in the specified
bytestream (which could be, but is not necessarily, the head of the
stream).
=item *
Search the specified bytestream for the specified bytecode. Return
the original bytecode stream, less everything up to the located
bytecode.
// @@NOTE: Should the return stream include the searched-for bytecode
or not? In general, I think this will be used to search for 'return'
bytecodes, in order to support the "step out of function"
functionality. In that case, it would be more convenient if the return
were B<not> there.
=item *
Search the specified bytecode stream for the specified line number.
This line may appear in the current module (the default), or in
another module, which must then be specified.
=item *
Search the specified bytecode stream for the beginning of the
specified subroutine.
=item *
Locates the beginning of the source line which called the function for
which the current stack frame was created.
=item *
Locate the next point, or all points, where a specified file is 'use'd or 'require'd
=back # Closes 'Locating Various Points in the Code' section.
=head3 Moving Through the Code
=over 4
=item *
Continue executing code, stop at end of code or first breakpoint found.
=item *
Continue up to a specified line, ignoring breakpoints on the way.
=item *
In the source which produced a specified bytecode stream, search
forwards for a specified pattern.
=item *
In the source which produced a specified bytecode stream, search
backwards for a specified pattern.
=item *
In the source which produced a specified bytecode stream, search
forwards for lines where expression is satisfied
=item *
In the source which produced a specified bytecode stream, search
backwards for lines where expression is satisfied
=back # Closes 'Moving through the Code'
=head3 Variable and Code Manipulation
=over 4
=item *
List all subroutines in a particular module (or all modules).
=item *
Locate the file containing the definition of the specified func/method.
=item *
Fetch an element from a specified (default: main::) symbol table.
=item *
Fetch all elements from a specified (default: main::) symbol table.
=item *
Set an element of a specified symbol table.
=item *
Retrieve an element from a specified scratchpad. Scratchpads must be
identifiable in a human-readable way.
=item *
Set an element in a specified scratchpad.
=item *
Fetch code or data from a closure.
=item *
Modify the code and/or data of a specified closure. Closures must be
identifiable in a human-readable way.
=item *
Retrieve the stack. (Probably we will want to limit this to
something like "Retrieve the previous/next stack frame" so that we
don't swamp ourselves; we can always iterate to get more frames.)
=item *
Designate a particular frame within the stack as the "current" frame.
This is mainly intended to allow us to evaluate variables from within
the context of the stack frame where they were created, modified, etc.
=item *
Specify what line in the current function should be executed next.
=item *
Erase all frames above the current one from the stack; restart
execution from the top of this frame. This is intended to support the
"Specify what line will run next" functionality, up to and including
the ability to jump out of the current function.
=item *
Get/set the string encoding of a specified string.
=item *
Get/set the normalization of a specified Unicode string.
=item *
Get the version number of the interpreter.
=back # Closes 'Variable and Code Manipulation'
=head2 Regex Engine
=over 4
=item *
Get contents of $1..$N.
=item *
Get contents of $`, $&, and $' (pre-match, matched string, post-match).
=item *
Get the matched portion of the string (i.e., how much of the string
has been used up).
=item *
Get unmatched portion of the string.
=item *
Get the complete state machine of the specified regex.
=item *
Get the next state in state machine.
=item *
Match the next character in the regex.
=back # Closes 'Regex Engine' section.
=head2 Garbage Collector
=over 4
=item *
Perform a GC pass now.
=item *
Set a lock forbidding the GC from running until the lock is released.
=item *
Release a previously set lock on the GC.
=item *
Display the current state of the GC lock.
=item *
Show which PMCs were visited on a particular GC pass.
=item *
Show whether a particular PMC was visited on a particular pass.
=item *
Show when memory was moved, which memory it was, and where it was
moved to.
=item *
Show when and which memory wass reclaimed on a particular pass.
=item *
Show how much memory was allocated by a particular line/statement/
sub/program, and how (i.e., in what structs).
=back # Closes 'Garbage Collector' section
=head2 Profiler
Until now, the Perl core has included a debugger but not a profiler.
Perl6 seems like an excellent time to add a profiler in core, parallel
to the debugger. Assuming that people agree with this, here are some
proposed hooks into the profiler.
=over 4
=item *
Show data type conversions throughout program.
=item *
Show how much CPU time was spent on the program.
=item *
Show how much CPU time was spent in each subroutine.
=item *
Show how much wall-clock time was spent on the program.
=item *
Show how much wall-clock time was spent in each sub.
=item *
Show how much system time was spent in each sub.
=item *
Show how much CPU time was spent on disk I/O, not including virtual memory.
=item *
Show how much CPU time was spent on virtual memory.
=item *
Show how much CPU time was spent on memory management.
=item *
Show minimum, average, and maximum amount of memory used after the
beginning of execution
=item *
Show minimum, average, and maximum number of filehandles
simultaneously open during execution.
=back # Closes 'Profiler' section
=head2 Internal to the Debugger
The Perl5 debugger contains four constructs that are almost but not
quite identical: breakpoints, watch expressions, actions, and what I am
calling "commands-around-prompt."
Breakpoints are attached to a particular line of source code and have
a condition associated with them (which, in many cases, is simply
'1'); when the given line of source is about to be executed, the
condition is evaluated. If it evaluates to a true value, then
execution pauses before the line is executed.
Watch expressions are placed on a particular variable to show when it
changes.
Actions are Perl expressions that are attached to a particular line of
source; the expression is evaluated just before the source line is
executed.
"Commands-around-prompt" come in four varieties: debugger commands
before, debugger commands after, Perl commands before, and Perl
command after the prompt. In each case, a command is run every time
the debugger prompt is displayed, either just before or just after (as
appropriate) the prompt itself appears.
=head3 Breakpoints
=over 4
=item *
Create a breakpoint.
=item *
Set a breakpoint at a particular point in the bytecode stream. The
user should be able to specify this point in as many ways as possible:
by line number, by sub name, by eval-block name, by closure name, by
module name (i.e., "whenever you go into this module, stop"). In
particular, it should be possible to set a breakpoint on a line in a
module other than the one that is currently being viewed (this has
been one of my longstanding pet peeves with the Perl debugger).
Breakpoints should be able to have a condition associated with them;
unless the condition evaluates to true, the breakpoint does not
activate. Setting a breakpoint must append it to the list of breakpoints.
=item *
Search the list for a particular breakpoint; if found, return it.
=item *
Display the list of breakpoints.
=item *
Remove one entry from the list of breakpoints.
=item *
Clear the list of breakpoints.
=back # Closes 'Breakpoints' section
=head3 Watch Expressions
=over 4
=item *
Create a watch expression.
=item *
Set a watch expression at a particular point in the bytecode stream. The
user should be able to specify this point in as many ways as possible:
by line number, by sub name, by eval-block name, by closure name, by
module name (i.e., "whenever you go into this module, stop"). In
particular, it should be possible to set a watch expression on a line in a
module other than the one that is currently being viewed (this has
been one of my longstanding pet peeves with the Perl debugger).
Watch expressions should be able to have a condition associated with them;
unless the condition evaluates to true, the watch expression does not
activate. Setting a watch expression must append it to the list of watch expressions.
=item *
Search the list for a particular watch expression; if found, return it.
=item *
Display the list of watch expressions.
=item *
Remove one entry from the list of watch expressions.
=item *
Clear the list of watch expressions.
=back # Closes 'Watch Expressions' section
=head3 Actions
=over 4
=item *
Create an action.
=item *
Set an action at a particular point in the code.. The user should be
able to specify this point in as many ways as possible: by line
number, by sub name, by eval-block name, by closure name, by module
name (i.e., "whenever you go into this module, stop"). In particular,
it should be possible to set an action on a line in a module other than
the one that is currently being viewed (this has been one of my
longstanding pet peeves with the Perl debugger). Actions should be
able to have a condition associated with them; unless the condition
evaluates to true, the action does not activate. Setting an action
must append it to the list of actions.
=item *
Search the list for a particular action; if found, return it.
=item *
Display the list of actions.
=item *
Remove one entry from the list of actions.
=item *
Clear the list of actions.
=back # Closes 'Actions' section
=head3 Commands-Around-Prompt
=over 4
=item *
Create a command-around-prompt.
=item *
Append a command-around-prompt to either the 'pre-prompt' or the
'post-prompt' list.
=item *
Evaluate all the commands-around-prompt in the 'pre-prompt' list.
=item *
Evaluate all the commands-around-prompt in the 'post-prompt' list.
=item *
Display the 'pre-prompt' or 'post-prompt' list of commands-around-prompt.
=item *
Remove one entry from a list of commands-around-prompt.
=item *
Clear the list of commands-around-prompt.
=back # Closes 'Commands-Around-Prompt' section
=head3 The Debugger's Command History
=over 4
=item *
Set and get the size of the command history.
=item *
Get Nth most recent item from the command history.
=item *
Get Nth most recent item that (does | does not) match PATTERN from the
command history.
=item *
Add an element to the command history.
=item *
Display complete command history.
=item *
Display an item from the command history.
=item *
Display last N items from the command history.
=back # Closes 'The Debugger's Command History'
=head3 Debugger Help
=over 4
=item *
Display a short summary of the debugger commands.
=item *
Display the full listing of the debugger commands.
=item *
Set the program that is used to show man pages.
=item *
Run 'man' on a specified topic.
=back # Closes 'Debugger Help'
=head3 Command Aliases
=over 4
=item *
Create an alias that sets one user-specified command to run another.
=item *
Delete an alias.
=item *
Show an alias.
=item *
Show all aliases.
=back # Closes 'Aliases'
=head3 Pretty-Printing
=over 4
=item *
Pretty-print the name and type (e.g. HASH) of the variable to which a
reference points.
=item *
Pretty-print the dump of an object variable (all methods, vars, etc).
=item *
Pretty-print the hierarchy of all classes currently loaded.
=item *
Pretty-print the inheritance tree for a particular class.
=item *
Pretty-print the inheritance tree for a particular object.
=item *
Pretty-print the methods callable via specified object or its ancestors.
=item *
Pretty-print a Unicode string in its current encoding/normalization.
(Useful to determine exactly how many glyphs are in it.)
=back # Closes 'Pretty-Printing'
=head3 Miscellaneous
=over 4
=item *
Quit debugging, exit the debugger.
=item *
Rerun the debugger on the current program; it should be possible to
specify whether the program should be reparsed or not.
=item *
Page a stream to the screen.
=item *
Grep a list of strings for elements that do or do not match a pattern.
=item *
Set or get the value of a debugger option.
=back # Closes 'Miscellaneous'
=head1 Implementation
Aye, here's the rub.