Given a CODE ref, is it possible to:
Normally we create subroutines in perl by specifying source code which is then parsed and converted into a parse tree.
I would like to write a perl function which can create a subroutine by specifying its parse tree, and that parse tree could be derived from another parse tree of some other subroutine.
Possible?
I don't know the full answer to your question, but I know that Data::Dumper can deparse a code reference. Looking at its documentation, I see that it uses B::Deparse
to do the heavy lifting (the B::
modules are the ones that interact with the compiler). Unfortunately it seems that this only results in a textual representation of the coderef.
Instead I searched for Op
on metacpan and got many more interesting possibilities. Since I am now far out of my depth in the deepest Perl magic, I will leave it to you to look over those results. Perhaps something will be useful.
This has nothing to do with opcodes, but it does enclose the same two variables in three different closures. The variables are enclosed within subroutines reminiscent of class get/set routines, and those closed vars are then shared by other closures via their access routine.
This is a response to the comment: I'm sure it will be necessary to access the underlying nodes in the parse tree so that I can create new closures which are closed over the same variables.
use strict;
use warnings;
use v5.14;
# create closed vars
my $v1 = access_closure(6);
my $v2 = access_closure(42);
# play with them
say "v1 ", &$v1;
say "v2 ", &$v2;
say "v1 ", &$v1(5);
say "v2 ", &$v2(43);
say "v1 ", &$v1;
say "v2 ", &$v2;
# create silly closures that use them
my $test1 = test_closure(2);
my $test2 = test_closure(17);
my $test3 = test_closure(50);
# play with those
&$test1;
&$test2;
&$test3;
# create the get/set routine for a closed var
sub access_closure {
my $val = shift;
return sub {
$val = shift if @_;
return $val;
}
}
# create a silly closure that encloses a control var and uses the two other vars
sub test_closure {
my $val = shift;
return sub {
say "\nval is $val";
printf "v1 is %2d, v2 is %2d\n",
&$v1, &$v2;
if (&$v1 < $val) {
say "Increment v1";
&$v1(&$v1+1);
}
if (&$v2 > $val) {
say "Decrement v2";
&$v2(&$v2-1);
}
printf "v1 is %2d, v2 is %2d\n",
&$v1, &$v2;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With