Recorrer el Árbol

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
Licencia de Creative Commons
Principios de Programación Imperativa, Funcional y Orientada a Objetos Una Introducción en Perl/Una Introducción a Perl
por Casiano Rodríguez León is licensed under a Creative Commons Reconocimiento 3.0 Unported License.

Permissions beyond the scope of this license may be available at http://campusvirtual.ull.es/ocw/course/view.php?id=43.
2012-06-19