El siguiente programa Btree3.pl implanta una subrutina
treetrav que muestra el árbol
generado por el compilador para una subrutina dada.
pp2@nereida:~/src/perl/B$ cat -n Btree3.pl
1 #!/usr/local/bin/perl -w
2 use strict;
3 use B::Utils;
4
5 my $s = sub {
6 my $a = shift;
7 print $a+1;
8 };
9
10 sub treetrav {
.. ...........
22 }
23
24 my $b = B::svref_2object($s); # Objeto B::CV
25 print "*** Tree ***\n";
26 my $op = $b->ROOT;
27 treetrav($op, 0);
La llamada a B::svref_2object sobre la subrutina referenciada
por $s nos produce un objeto
B::CV que representa el árbol de codigo resultante.
Cuando treetrav es llamada con el objeto y un sangrado inicial igual a 0
nos produce la siguiente
salida:
pp2@nereida:~/src/perl/B$ Btree3.pl
*** Tree ***
leavesub( #subroutine exit
lineseq( #line sequence
sassign( #scalar assignment
shift( #shift
rv2av( #array dereference
gv( #glob value
) # end gv
) # end rv2av
) # end shift
padsv( #private variable
) # end padsv
) # end sassign
nextstate( #next statement
) # end nextstate
print( #print
add( #addition (+)
padsv( #private variable
) # end padsv
const( #constant item
) # end const
) # end add
) # end print
) # end lineseq
) # end leavesub
La función treetrav usa los métodos name y desc
de la subclase B::OP
para obtener el nombre y la descripción de la operación actual.
El método kids en B::Utils
devuelve la lista de hijos:
10 sub treetrav {
11 my $op = shift;
12 my $indent = shift;
13
14 my $spaces = " "x$indent;
15 print $spaces.$op->name."(\t\t#".$op->desc;
16 print "\n";
17 for ($op->kids()) {
18 treetrav($_, $indent+2);
19 }
20 print "$spaces) # end ".$op->name;
21 print "\n";
22 }
Hay varias subrutinas de recorrido del árbol de
códigos. Una de las mas sencillas es walkoptree_simple
(en B::Utils):
walkoptree_simple($op, \&callback, [$data])
Casiano Rodríguez León
