http://qs1969.pair.com?node_id=11122212

aartist has asked for the wisdom of the Perl Monks concerning the following question:

Hi
How I can visualize a Perl program? For example I like to see all the perl variables and the line-numbers or subroutines where it is used. I understand that variables can be created on the fly with eval and $$ and even another name-space but let's ignore for them for now, as my current code base doesn't have that.

Thanks.

Replies are listed 'Best First'.
Re: Visualize Perl Program
by davido (Cardinal) on Sep 25, 2020 at 19:46 UTC

    B::Xref (lanx beat me to mentioning it; I was fiddling with a POC).

    #!/usr/bin/env perl my $fb = fizzbuzz(); print "$_\n" for @$fb; sub fizzbuzz { my ($n, $m) = (1, 100); my @out; for my $num ($n .. $m) { my $line = ''; $line .= 'fizz' if $num % 3 == 0; $line .= 'buzz' if $num % 5 == 0; push @out, $line || $num; } return \@out; }

    When you run this with B::Xref you get the following:

    perl -MO=Xref mytest.pl File mytest.pl Subroutine (definitions) Package Internals &SvREADONLY s0 &SvREFCNT s0 &V s0 &getcwd s0 &hv_clear_placeholders s0 Package PerlIO &get_layers s0 Package Regexp &DESTROY s2147483647 Package Tie::Hash::NamedCapture &CLEAR s0 &DELETE s0 &EXISTS s0 &FETCH s0 &FIRSTKEY s0 &NEXTKEY s0 &SCALAR s0 &STORE s0 &TIEHASH s0 &_tie_it s0 &flags s0 Package UNIVERSAL &DOES s0 &VERSION s0 &can s0 &isa s0 Package constant &_make_const s0 Package main &fizzbuzz s3 Package mro &method_changed_in s0 Package re &is_regexp s0 &regexp_pattern s0 &regname s0 &regnames s0 &regnames_count s0 Package version &("" s0 &() s0 &(* s0 &(*= s0 &(+ s0 &(+= s0 &(- s0 &(-= s0 &(/ s0 &(/= s0 &(0+ s0 &(<=> s0 &(abs s0 &(bool s0 &(cmp s0 &(nomethod s0 &_VERSION s0 &boolean s0 &declare s0 &is_alpha s0 &is_qv s0 &new s0 &noop s0 &normal s0 &numify s0 &parse s0 &qv s0 &stringify s0 &vcmp s0 Subroutine (main) Package (lexical) $fb i3, 4 @$fb 4 Package main $_ 4 &fizzbuzz &3 Subroutine fizzbuzz Package (lexical) $line i10, 13 $m i7, 9 $n i7, 9 $num 11, 12, 13 @out i8, 13, 15 mytest.pl syntax OK

    The numbers you see all over the place are where some entity appears. So $line first appears on line 10, and again on line 13, for example. As you layer in other modules such as strict, warnings, or others that are actually substantial, the output grows considerably. But things are fairly well categorized, so if you know what package to look within, you'll find what you're after. I actually removed use strict and use warnings just to produce output that was more useful in this post.


    Dave

      Wow, discovered a gem here. I had no idea, why I had not taken care to ask/know this earlier.
Re: Visualize Perl Program
by Smonff (Scribe) on Sep 25, 2020 at 21:19 UTC

      /tja(ː)/

      «The Crux of the Biscuit is the Apostrophe»

      perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help

Re: Visualize Perl Program
by LanX (Saint) on Sep 25, 2020 at 19:34 UTC
Re: Visualize Perl Program -- PPI
by Discipulus (Canon) on Oct 01, 2020 at 10:53 UTC
    Hello aartist,

    I'm currently experimenting with PPI and it can be used to visualize your program.

    Using davido sample code I arranged:

    use strict; use warnings; use PPI; use PPI::Dumper; # retrieve the example standalone script from DATA my $doc; while (<DATA>){ $doc .= $_} my $pdom = PPI::Document->new( \$doc ); # uncomment to see the whole pdom #PPI::Dumper->new($pdom)->print; $pdom->find( sub{ # skip white spaces, for example return if $_[1]->isa('PPI::Token::Whitespace'); # just print top level elements if ( # is a top level element $_[1]->parent == $pdom ){ # PPI class remove \n at the en +d starting line print "found TOPLEVEL ",ref $_[1]," ", $_[1]=~s/\n$//r ," +(line ",$_[1]->line_number,")\n"; } } ); __DATA__ #!/usr/bin/env perl my $fb = fizzbuzz(); print "$_\n" for @$fb; sub fizzbuzz { my ($n, $m) = (1, 100); my @out; for my $num ($n .. $m) { my $line = ''; $line .= 'fizz' if $num % 3 == 0; $line .= 'buzz' if $num % 5 == 0; push @out, $line || $num; } return \@out; }

    and the output is:

    found TOPLEVEL PPI::Token::Comment #!/usr/bin/env perl (line 1) found TOPLEVEL PPI::Statement::Variable my $fb = fizzbuzz(); (line 3) found TOPLEVEL PPI::Statement print "$_\n" for @$fb; (line 4) found TOPLEVEL PPI::Statement::Sub sub fizzbuzz { my ($n, $m) = (1, 100); my @out; for my $num ($n .. $m) { my $line = ''; $line .= 'fizz' if $num % 3 == 0; $line .= 'buzz' if $num % 5 == 0; push @out, $line || $num; } return \@out; } (line 6)

    L*

    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.