use Sub::Defer;
use B 'perlstring';
+use Scalar::Util qw(weaken);
use base qw(Exporter);
our @EXPORT = qw(quote_sub unquote_sub quoted_from_sub);
our %QUOTED;
+our %WEAK_REFS;
+
sub capture_unroll {
my ($from, $captures, $indent) = @_;
join(
$ENV{SUB_QUOTE_DEBUG} && warn $assembled_code;
}
$assembled_code .= "\n1;";
- unless (_clean_eval $assembled_code, \@assembled_captures) {
- die "Eval went very, very wrong:\n\n${debug_code}\n\n$@";
+ {
+ local $@;
+ unless (_clean_eval $assembled_code, \@assembled_captures) {
+ die "Eval went very, very wrong:\n\n${debug_code}\n\n$@";
+ }
}
$ENV{SUB_QUOTE_DEBUG} && warn $debug_code;
%QUOTE_OUTSTANDING = ();
$QUOTE_OUTSTANDING{$outstanding} = $QUOTED{$outstanding} = [
$name, $code, $captures
];
+ weaken($WEAK_REFS{$outstanding} = $deferred);
return $deferred;
}
sub quoted_from_sub {
my ($sub) = @_;
- $QUOTED{$sub||''};
+ $WEAK_REFS{$sub||''} and $QUOTED{$sub||''};
}
sub unquote_sub {
quote_sub 'Silly::doggy', q{ print "woof" };
- my $sound; $$sound = 0;
+ my $sound = 0;
quote_sub 'Silly::dagron',
- q{ print ++$$sound % 2 ? 'burninate' : 'roar' },
+ q{ print ++$sound % 2 ? 'burninate' : 'roar' },
{ '$sound' => \$sound };
And elsewhere:
=head2 quote_sub
- my $coderef = quote_sub 'Foo:bar', q{ print $x++ . "\n" }, { '$x' => \0 };
+ my $coderef = quote_sub 'Foo::bar', q{ print $x++ . "\n" }, { '$x' => \0 };
Arguments: ?$name, $code, ?\%captures, ?\%options
my $coderef = unquote_sub $sub;
-Forcibly replace subroutine with actual code. Note that as many subs are
-unquoted at a time for performance reasons. This means that if you have a
-syntax error in one of your quoted subs you may find out when some other sub
-is unquoted.
+Forcibly replace subroutine with actual code. Note that for performance
+reasons all quoted subs declared so far will be globally unquoted/parsed in
+a single eval. This means that if you have a syntax error in one of your
+quoted subs you may find out when some other sub is unquoted.
If $sub is not a quoted sub, this is a no-op.