remove debug garbage
[p5sagit/Filter-Keyword.git] / lib / Filter / Keyword.pm
CommitLineData
3b08744b 1package Filter::Keyword;
3b08744b 2use Moo;
3
c15f7959 4use Filter::Keyword::Filter;
5use Scalar::Util qw(weaken);
6use Package::Stash::PP;
7use B qw(svref_2object);
6c0ec68b 8use B::Hooks::EndOfScope;
3b08744b 9
c15f7959 10sub _compiling_file () {
11 my $depth = 0;
12 while (my @caller = caller(++$depth)) {
13 if ($caller[3] =~ /::BEGIN$/) {
14 # older perls report the BEGIN in the wrong file
15 return $depth > 1 ? (caller($depth-1))[1] : $caller[1];
16 #return $caller[1];
17 }
18 }
19 die;
20}
3b08744b 21
c15f7959 22my %filters;
23sub install {
3b08744b 24 my ($self) = @_;
c15f7959 25 $self->shadow_sub;
6c0ec68b 26
27 my $file = _compiling_file;
c15f7959 28 my $filter = $filters{$file} ||= Filter::Keyword::Filter->new;
29 $filter->install;
6c0ec68b 30
c15f7959 31 my $parser = $filter->parser;
32 $parser->add_keyword($self);
33 $self->keyword_parser($parser);
6c0ec68b 34
35 on_scope_end {
36 $self->remove;
37 };
3b08744b 38}
39
17022343 40has _shadowed_sub => (is => 'rw', clearer => '_clear_shadowed_sub');
41
c15f7959 42sub shadow_sub {
43 my $self = shift;
44 my $stash = $self->stash;
45 if (my $shadowed = $stash->get_symbol('&'.$self->keyword_name)) {
17022343 46 $self->_shadowed_sub($shadowed);
c15f7959 47 $stash->remove_symbol('&'.$self->keyword_name);
48 $stash->add_symbol('&__'.$self->keyword_name, $shadowed);
49 }
50}
51
52sub remove {
53 my ($self) = @_;
54 $self->keyword_parser->remove_keyword($self);
55 $self->clear_keyword_parser;
56 $self->clear_globref;
17022343 57 my $stash = $self->stash;
58 if (my $shadowed = $self->_shadowed_sub) {
59 $self->_clear_shadowed_sub;
60 $stash->remove_symbol('&__'.$self->keyword_name);
61 $stash->add_symbol('&'.$self->keyword_name, $shadowed);
62 }
c15f7959 63}
64
809ae673 65has keyword_parser => (
66 is => 'rw',
67 weak_ref => 1,
68 clearer => 1,
69 handles => [
70 'match_source',
71 'current_match',
72 ],
73);
c15f7959 74
75has target_package => (is => 'ro', required => 1);
76has keyword_name => (is => 'ro', required => 1);
77has parser => (is => 'ro', required => 1);
78
79has stash => (is => 'lazy');
80
81sub _build_stash {
82 my ($self) = @_;
83 Package::Stash::PP->new($self->target_package);
84}
85
86has globref => (is => 'lazy', clearer => 'clear_globref');
87
88sub _build_globref {
89 no strict 'refs'; no warnings 'once';
90 \*{join'::',$_[0]->target_package,$_[0]->keyword_name}
91}
92
93after clear_globref => sub {
94 my ($self) = @_;
95 $self->stash->remove_symbol('&'.$self->keyword_name);
96 $self->globref_refcount(undef);
97};
98
99has globref_refcount => (is => 'rw');
100
101sub save_refcount {
102 my ($self) = @_;
103 $self->globref_refcount(svref_2object($self->globref)->REFCNT);
104}
105
106sub have_match {
107 my ($self) = @_;
108 return 0 unless defined($self->globref_refcount);
109 svref_2object($self->globref)->REFCNT > $self->globref_refcount;
110}
111
bee972ee 112sub inject_after_scope {
113 my $inject = shift;
114 on_scope_end {
115 filter_add(sub {
116 my($status) ;
117 $status = filter_read();
118 if ($status >= 0) {
119 $_ = $inject . $_;
120 }
121 filter_del();
122 $status ;
123 });
124 };
3b08744b 125}
126
1271;