The O
module has many interesting
Modi Operandi beyond feeding the exasperatingly experimental code
generators. By providing relatively painless access to the Perl
compiler's output, this module makes it easy to build other tools that
need to know everything about a Perl program.
The B::Lint
module is named after
lint (1), the C program verifier. It
inspects programs for questionable constructs that often trip up
beginners but don't normally trigger warnings. Call the module
directly:
% perl -MO=Lint,all myprog
Only a few checks are currently defined, such as using an array
in an implicit scalar context, relying on default variables, and
accessing another package's (nominally private) identifiers that start
with _
. See B::Lint (3)
for details.
The B::Xref
module generates
cross-reference listings of the declaration and use of all variables
(both global and lexically scoped), subroutines, and formats in a
program, broken down by file and subroutine. Call the module this
way:
% perl -MO=Xref myprog > myprof.pxref
For instance, here's a partial report:
Subroutine parse_argv Package (lexical) $on i113, 114 $opt i113, 114 %getopt_cfg i107, 113 @cfg_args i112, 114, 116, 116 Package Getopt::Long $ignorecase 101 &GetOptions &124 Package main $Options 123, 124, 141, 150, 165, 169 %$Options 141, 150, 165, 169 &check_read &167 @ARGV 121, 157, 157, 162, 166, 166
This shows that the parse_argv
subroutine had
four lexical variables of its own; it also accessed global identifiers
from both the main
package and from
Getopt::Long
. The numbers are the lines where that
item was used: a leading i
indicates that the item
was first introduced at the following line number, and a leading
&
means a subroutine was called there.
Dereferences are listed separately, which is why both
$Options
and %$Options
are
shown.
The B::Deparse
is a pretty printer
that can demystify Perl code and help you understand what
transformations the optimizer has taken with your code. For example,
this shows what defaults Perl uses for various constructs:
% perl -MO=Deparse -ne 'for (1 .. 10) { print if -t }'
LINE: while (defined($_ = <ARGV>)) {
foreach $_ (1 .. 10) {
print $_ if -t STDIN;
}
}
The -p
switch adds parentheses so you can
see Perl's idea of precedence:
% perl -MO=Deparse,-p -e 'print $a ** 3 + sqrt(2) / 10 ** -2 ** $c'
print((($a ** 3) + (1.4142135623731 / (10 ** (-(2 ** $c))))));
You can use -q
to see what primitives
interpolated strings are compiled into:
% perl -MO=Deparse,-q -e '"A $name and some @ARGV
"'
'A ' . $name . ' and some ' . join($", @ARGV) . "
";
And this shows how Perl really compiles a three-part
for
loop into a while
loop:
% perl -MO=Deparse -e 'for ($i=0;$i<10;$i++) { $x++ }'
$i = 0;
while ($i < 10) {
++$x;
}
continue {
++$i
}
You could even call B::Deparse
on a
Perl bytecode file produced by perlcc -b, and
have it decompile that binary file for you. Serialized Perl opcodes
may be a tad tough to read, but strong encryption they are not.