Debugging

Debug Perl 6 programs

There are at least two useful debuggers available for Rakudo, the Perl 6 compiler:

A command-line debugger frontend for Rakudo. This module installs the perl6-debug-m command-line utility, and is bundled with the Rakudo Star distributions. Please check its repository for instructions and a tutorial.

Simple tracing and debugging support for Perl 6 grammars.

Please see the documentation for these programs for further information.

Historically others have existed and others are likely to be written in the future, check the Perl 6 Modules website.

There are also environment variables that can be set to aid debugging various aspects of your program. See Perl 6 Environment Variables and Running rakudo from the command line for more information.

trace pragma

The trace pragma causes the program to print out step-by-step which lines get executed:

use trace;
sub foo { say "hi" }
foo;
# OUTPUT: 
# 2 (/tmp/script.p6 line 2) 
# sub foo { say "hi" } 
# 5 (/tmp/script.p6 line 3) 
# foo 
# 3 (/tmp/script.p6 line 2) 
# say "hi" 
# hi 

Dumper function dd

Note: this routine is a Rakudo-specific debugging feature and not standard Perl 6.

The Tiny Data Dumper: This function takes the input list of variables and notes them (on $*ERR) in an easy to read format, along with the name of the variable. Thus,

my $a = 42;
my %hash = "a" => 1"b" => 2"c" => 3;
 
dd %hash$a;
#`( OUTPUT:
    Hash %hash = {:a(1), :b(2), :c(3)}
    Int $a = 42
)

to the standard error stream.

Please note that dd will ignore named parameters. You can use a Capture or Array to force it to dump everything passed to it.

dd \((:a(1), :b(2)), :c(3));
dd [(:a(1), :b(2)), :c(3)];

If you don't specify any parameters at all, it will just print the type and name of the current subroutine / method to the standard error stream:

sub a { dd }a   # OUTPUT: «sub a()␤» 

This can be handy as a cheap trace function.

Using backtraces

The Backtrace class gets the current call stack, and can return it as a string:

my $trace = Backtrace.new;
sub inner { say ~Backtrace.new}
sub outer { inner}
outer;
 
# OUTPUT: 
# perl6 /tmp/script.p6 
#   in sub inner at /tmp/script.p6 line 2 
#   in sub outer at /tmp/script.p6 line 3 
#   in block <unit> at /tmp/script.p6 line 4