El módulo de núcleo B::Deparse proporciona esta funcionalidad.
use B::Deparse();
my $deparse = B::Deparse->new;
my $code = sub {print "hello, world!"};
print 'sub ', $deparse->coderef2text($code), "\n";
que imprime:
sub {
print 'hello, world!';
}
Al utilizar B::Deparse
es importante recordar que lo que devuelve es una versión descompilada del árbol compilado de códigos de operación, no el texto fuente original. Esto significa que las constantes, las expresiones aritméticas y otras construcciones pueden ser dobladas y reescritas por el optimizador.
La otra parte del rompecabezas se trata de cerrar las variables léxicas. Si las subrutinas con las que está trabajando acceden a léxicos externos, no estarán presentes en la salida de deparse y provocarán la falla de la recopilación. Puede resolverlo con las funciones closed_over
y set_closed_over
del módulo PadWalker.
use PadWalker qw/closed_over set_closed_over/;
my $closure = do {
my $counter = 0;
sub {$counter++}
};
print $closure->(), ' ' for 1..3; # 0 1 2
print "\n";
my $pad = closed_over $closure; # hash of lexicals
# create dummy lexicals for compilation
my $copy = eval 'my ('.join(','=> keys %$pad).');'.
'sub '.$deparse->coderef2text($closure);
set_closed_over $copy, $pad; # replace dummy lexicals with real ones
print $copy->(), ' ' for 1..3; # 3 4 5
Por último, si quieres averiguar dónde código fuente real de la subrutina es, puede utilizar el módulo principal B:
use B();
my $meta = B::svref_2object($closure);
print "$closure at ".$meta->FILE.' line '.$meta->GV->LINE."\n";
que imprime algo como:
CODE(0x28dcffc) at filename.pl line 21
respuesta muy en profundidad, gracias. :) –
Desafortunadamente, me di cuenta de que mi problema principal era en realidad con el compartimento seguro en el que se encontraba mi Mason: las clases de back-end están bloqueadas de ejecución, así que creo que no tengo suerte. –