reinstall shadowed sub before continuing parse
Graham Knop [Tue, 18 Jun 2013 08:24:45 +0000 (04:24 -0400)]
This allows shadowed subs to be called in the code returned by the
filter.  It requires restarting the filter so we can switch out the
glob, having the 'trigger' keyword bind to the fake sub and the ouput of
tthe filter bind to the original shadowed sub.

lib/Filter/Keyword.pm
lib/Filter/Keyword/Parser.pm

index 2671ea0..7413655 100644 (file)
@@ -39,7 +39,7 @@ sub install {
   };
 }
 
-has _shadowed_sub => (is => 'rw', clearer => '_clear_shadowed_sub');
+has _shadowed_sub => (is => 'rw', clearer => 1);
 
 sub shadow_sub {
   my $self = shift;
@@ -47,7 +47,6 @@ sub shadow_sub {
   if (my $shadowed = $stash->get_symbol('&'.$self->keyword_name)) {
     $self->_shadowed_sub($shadowed);
     $stash->remove_symbol('&'.$self->keyword_name);
-    $stash->add_symbol('&__'.$self->keyword_name, $shadowed);
   }
 }
 
@@ -59,7 +58,6 @@ sub remove {
   my $stash = $self->stash;
   if (my $shadowed = $self->_shadowed_sub) {
     $self->_clear_shadowed_sub;
-    $stash->remove_symbol('&__'.$self->keyword_name);
     $stash->add_symbol('&'.$self->keyword_name, $shadowed);
   }
 }
@@ -78,6 +76,11 @@ has target_package => (is => 'ro', required => 1);
 has keyword_name   => (is => 'ro', required => 1);
 has parser         => (is => 'ro', required => 1);
 
+sub parse {
+  my $self = shift;
+  $self->${\$self->parser}(@_);
+}
+
 has stash => (is => 'lazy');
 
 sub _build_stash {
@@ -95,6 +98,9 @@ sub _build_globref {
 after clear_globref => sub {
   my ($self) = @_;
   $self->stash->remove_symbol('&'.$self->keyword_name);
+  if (my $shadowed = $self->_shadowed_sub) {
+    { no warnings 'redefine', 'prototype'; *{$self->globref} = $shadowed; }
+  }
   $self->globref_refcount(undef);
 };
 
index 2c80ad3..dcc8214 100644 (file)
@@ -27,6 +27,8 @@ has short_circuit => (is => 'rw');
 
 has code => (is => 'rw', default => sub { '' });
 
+has active_keyword => (is => 'rw', clearer => 1);
+
 sub get_next {
   my ($self) = @_;
   if ($self->short_circuit) {
@@ -34,10 +36,20 @@ sub get_next {
     $self->${\$self->re_add};
     return ('', 0);
   }
+  if (my $keyword = $self->active_keyword) {
+    $self->clear_active_keyword;
+    $keyword->clear_globref;
+    return $keyword->parse($self);
+  }
   for my $keyword (@{$self->keywords}) {
     if ($keyword->have_match) {
-      $keyword->clear_globref;
-      return $keyword->parser->($keyword, $self);
+      $self->active_keyword($keyword);
+      $self->short_circuit(1);
+      my $match = $self->current_match->[0];
+      my $end = $match eq '{' ? '}'
+              : $match eq '(' ? ')'
+                              : '';
+      return ("$end;", 1);
     }
   }
   return $self->check_match;