ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/staticperl/perl/lib/Filter/Simple.pm
Revision: 1.1
Committed: Thu Jun 30 14:27:12 2005 UTC (21 years, 4 months ago) by root
Branch: MAIN
CVS Tags: PERL-5-8-7, HEAD
Branch point for: PERL
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 package Filter::Simple;
2    
3     use Text::Balanced ':ALL';
4    
5     use vars qw{ $VERSION @EXPORT };
6    
7     $VERSION = '0.78';
8    
9     use Filter::Util::Call;
10     use Carp;
11    
12     @EXPORT = qw( FILTER FILTER_ONLY );
13    
14    
15     sub import {
16     if (@_>1) { shift; goto &FILTER }
17     else { *{caller()."::$_"} = \&$_ foreach @EXPORT }
18     }
19    
20     sub FILTER (&;$) {
21     my $caller = caller;
22     my ($filter, $terminator) = @_;
23     local $SIG{__WARN__} = sub{};
24     *{"${caller}::import"} = gen_filter_import($caller,$filter,$terminator);
25     *{"${caller}::unimport"} = gen_filter_unimport($caller);
26     }
27    
28     sub fail {
29     croak "FILTER_ONLY: ", @_;
30     }
31    
32     my $exql = sub {
33     my @bits = extract_quotelike $_[0], qr//;
34     return unless $bits[0];
35     return \@bits;
36     };
37    
38     my $ws = qr/\s+/;
39     my $id = qr/\b(?!([ysm]|q[rqxw]?|tr)\b)\w+/;
40     my $EOP = qr/\n\n|\Z/;
41     my $CUT = qr/\n=cut.*$EOP/;
42     my $pod_or_DATA = qr/
43     ^=(?:head[1-4]|item) .*? $CUT
44     | ^=pod .*? $CUT
45     | ^=for .*? $EOP
46     | ^=begin \s* (\S+) .*? \n=end \s* \1 .*? $EOP
47     | ^__(DATA|END)__\r?\n.*
48     /smx;
49    
50     my %extractor_for = (
51     quotelike => [ $ws, $id, { MATCH => \&extract_quotelike } ],
52     regex => [ $ws, $pod_or_DATA, $id, $exql ],
53     string => [ $ws, $pod_or_DATA, $id, $exql ],
54     code => [ $ws, { DONT_MATCH => $pod_or_DATA },
55     $id, { DONT_MATCH => \&extract_quotelike } ],
56     executable => [ $ws, { DONT_MATCH => $pod_or_DATA } ],
57     all => [ { MATCH => qr/(?s:.*)/ } ],
58     );
59    
60     my %selector_for = (
61     all => sub { my ($t)=@_; sub{ $_=$$_; $t->(@_); $_} },
62     executable=> sub { my ($t)=@_; sub{ref() ? $_=$$_ : $t->(@_); $_} },
63     quotelike => sub { my ($t)=@_; sub{ref() && do{$_=$$_; $t->(@_)}; $_} },
64     regex => sub { my ($t)=@_;
65     sub{ref() or return $_;
66     my ($ql,undef,$pre,$op,$ld,$pat) = @$_;
67     return $_->[0] unless $op =~ /^(qr|m|s)/
68     || !$op && ($ld eq '/' || $ld eq '?');
69     $_ = $pat;
70     $t->(@_);
71     $ql =~ s/^(\s*\Q$op\E\s*\Q$ld\E)\Q$pat\E/$1$_/;
72     return "$pre$ql";
73     };
74     },
75     string => sub { my ($t)=@_;
76     sub{ref() or return $_;
77     local *args = \@_;
78     my ($pre,$op,$ld1,$str1,$rd1,$ld2,$str2,$rd2,$flg) = @{$_}[2..10];
79     return $_->[0] if $op =~ /^(qr|m)/
80     || !$op && ($ld1 eq '/' || $ld1 eq '?');
81     if (!$op || $op eq 'tr' || $op eq 'y') {
82     local *_ = \$str1;
83     $t->(@args);
84     }
85     if ($op =~ /^(tr|y|s)/) {
86     local *_ = \$str2;
87     $t->(@args);
88     }
89     my $result = "$pre$op$ld1$str1$rd1";
90     $result .= $ld2 if $ld1 =~ m/[[({<]/; #])}>
91     $result .= "$str2$rd2$flg";
92     return $result;
93     };
94     },
95     );
96    
97    
98     sub gen_std_filter_for {
99     my ($type, $transform) = @_;
100     return sub { my (@pieces, $instr);
101     $DB::single=1;
102     for (extract_multiple($_,$extractor_for{$type})) {
103     if (ref()) { push @pieces, $_; $instr=0 }
104     elsif ($instr) { $pieces[-1] .= $_ }
105     else { push @pieces, $_; $instr=1 }
106     }
107     if ($type eq 'code') {
108     my $count = 0;
109     local $placeholder = qr/\Q$;\E(?:\C{4})\Q$;\E/;
110     my $extractor = qr/\Q$;\E(\C{4})\Q$;\E/;
111     $_ = join "",
112     map { ref $_ ? $;.pack('N',$count++).$; : $_ }
113     @pieces;
114     @pieces = grep { ref $_ } @pieces;
115     $transform->(@_);
116     s/$extractor/${$pieces[unpack('N',$1)]}/g;
117     }
118     else {
119     my $selector = $selector_for{$type}->($transform);
120     $_ = join "", map $selector->(@_), @pieces;
121     }
122     }
123     };
124    
125     sub FILTER_ONLY {
126     my $caller = caller;
127     while (@_ > 1) {
128     my ($what, $how) = splice(@_, 0, 2);
129     fail "Unknown selector: $what"
130     unless exists $extractor_for{$what};
131     fail "Filter for $what is not a subroutine reference"
132     unless ref $how eq 'CODE';
133     push @transforms, gen_std_filter_for($what,$how);
134     }
135     my $terminator = shift;
136    
137     my $multitransform = sub {
138     foreach my $transform ( @transforms ) {
139     $transform->(@_);
140     }
141     };
142     no warnings 'redefine';
143     *{"${caller}::import"} =
144     gen_filter_import($caller,$multitransform,$terminator);
145     *{"${caller}::unimport"} = gen_filter_unimport($caller);
146     }
147    
148     my $ows = qr/(?:[ \t]+|#[^\n]*)*/;
149    
150     sub gen_filter_import {
151     my ($class, $filter, $terminator) = @_;
152     my %terminator;
153     my $prev_import = *{$class."::import"}{CODE};
154     return sub {
155     my ($imported_class, @args) = @_;
156     my $def_terminator =
157     qr/^(?:\s*no\s+$imported_class\s*;$ows|__(?:END|DATA)__)\r?$/;
158     if (!defined $terminator) {
159     $terminator{terminator} = $def_terminator;
160     }
161     elsif (!ref $terminator || ref $terminator eq 'Regexp') {
162     $terminator{terminator} = $terminator;
163     }
164     elsif (ref $terminator ne 'HASH') {
165     croak "Terminator must be specified as scalar or hash ref"
166     }
167     elsif (!exists $terminator->{terminator}) {
168     $terminator{terminator} = $def_terminator;
169     }
170     filter_add(
171     sub {
172     my ($status, $lastline);
173     my $count = 0;
174     my $data = "";
175     while ($status = filter_read()) {
176     return $status if $status < 0;
177     if ($terminator{terminator} &&
178     m/$terminator{terminator}/) {
179     $lastline = $_;
180     last;
181     }
182     $data .= $_;
183     $count++;
184     $_ = "";
185     }
186     $_ = $data;
187     $filter->($imported_class, @args) unless $status < 0;
188     if (defined $lastline) {
189     if (defined $terminator{becomes}) {
190     $_ .= $terminator{becomes};
191     }
192     elsif ($lastline =~ $def_terminator) {
193     $_ .= $lastline;
194     }
195     }
196     return $count;
197     }
198     );
199     if ($prev_import) {
200     goto &$prev_import;
201     }
202     elsif ($class->isa('Exporter')) {
203     $class->export_to_level(1,@_);
204     }
205     }
206     }
207    
208     sub gen_filter_unimport {
209     my ($class) = @_;
210     my $prev_unimport = *{$class."::unimport"}{CODE};
211     return sub {
212     filter_del();
213     goto &$prev_unimport if $prev_unimport;
214     }
215     }
216    
217     1;
218    
219     __END__
220    
221     =head1 NAME
222    
223     Filter::Simple - Simplified source filtering
224    
225    
226     =head1 SYNOPSIS
227    
228     # in MyFilter.pm:
229    
230     package MyFilter;
231    
232     use Filter::Simple;
233    
234     FILTER { ... };
235    
236     # or just:
237     #
238     # use Filter::Simple sub { ... };
239    
240     # in user's code:
241    
242     use MyFilter;
243    
244     # this code is filtered
245    
246     no MyFilter;
247    
248     # this code is not
249    
250    
251     =head1 DESCRIPTION
252    
253     =head2 The Problem
254    
255     Source filtering is an immensely powerful feature of recent versions of Perl.
256     It allows one to extend the language itself (e.g. the Switch module), to
257     simplify the language (e.g. Language::Pythonesque), or to completely recast the
258     language (e.g. Lingua::Romana::Perligata). Effectively, it allows one to use
259     the full power of Perl as its own, recursively applied, macro language.
260    
261     The excellent Filter::Util::Call module (by Paul Marquess) provides a
262     usable Perl interface to source filtering, but it is often too powerful
263     and not nearly as simple as it could be.
264    
265     To use the module it is necessary to do the following:
266    
267     =over 4
268    
269     =item 1.
270    
271     Download, build, and install the Filter::Util::Call module.
272     (If you have Perl 5.7.1 or later, this is already done for you.)
273    
274     =item 2.
275    
276     Set up a module that does a C<use Filter::Util::Call>.
277    
278     =item 3.
279    
280     Within that module, create an C<import> subroutine.
281    
282     =item 4.
283    
284     Within the C<import> subroutine do a call to C<filter_add>, passing
285     it either a subroutine reference.
286    
287     =item 5.
288    
289     Within the subroutine reference, call C<filter_read> or C<filter_read_exact>
290     to "prime" $_ with source code data from the source file that will
291     C<use> your module. Check the status value returned to see if any
292     source code was actually read in.
293    
294     =item 6.
295    
296     Process the contents of $_ to change the source code in the desired manner.
297    
298     =item 7.
299    
300     Return the status value.
301    
302     =item 8.
303    
304     If the act of unimporting your module (via a C<no>) should cause source
305     code filtering to cease, create an C<unimport> subroutine, and have it call
306     C<filter_del>. Make sure that the call to C<filter_read> or
307     C<filter_read_exact> in step 5 will not accidentally read past the
308     C<no>. Effectively this limits source code filters to line-by-line
309     operation, unless the C<import> subroutine does some fancy
310     pre-pre-parsing of the source code it's filtering.
311    
312     =back
313    
314     For example, here is a minimal source code filter in a module named
315     BANG.pm. It simply converts every occurrence of the sequence C<BANG\s+BANG>
316     to the sequence C<die 'BANG' if $BANG> in any piece of code following a
317     C<use BANG;> statement (until the next C<no BANG;> statement, if any):
318    
319     package BANG;
320    
321     use Filter::Util::Call ;
322    
323     sub import {
324     filter_add( sub {
325     my $caller = caller;
326     my ($status, $no_seen, $data);
327     while ($status = filter_read()) {
328     if (/^\s*no\s+$caller\s*;\s*?$/) {
329     $no_seen=1;
330     last;
331     }
332     $data .= $_;
333     $_ = "";
334     }
335     $_ = $data;
336     s/BANG\s+BANG/die 'BANG' if \$BANG/g
337     unless $status < 0;
338     $_ .= "no $class;\n" if $no_seen;
339     return 1;
340     })
341     }
342    
343     sub unimport {
344     filter_del();
345     }
346    
347     1 ;
348    
349     This level of sophistication puts filtering out of the reach of
350     many programmers.
351    
352    
353     =head2 A Solution
354    
355     The Filter::Simple module provides a simplified interface to
356     Filter::Util::Call; one that is sufficient for most common cases.
357    
358     Instead of the above process, with Filter::Simple the task of setting up
359     a source code filter is reduced to:
360    
361     =over 4
362    
363     =item 1.
364    
365     Download and install the Filter::Simple module.
366     (If you have Perl 5.7.1 or later, this is already done for you.)
367    
368     =item 2.
369    
370     Set up a module that does a C<use Filter::Simple> and then
371     calls C<FILTER { ... }>.
372    
373     =item 3.
374    
375     Within the anonymous subroutine or block that is passed to
376     C<FILTER>, process the contents of $_ to change the source code in
377     the desired manner.
378    
379     =back
380    
381     In other words, the previous example, would become:
382    
383     package BANG;
384     use Filter::Simple;
385    
386     FILTER {
387     s/BANG\s+BANG/die 'BANG' if \$BANG/g;
388     };
389    
390     1 ;
391    
392     Note that the source code is passed as a single string, so any regex that
393     uses C<^> or C<$> to detect line boundaries will need the C</m> flag.
394    
395     =head2 Disabling or changing <no> behaviour
396    
397     By default, the installed filter only filters up to a line consisting of one of
398     the three standard source "terminators":
399    
400     no ModuleName; # optional comment
401    
402     or:
403    
404     __END__
405    
406     or:
407    
408     __DATA__
409    
410     but this can be altered by passing a second argument to C<use Filter::Simple>
411     or C<FILTER> (just remember: there's I<no> comma after the initial block when
412     you use C<FILTER>).
413    
414     That second argument may be either a C<qr>'d regular expression (which is then
415     used to match the terminator line), or a defined false value (which indicates
416     that no terminator line should be looked for), or a reference to a hash
417     (in which case the terminator is the value associated with the key
418     C<'terminator'>.
419    
420     For example, to cause the previous filter to filter only up to a line of the
421     form:
422    
423     GNAB esu;
424    
425     you would write:
426    
427     package BANG;
428     use Filter::Simple;
429    
430     FILTER {
431     s/BANG\s+BANG/die 'BANG' if \$BANG/g;
432     }
433     qr/^\s*GNAB\s+esu\s*;\s*?$/;
434    
435     or:
436    
437     FILTER {
438     s/BANG\s+BANG/die 'BANG' if \$BANG/g;
439     }
440     { terminator => qr/^\s*GNAB\s+esu\s*;\s*?$/ };
441    
442     and to prevent the filter's being turned off in any way:
443    
444     package BANG;
445     use Filter::Simple;
446    
447     FILTER {
448     s/BANG\s+BANG/die 'BANG' if \$BANG/g;
449     }
450     ""; # or: 0
451    
452     or:
453    
454     FILTER {
455     s/BANG\s+BANG/die 'BANG' if \$BANG/g;
456     }
457     { terminator => "" };
458    
459     B<Note that, no matter what you set the terminator pattern to,
460     the actual terminator itself I<must> be contained on a single source line.>
461    
462    
463     =head2 All-in-one interface
464    
465     Separating the loading of Filter::Simple:
466    
467     use Filter::Simple;
468    
469     from the setting up of the filtering:
470    
471     FILTER { ... };
472    
473     is useful because it allows other code (typically parser support code
474     or caching variables) to be defined before the filter is invoked.
475     However, there is often no need for such a separation.
476    
477     In those cases, it is easier to just append the filtering subroutine and
478     any terminator specification directly to the C<use> statement that loads
479     Filter::Simple, like so:
480    
481     use Filter::Simple sub {
482     s/BANG\s+BANG/die 'BANG' if \$BANG/g;
483     };
484    
485     This is exactly the same as:
486    
487     use Filter::Simple;
488     BEGIN {
489     Filter::Simple::FILTER {
490     s/BANG\s+BANG/die 'BANG' if \$BANG/g;
491     };
492     }
493    
494     except that the C<FILTER> subroutine is not exported by Filter::Simple.
495    
496    
497     =head2 Filtering only specific components of source code
498    
499     One of the problems with a filter like:
500    
501     use Filter::Simple;
502    
503     FILTER { s/BANG\s+BANG/die 'BANG' if \$BANG/g };
504    
505     is that it indiscriminately applies the specified transformation to
506     the entire text of your source program. So something like:
507    
508     warn 'BANG BANG, YOU'RE DEAD';
509     BANG BANG;
510    
511     will become:
512    
513     warn 'die 'BANG' if $BANG, YOU'RE DEAD';
514     die 'BANG' if $BANG;
515    
516     It is very common when filtering source to only want to apply the filter
517     to the non-character-string parts of the code, or alternatively to I<only>
518     the character strings.
519    
520     Filter::Simple supports this type of filtering by automatically
521     exporting the C<FILTER_ONLY> subroutine.
522    
523     C<FILTER_ONLY> takes a sequence of specifiers that install separate
524     (and possibly multiple) filters that act on only parts of the source code.
525     For example:
526    
527     use Filter::Simple;
528    
529     FILTER_ONLY
530     code => sub { s/BANG\s+BANG/die 'BANG' if \$BANG/g },
531     quotelike => sub { s/BANG\s+BANG/CHITTY CHITTY/g };
532    
533     The C<"code"> subroutine will only be used to filter parts of the source
534     code that are not quotelikes, POD, or C<__DATA__>. The C<quotelike>
535     subroutine only filters Perl quotelikes (including here documents).
536    
537     The full list of alternatives is:
538    
539     =over
540    
541     =item C<"code">
542    
543     Filters only those sections of the source code that are not quotelikes, POD, or
544     C<__DATA__>.
545    
546     =item C<"executable">
547    
548     Filters only those sections of the source code that are not POD or C<__DATA__>.
549    
550     =item C<"quotelike">
551    
552     Filters only Perl quotelikes (as interpreted by
553     C<&Text::Balanced::extract_quotelike>).
554    
555     =item C<"string">
556    
557     Filters only the string literal parts of a Perl quotelike (i.e. the
558     contents of a string literal, either half of a C<tr///>, the second
559     half of an C<s///>).
560    
561     =item C<"regex">
562    
563     Filters only the pattern literal parts of a Perl quotelike (i.e. the
564     contents of a C<qr//> or an C<m//>, the first half of an C<s///>).
565    
566     =item C<"all">
567    
568     Filters everything. Identical in effect to C<FILTER>.
569    
570     =back
571    
572     Except for C<< FILTER_ONLY code => sub {...} >>, each of
573     the component filters is called repeatedly, once for each component
574     found in the source code.
575    
576     Note that you can also apply two or more of the same type of filter in
577     a single C<FILTER_ONLY>. For example, here's a simple
578     macro-preprocessor that is only applied within regexes,
579     with a final debugging pass that prints the resulting source code:
580    
581     use Regexp::Common;
582     FILTER_ONLY
583     regex => sub { s/!\[/[^/g },
584     regex => sub { s/%d/$RE{num}{int}/g },
585     regex => sub { s/%f/$RE{num}{real}/g },
586     all => sub { print if $::DEBUG };
587    
588    
589    
590     =head2 Filtering only the code parts of source code
591    
592     Most source code ceases to be grammatically correct when it is broken up
593     into the pieces between string literals and regexes. So the C<'code'>
594     component filter behaves slightly differently from the other partial filters
595     described in the previous section.
596    
597     Rather than calling the specified processor on each individual piece of
598     code (i.e. on the bits between quotelikes), the C<'code'> partial filter
599     operates on the entire source code, but with the quotelike bits
600     "blanked out".
601    
602     That is, a C<'code'> filter I<replaces> each quoted string, quotelike,
603     regex, POD, and __DATA__ section with a placeholder. The
604     delimiters of this placeholder are the contents of the C<$;> variable
605     at the time the filter is applied (normally C<"\034">). The remaining
606     four bytes are a unique identifier for the component being replaced.
607    
608     This approach makes it comparatively easy to write code preprocessors
609     without worrying about the form or contents of strings, regexes, etc.
610     For convenience, during a C<'code'> filtering operation, Filter::Simple
611     provides a package variable (C<$Filter::Simple::placeholder>) that contains
612     a pre-compiled regex that matches any placeholder. Placeholders can be
613     moved and re-ordered within the source code as needed.
614    
615     Once the filtering has been applied, the original strings, regexes,
616     POD, etc. are re-inserted into the code, by replacing each
617     placeholder with the corresponding original component.
618    
619     For example, the following filter detects concatentated pairs of
620     strings/quotelikes and reverses the order in which they are
621     concatenated:
622    
623     package DemoRevCat;
624     use Filter::Simple;
625    
626     FILTER_ONLY code => sub { my $ph = $Filter::Simple::placeholder;
627     s{ ($ph) \s* [.] \s* ($ph) }{ $2.$1 }gx
628     };
629    
630     Thus, the following code:
631    
632     use DemoRevCat;
633    
634     my $str = "abc" . q(def);
635    
636     print "$str\n";
637    
638     would become:
639    
640     my $str = q(def)."abc";
641    
642     print "$str\n";
643    
644     and hence print:
645    
646     defabc
647    
648    
649     =head2 Using Filter::Simple with an explicit C<import> subroutine
650    
651     Filter::Simple generates a special C<import> subroutine for
652     your module (see L<"How it works">) which would normally replace any
653     C<import> subroutine you might have explicitly declared.
654    
655     However, Filter::Simple is smart enough to notice your existing
656     C<import> and Do The Right Thing with it.
657     That is, if you explicitly define an C<import> subroutine in a package
658     that's using Filter::Simple, that C<import> subroutine will still
659     be invoked immediately after any filter you install.
660    
661     The only thing you have to remember is that the C<import> subroutine
662     I<must> be declared I<before> the filter is installed. If you use C<FILTER>
663     to install the filter:
664    
665     package Filter::TurnItUpTo11;
666    
667     use Filter::Simple;
668    
669     FILTER { s/(\w+)/\U$1/ };
670    
671     that will almost never be a problem, but if you install a filtering
672     subroutine by passing it directly to the C<use Filter::Simple>
673     statement:
674    
675     package Filter::TurnItUpTo11;
676    
677     use Filter::Simple sub{ s/(\w+)/\U$1/ };
678    
679     then you must make sure that your C<import> subroutine appears before
680     that C<use> statement.
681    
682    
683     =head2 Using Filter::Simple and Exporter together
684    
685     Likewise, Filter::Simple is also smart enough
686     to Do The Right Thing if you use Exporter:
687    
688     package Switch;
689     use base Exporter;
690     use Filter::Simple;
691    
692     @EXPORT = qw(switch case);
693     @EXPORT_OK = qw(given when);
694    
695     FILTER { $_ = magic_Perl_filter($_) }
696    
697     Immediately after the filter has been applied to the source,
698     Filter::Simple will pass control to Exporter, so it can do its magic too.
699    
700     Of course, here too, Filter::Simple has to know you're using Exporter
701     before it applies the filter. That's almost never a problem, but if you're
702     nervous about it, you can guarantee that things will work correctly by
703     ensuring that your C<use base Exporter> always precedes your
704     C<use Filter::Simple>.
705    
706    
707     =head2 How it works
708    
709     The Filter::Simple module exports into the package that calls C<FILTER>
710     (or C<use>s it directly) -- such as package "BANG" in the above example --
711     two automagically constructed
712     subroutines -- C<import> and C<unimport> -- which take care of all the
713     nasty details.
714    
715     In addition, the generated C<import> subroutine passes its own argument
716     list to the filtering subroutine, so the BANG.pm filter could easily
717     be made parametric:
718    
719     package BANG;
720    
721     use Filter::Simple;
722    
723     FILTER {
724     my ($die_msg, $var_name) = @_;
725     s/BANG\s+BANG/die '$die_msg' if \${$var_name}/g;
726     };
727    
728     # and in some user code:
729    
730     use BANG "BOOM", "BAM"; # "BANG BANG" becomes: die 'BOOM' if $BAM
731    
732    
733     The specified filtering subroutine is called every time a C<use BANG> is
734     encountered, and passed all the source code following that call, up to
735     either the next C<no BANG;> (or whatever terminator you've set) or the
736     end of the source file, whichever occurs first. By default, any C<no
737     BANG;> call must appear by itself on a separate line, or it is ignored.
738    
739    
740     =head1 AUTHOR
741    
742     Damian Conway (damian@conway.org)
743    
744     =head1 COPYRIGHT
745    
746     Copyright (c) 2000-2001, Damian Conway. All Rights Reserved.
747     This module is free software. It may be used, redistributed
748     and/or modified under the same terms as Perl itself.