No need for ScalarRef when using Sub::Quote
[gitmo/Role-Tiny.git] / lib / Sub / Quote.pm
index f58652a..b5c5cc6 100644 (file)
@@ -6,6 +6,7 @@ sub _clean_eval { eval $_[0] }
 
 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);
@@ -14,6 +15,8 @@ our %QUOTE_OUTSTANDING;
 
 our %QUOTED;
 
+our %WEAK_REFS;
+
 sub capture_unroll {
   my ($from, $captures, $indent) = @_;
   join(
@@ -87,8 +90,11 @@ sub _unquote_all_outstanding {
     $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 = ();
@@ -117,12 +123,13 @@ sub quote_sub {
   $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 {
@@ -147,10 +154,10 @@ Sub::Quote - efficient generation of subroutines via string eval
 
  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:
@@ -169,7 +176,7 @@ This package provides performant ways to generate subroutines from strings.
 
 =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
 
@@ -195,10 +202,10 @@ passed subroutine name on undefer.
 
  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.