1 package Filter::Keyword;
4 use Filter::Keyword::Filter;
5 use Filter::Util::Call;
6 use Scalar::Util qw(weaken);
7 use Package::Stash::PP;
8 use B qw(svref_2object);
9 use B::Hooks::EndOfScope;
10 use Scalar::Util qw(set_prototype);
12 sub _compiling_file () {
14 while (my @caller = caller(++$depth)) {
15 if ($caller[3] =~ /::BEGIN$/) {
16 # older perls report the BEGIN in the wrong file
17 return $depth > 1 ? (caller($depth-1))[1] : $caller[1];
29 my $file = _compiling_file;
30 my $filter = $filters{$file} ||= Filter::Keyword::Filter->new;
33 my $parser = $filter->parser;
34 $parser->add_keyword($self);
35 $self->keyword_parser($parser);
42 has _shadowed_sub => (is => 'rw', clearer => 1);
46 my $stash = $self->stash;
47 if (my $shadowed = $stash->get_symbol('&'.$self->keyword_name)) {
48 $self->_shadowed_sub($shadowed);
49 $stash->remove_symbol('&'.$self->keyword_name);
55 $self->keyword_parser->remove_keyword($self);
56 $self->clear_keyword_parser;
58 my $stash = $self->stash;
59 if (my $shadowed = $self->_shadowed_sub) {
60 $self->_clear_shadowed_sub;
61 $stash->add_symbol('&'.$self->keyword_name, $shadowed);
65 has keyword_parser => (
75 has target_package => (is => 'ro', required => 1);
76 has keyword_name => (is => 'ro', required => 1);
77 has parser => (is => 'ro', required => 1);
81 $self->${\$self->parser}(@_);
84 has stash => (is => 'lazy');
88 Package::Stash::PP->new($self->target_package);
91 has globref => (is => 'lazy', clearer => 'clear_globref');
94 no strict 'refs'; no warnings 'once';
95 \*{join'::',$_[0]->target_package,$_[0]->keyword_name}
98 after clear_globref => sub {
100 $self->stash->remove_symbol('&'.$self->keyword_name);
101 $self->globref_refcount(undef);
102 $self->restore_shadow;
107 if (my $shadowed = $self->_shadowed_sub) {
108 { no warnings 'redefine', 'prototype'; *{$self->globref} = $shadowed; }
112 has globref_refcount => (is => 'rw');
116 $self->globref_refcount(svref_2object($self->globref)->REFCNT);
119 sub install_matcher {
120 my ($self, $post) = @_;
121 my $stash = $self->stash;
123 set_prototype(\&$sub, '*;@') unless $post eq '(';
124 { no warnings 'redefine', 'prototype'; *{$self->globref} = $sub; }
125 $self->save_refcount;
130 return 0 unless defined($self->globref_refcount);
131 svref_2object($self->globref)->REFCNT > $self->globref_refcount;
134 sub inject_after_scope {
139 $status = filter_read();