initial import of half-assed half-working code
[p5sagit/Filter-Keyword.git] / lib / Filter / Keyword.pm
CommitLineData
3b08744b 1package Filter::Keyword;
2
3use Package::Stash::PP;
4use Filter::Util::Call;
5use B qw(svref_2object);
6use Moo;
7
8has target_package => (is => 'ro', required => 1);
9
10has stash => (is => 'lazy');
11
12sub _build_stash {
13 my ($self) = @_;
14 Package::Stash::PP->new($self->target_package);
15}
16
17has keyword_name => (is => 'ro', required => 1);
18
19has globref => (is => 'lazy', clearer => 'clear_globref');
20
21sub _build_globref {
22 no strict 'refs'; no warnings 'once';
23 \*{join'::',$_[0]->target_package,$_[0]->keyword_name}
24}
25
26after clear_globref => sub {
27 my ($self) = @_;
28 $self->stash->remove_symbol('&'.$self->keyword_name);
29 $self->globref_refcount(undef);
30};
31
32has globref_refcount => (is => 'rw');
33
34sub save_refcount {
35 my ($self) = @_;
36 warn "Save: ".$self->globref_refcount(svref_2object($self->globref)->REFCNT);
37}
38
39sub refcount_changed {
40 my ($self) = @_;
41 return 0 unless defined($self->globref_refcount);
42 svref_2object($self->globref)->REFCNT > $self->globref_refcount;
43}
44
45has info => (is => 'rw', predicate => 'has_info', clearer => 'clear_info');
46
47sub setup {
48 my ($self) = @_;
49 $self->globref;
50 filter_add($self);
51}
52
53my $name_re = '[A-Za-z][A-Za-z_0-9]*';
54
55sub filter {
56 my ($self) = @_;
57 if ($self->has_info) {
58 if (delete $self->info->{first}) {
59 warn "Attempting short circuit";
60 filter_add($self);
61 return 0;
62 }
63 my $info = $self->clear_info;
64 $_ = $info->{rest};
65 if ($self->refcount_changed) {
66 warn "Trapped: ".$info->{name};
67 my $name = $info->{name};
68 ${$info->{inner}} = sub { warn "Define ${name}" };
69 #$self->clear_globref;
70 s/{/; sub ${\$info->{name}} { my \$self = shift;/;
71 }
72warn "Line: $_";
73 return 1;
74 }
75 my $status = filter_read();
76warn "Line: $_";
77 my $kw = $self->keyword_name;
78 if (/(.*?$kw\s+(${name_re}))(.*)\Z/s) {
79 my ($start, $name, $rest) = ($1, $2, $3);
80 $self->clear_globref if $self->refcount_changed;
81 no warnings 'redefine';
82 my $inner = sub {};
83 *{$self->globref} = sub (*;@) { $inner->(@_) };
84 $self->save_refcount;
85 $_ = $start;
86 $self->info({
87 name => $name, rest => $rest, first => 1,
88 inner => \$inner
89 });
90 return 1;
91 }
92 return $status;
93}
94
951;