File Coverage

inc/Spiffy.pm
Criterion Covered Total %
statement 288 440 65.4
branch 114 204 55.8
condition 38 62 61.2
subroutine 38 61 62.3
pod 8 27 29.6
total 486 794 61.2


line stmt bran cond sub pod time code
1             ##
2             # name: Spiffy
3             # abstract: Spiffy Perl Interface Framework For You
4             # author: Ingy döt Net
5             # license: perl
6             # copyright: 2004, 2006, 2011, 2012
7              
8             package Spiffy;
9 21     21   6379 use strict;
  21         55  
  21         997  
10 21     21   2589 use 5.006001;
  21         77  
  21         799  
11 21     21   149 use warnings;
  21         47  
  21         853  
12 21     21   189 use Carp;
  21         40  
  21         13987  
13             require Exporter;
14             our $VERSION = '0.31';
15             our @EXPORT = ();
16             our @EXPORT_BASE = qw(field const stub super);
17             our @EXPORT_OK = (@EXPORT_BASE, qw(id WWW XXX YYY ZZZ));
18             our %EXPORT_TAGS = (XXX => [qw(WWW XXX YYY ZZZ)]);
19              
20             my $stack_frame = 0;
21             my $dump = 'yaml';
22             my $bases_map = {};
23              
24             sub WWW; sub XXX; sub YYY; sub ZZZ;
25              
26             # This line is here to convince "autouse" into believing we are autousable.
27             sub can {
28 392 50 33 392 0 4589 ($_[1] eq 'import' and caller()->isa('autouse'))
29             ? \&Exporter::import # pacify autouse's equality test
30             : $_[0]->SUPER::can($_[1]) # normal case
31             }
32              
33             # TODO
34             #
35             # Exported functions like field and super should be hidden so as not to
36             # be confused with methods that can be inherited.
37             #
38              
39             sub new {
40 233     233 0 346 my $class = shift;
41 233   33     895 $class = ref($class) || $class;
42 233         626 my $self = bless {}, $class;
43 233         748 while (@_) {
44 0         0 my $method = shift;
45 0         0 $self->$method(shift);
46             }
47 233         761 return $self;
48             }
49              
50             my $filtered_files = {};
51             my $filter_dump = 0;
52             my $filter_save = 0;
53             our $filter_result = '';
54             sub import {
55 21     21   146 no strict 'refs';
  21         53  
  21         706  
56 21     21   105 no warnings;
  21         44  
  21         34392  
57 126     126   294 my $self_package = shift;
58              
59             # XXX Using parse_arguments here might cause confusion, because the
60             # subclass's boolean_arguments and paired_arguments can conflict, causing
61             # difficult debugging. Consider using something truly local.
62 126         259 my ($args, @export_list) = do {
63             local *boolean_arguments = sub {
64 126     126   526 qw(
65             -base -Base -mixin -selfless
66             -XXX -dumper -yaml
67             -filter_dump -filter_save
68             )
69 126         761 };
70 126     126   524 local *paired_arguments = sub { qw(-package) };
  126         331  
71 126         1099 $self_package->parse_arguments(@_);
72             };
73 126 50       639 return spiffy_mixin_import(scalar(caller(0)), $self_package, @export_list)
74             if $args->{-mixin};
75              
76 126 50       372 $filter_dump = 1 if $args->{-filter_dump};
77 126 50       372 $filter_save = 1 if $args->{-filter_save};
78 126 50       360 $dump = 'yaml' if $args->{-yaml};
79 126 50       343 $dump = 'dumper' if $args->{-dumper};
80              
81 126         531 local @EXPORT_BASE = @EXPORT_BASE;
82              
83 126 50       729 if ($args->{-XXX}) {
84 0 0       0 push @EXPORT_BASE, @{$EXPORT_TAGS{XXX}}
  0         0  
85             unless grep /^XXX$/, @EXPORT_BASE;
86             }
87              
88             spiffy_filter()
89 126 100 66     1576 if ($args->{-selfless} or $args->{-Base}) and
      66        
90             not $filtered_files->{(caller($stack_frame))[1]}++;
91              
92 126   33     1683 my $caller_package = $args->{-package} || caller($stack_frame);
93 126 100 66     737 push @{"$caller_package\::ISA"}, $self_package
  63         1300  
94             if $args->{-Base} or $args->{-base};
95              
96 126         250 for my $class (@{all_my_bases($self_package)}) {
  126         431  
97 189 50       3494 next unless $class->isa('Spiffy');
98 2394         12620 my @export = grep {
99 2394         2398 not defined &{"$caller_package\::$_"};
  189         1737  
100 84         341 } ( @{"$class\::EXPORT"},
101             ($args->{-Base} or $args->{-base})
102 189 100 66     308 ? @{"$class\::EXPORT_BASE"} : (),
103             );
104 1134         4552 my @export_ok = grep {
105 1134         1760 not defined &{"$caller_package\::$_"};
  189         687  
106 189         278 } @{"$class\::EXPORT_OK"};
107              
108             # Avoid calling the expensive Exporter::export
109             # if there is nothing to do (optimization)
110 189         373 my %exportable = map { ($_, 1) } @export, @export_ok;
  3192         5600  
111 189 100       835 next unless keys %exportable;
112              
113 168         263 my @export_save = @{"$class\::EXPORT"};
  168         726  
114 168         215 my @export_ok_save = @{"$class\::EXPORT_OK"};
  168         589  
115 168         256 @{"$class\::EXPORT"} = @export;
  168         982  
116 168         431 @{"$class\::EXPORT_OK"} = @export_ok;
  168         618  
117 122         415 my @list = grep {
118 168         342 (my $v = $_) =~ s/^[\!\:]//;
119 122 100       581 $exportable{$v} or ${"$class\::EXPORT_TAGS"}{$v};
  80         539  
120             } @export_list;
121 168         25964 Exporter::export($class, $caller_package, @list);
122 168         349 @{"$class\::EXPORT"} = @export_save;
  168         932  
123 168         322 @{"$class\::EXPORT_OK"} = @export_ok_save;
  168         23487  
124             }
125             }
126              
127             sub spiffy_filter {
128 63     63 0 34744 require Filter::Util::Call;
129 63         45169 my $done = 0;
130             Filter::Util::Call::filter_add(
131             sub {
132 84 100   84   7464 return 0 if $done;
133 63         148 my ($data, $end) = ('', '');
134 63         941 while (my $status = Filter::Util::Call::filter_read()) {
135 22008 50       37693 return $status if $status < 0;
136 22008 100       44076 if (/^__(?:END|DATA)__\r?$/) {
137 42         118 $end = $_;
138 42         116 last;
139             }
140 21966         35420 $data .= $_;
141 21966         91687 $_ = '';
142             }
143 63         1555 $_ = $data;
144 63         106 my @my_subs;
145 63         9747 s[^(sub\s+\w+\s+\{)(.*\n)]
146             [${1}my \$self = shift;$2]gm;
147 63         5305 s[^(sub\s+\w+)\s*\(\s*\)(\s+\{.*\n)]
148             [${1}${2}]gm;
149 63         3431 s[^my\s+sub\s+(\w+)(\s+\{)(.*)((?s:.*?\n))\}\n]
150 0         0 [push @my_subs, $1; "\$$1 = sub$2my \$self = shift;$3$4\};\n"]gem;
  0         0  
151 63         154 my $preclare = '';
152 63 50       230 if (@my_subs) {
153 0         0 $preclare = join ',', map "\$$_", @my_subs;
154 0         0 $preclare = "my($preclare);";
155             }
156 63         1694 $_ = "use strict;use warnings;$preclare${_};1;\n$end";
157 63 50       542 if ($filter_dump) { print; exit }
  0         0  
  0         0  
158 63 50       203 if ($filter_save) { $filter_result = $_; $_ = $filter_result; }
  0         0  
  0         0  
159 63         3441 $done = 1;
160             }
161 63         624 );
162             }
163              
164             sub base {
165 0     0 0 0 push @_, -base;
166 0         0 goto &import;
167             }
168              
169             sub all_my_bases {
170 168     168 0 285 my $class = shift;
171              
172 168 100       887 return $bases_map->{$class}
173             if defined $bases_map->{$class};
174              
175 63         155 my @bases = ($class);
176 21     21   166 no strict 'refs';
  21         48  
  21         7753  
177 63         134 for my $base_class (@{"${class}::ISA"}) {
  63         425  
178 42         80 push @bases, @{all_my_bases($base_class)};
  42         159  
179             }
180 63         249 my $used = {};
181 63         160 $bases_map->{$class} = [grep {not $used->{$_}++} @bases];
  126         660  
182             }
183              
184             my %code = (
185             sub_start =>
186             "sub {\n",
187             set_default =>
188             " \$_[0]->{%s} = %s\n unless exists \$_[0]->{%s};\n",
189             init =>
190             " return \$_[0]->{%s} = do { my \$self = \$_[0]; %s }\n" .
191             " unless \$#_ > 0 or defined \$_[0]->{%s};\n",
192             weak_init =>
193             " return do {\n" .
194             " \$_[0]->{%s} = do { my \$self = \$_[0]; %s };\n" .
195             " Scalar::Util::weaken(\$_[0]->{%s}) if ref \$_[0]->{%s};\n" .
196             " \$_[0]->{%s};\n" .
197             " } unless \$#_ > 0 or defined \$_[0]->{%s};\n",
198             return_if_get =>
199             " return \$_[0]->{%s} unless \$#_ > 0;\n",
200             set =>
201             " \$_[0]->{%s} = \$_[1];\n",
202             weaken =>
203             " Scalar::Util::weaken(\$_[0]->{%s}) if ref \$_[0]->{%s};\n",
204             sub_end =>
205             " return \$_[0]->{%s};\n}\n",
206             );
207              
208             sub field {
209 378     378 1 851 my $package = caller;
210 378         1568 my ($args, @values) = do {
211 21     21   311 no warnings;
  21         36  
  21         10092  
212 378     378   1613 local *boolean_arguments = sub { (qw(-weak)) };
  378         734  
213 378     378   1805 local *paired_arguments = sub { (qw(-package -init)) };
  378         852  
214 378         1274 Spiffy->parse_arguments(@_);
215             };
216 378         885 my ($field, $default) = @values;
217 378 50       1302 $package = $args->{-package} if defined $args->{-package};
218 378 50 66     1364 die "Cannot have a default for a weakened field ($field)"
219             if defined $default && $args->{-weak};
220 378 50       573 return if defined &{"${package}::$field"};
  378         2300  
221 378 50       1170 require Scalar::Util if $args->{-weak};
222 378 100 100     2433 my $default_string =
    100 66        
223             ( ref($default) eq 'ARRAY' and not @$default )
224             ? '[]'
225             : (ref($default) eq 'HASH' and not keys %$default )
226             ? '{}'
227             : default_as_code($default);
228              
229 378         780 my $code = $code{sub_start};
230 378 100       1147 if ($args->{-init}) {
231 84 50       304 my $fragment = $args->{-weak} ? $code{weak_init} : $code{init};
232 84         448 $code .= sprintf $fragment, $field, $args->{-init}, ($field) x 4;
233             }
234 378 100       1582 $code .= sprintf $code{set_default}, $field, $default_string, $field
235             if defined $default;
236 378         1154 $code .= sprintf $code{return_if_get}, $field;
237 378         2005 $code .= sprintf $code{set}, $field;
238 378 50       923 $code .= sprintf $code{weaken}, $field, $field
239             if $args->{-weak};
240 378         983 $code .= sprintf $code{sub_end}, $field;
241              
242 378 100 100 35   56326 my $sub = eval $code;
  35 100 100     211  
  26 100 100     152  
  14 100 100     66  
  51 100       479  
  52 100       624  
  20 100       75  
  18 100       87  
  52 100       404  
  32 100       241  
  13 100       74  
  31 100       203  
  42 100       187  
  33 100       146  
  41 100       254  
  26 100       125  
  33 100       163  
  29 100       108  
  23 100       114  
  24 100       192  
  12 100       55  
  20 100       188  
  35 100       207  
  17 100       79  
  13 100       95  
  40 100       140  
  43 100       149  
  35 100       91  
  25 100       114  
  32 100       137  
  96         750  
  35         148  
  84         773  
  26         161  
  47         295  
  36         261  
  52         328  
  23         220  
  21         165  
  37         166  
  36         154  
  35         144  
  24         118  
  19         75  
  51         451  
  53         358  
  30         182  
  19         150  
  26         140  
  43         306  
  25         88  
  27         141  
  21         118  
  17         112  
  13         104  
  47         180  
  50         240  
  42         173  
  19         228  
  24         123  
  28         152  
  21         110  
  17         94  
  41         335  
  9         54  
  29         237  
  26         190  
  10         56  
  24         168  
  31         228  
  9         26  
  17         152  
  33         190  
  13         41  
  13         32  
243 378 50       1109 die $@ if $@;
244 21     21   128 no strict 'refs';
  21         48  
  21         5712  
245 378         424 *{"${package}::$field"} = $sub;
  378         3545  
246 378 50       1812 return $code if defined wantarray;
247             }
248              
249             sub default_as_code {
250 315     315 0 31684 require Data::Dumper;
251 315         339318 local $Data::Dumper::Sortkeys = 1;
252 315         1080 my $code = Data::Dumper::Dumper(shift);
253 315         20752 $code =~ s/^\$VAR1 = //;
254 315         901 $code =~ s/;$//;
255 315         1889 return $code;
256             }
257              
258             sub const {
259 0     0 1 0 my $package = caller;
260 0         0 my ($args, @values) = do {
261 21     21   171 no warnings;
  21         48  
  21         2807  
262 0     0   0 local *paired_arguments = sub { (qw(-package)) };
  0         0  
263 0         0 Spiffy->parse_arguments(@_);
264             };
265 0         0 my ($field, $default) = @values;
266 0 0       0 $package = $args->{-package} if defined $args->{-package};
267 21     21   153 no strict 'refs';
  21         34  
  21         4528  
268 0 0       0 return if defined &{"${package}::$field"};
  0         0  
269 0     0   0 *{"${package}::$field"} = sub { $default }
  0         0  
270 0         0 }
271              
272             sub stub {
273 0     0 1 0 my $package = caller;
274 0         0 my ($args, @values) = do {
275 21     21   115 no warnings;
  21         29  
  21         2521  
276 0     0   0 local *paired_arguments = sub { (qw(-package)) };
  0         0  
277 0         0 Spiffy->parse_arguments(@_);
278             };
279 0         0 my ($field, $default) = @values;
280 0 0       0 $package = $args->{-package} if defined $args->{-package};
281 21     21   116 no strict 'refs';
  21         30  
  21         16074  
282 0 0       0 return if defined &{"${package}::$field"};
  0         0  
283 0         0 *{"${package}::$field"} =
284             sub {
285 0     0   0 require Carp;
286 0         0 Carp::confess
287             "Method $field in package $package must be subclassed";
288             }
289 0         0 }
290              
291             sub parse_arguments {
292 504     504 1 795 my $class = shift;
293 504         1096 my ($args, @values) = ({}, ());
294 504         1574 my %booleans = map { ($_, 1) } $class->boolean_arguments;
  1512         4467  
295 504         2208 my %pairs = map { ($_, 1) } $class->paired_arguments;
  882         2473  
296 504         1592 while (@_) {
297 775         1198 my $elem = shift;
298 775 100 66     7113 if (defined $elem and defined $booleans{$elem}) {
    100 66        
      66        
299 63 50 33     432 $args->{$elem} = (@_ and $_[0] =~ /^[01]$/)
300             ? shift
301             : 1;
302             }
303             elsif (defined $elem and defined $pairs{$elem} and @_) {
304 84         339 $args->{$elem} = shift;
305             }
306             else {
307 628         14873 push @values, $elem;
308             }
309             }
310 504 50       7378 return wantarray ? ($args, @values) : $args;
311             }
312              
313 0     0 1 0 sub boolean_arguments { () }
314 0     0 1 0 sub paired_arguments { () }
315              
316             # get a unique id for any node
317             sub id {
318 0 0   0 0 0 if (not ref $_[0]) {
319 0 0       0 return 'undef' if not defined $_[0];
320 0 0       0 \$_[0] =~ /\((\w+)\)$/o or die;
321 0         0 return "$1-S";
322             }
323 0         0 require overload;
324 0 0       0 overload::StrVal($_[0]) =~ /\((\w+)\)$/o or die;
325 0         0 return $1;
326             }
327              
328             #===============================================================================
329             # It's super, man.
330             #===============================================================================
331             package DB;
332             {
333 21     21   124 no warnings 'redefine';
  21         51  
  21         5874  
334             sub super_args {
335 0 0   0 0 0 my @dummy = caller(@_ ? $_[0] : 2);
336 0         0 return @DB::args;
337             }
338             }
339              
340             package Spiffy;
341             sub super {
342 0     0 1 0 my $method;
343 0         0 my $frame = 1;
344 0         0 while ($method = (caller($frame++))[3]) {
345 0 0       0 $method =~ s/.*::// and last;
346             }
347 0         0 my @args = DB::super_args($frame);
348 0 0       0 @_ = @_ ? ($args[0], @_) : @args;
349 0 0       0 my $class = ref $_[0] ? ref $_[0] : $_[0];
350 0         0 my $caller_class = caller;
351 0         0 my $seen = 0;
352 0 0 0     0 my @super_classes = reverse grep {
353 0         0 ($seen or $seen = ($_ eq $caller_class)) ? 0 : 1;
354 0         0 } reverse @{all_my_bases($class)};
355 0         0 for my $super_class (@super_classes) {
356 21     21   117 no strict 'refs';
  21         39  
  21         17880  
357 0 0       0 next if $super_class eq $class;
358 0 0       0 if (defined &{"${super_class}::$method"}) {
  0         0  
359 0 0       0 ${"$super_class\::AUTOLOAD"} = ${"$class\::AUTOLOAD"}
  0         0  
  0         0  
360             if $method eq 'AUTOLOAD';
361 0         0 return &{"${super_class}::$method"};
  0         0  
362             }
363             }
364 0         0 return;
365             }
366              
367             #===============================================================================
368             # This code deserves a spanking, because it is being very naughty.
369             # It is exchanging base.pm's import() for its own, so that people
370             # can use base.pm with Spiffy modules, without being the wiser.
371             #===============================================================================
372             my $real_base_import;
373             my $real_mixin_import;
374              
375             BEGIN {
376 21 50   21   139 require base unless defined $INC{'base.pm'};
377 21   50     482 $INC{'mixin.pm'} ||= 'Spiffy/mixin.pm';
378 21         48 $real_base_import = \&base::import;
379 21         103 $real_mixin_import = \&mixin::import;
380 21     21   127 no warnings;
  21         36  
  21         7718  
381 21         221 *base::import = \&spiffy_base_import;
382 21         1093 *mixin::import = \&spiffy_mixin_import;
383             }
384              
385             # my $i = 0;
386             # while (my $caller = caller($i++)) {
387             # next unless $caller eq 'base' or $caller eq 'mixin';
388             # croak <
389             # Spiffy.pm must be loaded before calling 'use base' or 'use mixin' with a
390             # Spiffy module. See the documentation of Spiffy.pm for details.
391             # END
392             # }
393              
394             sub spiffy_base_import {
395 210     210 0 415782 my @base_classes = @_;
396 210         403 shift @base_classes;
397 21     21   115 no strict 'refs';
  21         35  
  21         9712  
398 210         4136 goto &$real_base_import
399             unless grep {
400 210 100       520 eval "require $_" unless %{"$_\::"};
  210 50       313  
401 210         1004569 $_->isa('Spiffy');
402             } @base_classes;
403 0           my $inheritor = caller(0);
404 0           for my $base_class (@base_classes) {
405 0 0         next if $inheritor->isa($base_class);
406 0 0         croak "Can't mix Spiffy and non-Spiffy classes in 'use base'.\n",
407             "See the documentation of Spiffy.pm for details\n "
408             unless $base_class->isa('Spiffy');
409 0           $stack_frame = 1; # tell import to use different caller
410 0           import($base_class, '-base');
411 0           $stack_frame = 0;
412             }
413             }
414              
415             sub mixin {
416 0     0 1   my $self = shift;
417 0           my $target_class = ref($self);
418 0           spiffy_mixin_import($target_class, @_)
419             }
420              
421             sub spiffy_mixin_import {
422 0     0 0   my $target_class = shift;
423 0 0         $target_class = caller(0)
424             if $target_class eq 'mixin';
425 0 0         my $mixin_class = shift
426             or die "Nothing to mixin";
427 0           eval "require $mixin_class";
428 0           my @roles = @_;
429 0           my $pseudo_class = join '-', $target_class, $mixin_class, @roles;
430 0           my %methods = spiffy_mixin_methods($mixin_class, @roles);
431 21     21   152 no strict 'refs';
  21         53  
  21         695  
432 21     21   108 no warnings;
  21         41  
  21         3835  
433 0           @{"$pseudo_class\::ISA"} = @{"$target_class\::ISA"};
  0            
  0            
434 0           @{"$target_class\::ISA"} = ($pseudo_class);
  0            
435 0           for (keys %methods) {
436 0           *{"$pseudo_class\::$_"} = $methods{$_};
  0            
437             }
438             }
439              
440             sub spiffy_mixin_methods {
441 0     0 0   my $mixin_class = shift;
442 21     21   115 no strict 'refs';
  21         54  
  21         10866  
443 0           my %methods = spiffy_all_methods($mixin_class);
444 0           map {
445 0 0         $methods{$_}
446 0           ? ($_, \ &{"$methods{$_}\::$_"})
447 0 0         : ($_, \ &{"$mixin_class\::$_"})
448             } @_
449             ? (get_roles($mixin_class, @_))
450             : (keys %methods);
451             }
452              
453             sub get_roles {
454 0     0 0   my $mixin_class = shift;
455 0           my @roles = @_;
456 0           while (grep /^!*:/, @roles) {
457 0           @roles = map {
458 0           s/!!//g;
459             /^!:(.*)/ ? do {
460 0           my $m = "_role_$1";
461 0           map("!$_", $mixin_class->$m);
462             } :
463 0 0         /^:(.*)/ ? do {
    0          
464 0           my $m = "_role_$1";
465 0           ($mixin_class->$m);
466             } :
467             ($_)
468             } @roles;
469             }
470 0 0 0       if (@roles and $roles[0] =~ /^!/) {
471 0           my %methods = spiffy_all_methods($mixin_class);
472 0           unshift @roles, keys(%methods);
473             }
474 0           my %roles;
475 0           for (@roles) {
476 0           s/!!//g;
477 0 0         delete $roles{$1}, next
478             if /^!(.*)/;
479 0           $roles{$_} = 1;
480             }
481 0           keys %roles;
482             }
483              
484             sub spiffy_all_methods {
485 21     21   148 no strict 'refs';
  21         42  
  21         5143  
486 0     0 0   my $class = shift;
487 0 0         return if $class eq 'Spiffy';
488 0           my %methods = map {
489 0           ($_, $class)
490             } grep {
491 0 0         defined &{"$class\::$_"} and not /^_/
  0            
492 0           } keys %{"$class\::"};
493 0           my %super_methods;
494 0           %super_methods = spiffy_all_methods(${"$class\::ISA"}[0])
  0            
495 0 0         if @{"$class\::ISA"};
496 0           %{{%super_methods, %methods}};
  0            
497             }
498              
499              
500             # END of naughty code.
501             #===============================================================================
502             # Debugging support
503             #===============================================================================
504             sub spiffy_dump {
505 21     21   121 no warnings;
  21         180  
  21         13134  
506 0 0   0 0   if ($dump eq 'dumper') {
507 0           require Data::Dumper;
508 0           $Data::Dumper::Sortkeys = 1;
509 0           $Data::Dumper::Indent = 1;
510 0           return Data::Dumper::Dumper(@_);
511             }
512 0           require YAML;
513 0           $YAML::UseVersion = 0;
514 0           return YAML::Dump(@_) . "...\n";
515             }
516              
517             sub at_line_number {
518 0     0 0   my ($file_path, $line_number) = (caller(1))[1,2];
519 0           " at $file_path line $line_number\n";
520             }
521              
522             sub WWW {
523 0     0 0   warn spiffy_dump(@_) . at_line_number;
524 0 0         return wantarray ? @_ : $_[0];
525             }
526              
527             sub XXX {
528 0     0 0   die spiffy_dump(@_) . at_line_number;
529             }
530              
531             sub YYY {
532 0     0 0   print spiffy_dump(@_) . at_line_number;
533 0 0         return wantarray ? @_ : $_[0];
534             }
535              
536             sub ZZZ {
537 0     0 0   require Carp;
538 0           Carp::confess spiffy_dump(@_);
539             }
540              
541             1;
542              
543             =head1 SYNOPSIS
544              
545             package Keen;
546             use Spiffy -Base;
547             field 'mirth';
548             const mood => ':-)';
549              
550             sub happy {
551             if ($self->mood eq ':-(') {
552             $self->mirth(-1);
553             print "Cheer up!";
554             }
555             super;
556             }
557              
558             =head1 DESCRIPTION
559              
560             "Spiffy" is a framework and methodology for doing object oriented (OO)
561             programming in Perl. Spiffy combines the best parts of Exporter.pm, base.pm,
562             mixin.pm and SUPER.pm into one magic foundation class. It attempts to fix all
563             the nits and warts of traditional Perl OO, in a clean, straightforward and
564             (perhaps someday) standard way.
565              
566             Spiffy borrows ideas from other OO languages like Python, Ruby, Java and Perl
567             6. It also adds a few tricks of its own.
568              
569             If you take a look on CPAN, there are a ton of OO related modules. When
570             starting a new project, you need to pick the set of modules that makes most
571             sense, and then you need to use those modules in each of your classes. Spiffy,
572             on the other hand, has everything you'll probably need in one module, and you
573             only need to use it once in one of your classes. If you make Spiffy.pm the
574             base class of the basest class in your project, Spiffy will automatically pass
575             all of its magic to all of your subclasses. You may eventually forget that
576             you're even using it!
577              
578             The most striking difference between Spiffy and other Perl object oriented
579             base classes, is that it has the ability to export things. If you create a
580             subclass of Spiffy, all the things that Spiffy exports will automatically be
581             exported by your subclass, in addition to any more things that you want to
582             export. And if someone creates a subclass of your subclass, all of those
583             things will be exported automatically, and so on. Think of it as "Inherited
584             Exportation", and it uses the familiar Exporter.pm specification syntax.
585              
586             To use Spiffy or any subclass of Spiffy as a base class of your class, you
587             specify the C<-base> argument to the C command.
588              
589             use MySpiffyBaseModule -base;
590              
591             You can also use the traditional C syntax and
592             everything will work exactly the same. The only caveat is that Spiffy.pm must
593             already be loaded. That's because Spiffy rewires base.pm on the fly to do all
594             the Spiffy magics.
595              
596             Spiffy has support for Ruby-like mixins with Perl6-like roles. Just like
597             C you can use either of the following invocations:
598              
599             use mixin 'MySpiffyBaseModule';
600             use MySpiffyBaseModule -mixin;
601              
602             The second version will only work if the class being mixed in is a subclass of
603             Spiffy. The first version will work in all cases, as long as Spiffy has
604             already been loaded.
605              
606             To limit the methods that get mixed in, use roles. (Hint: they work just like
607             an Exporter list):
608              
609             use MySpiffyBaseModule -mixin => qw(:basics x y !foo);
610              
611             In object oriented Perl almost every subroutine is a method. Each method gets
612             the object passed to it as its first argument. That means practically every
613             subroutine starts with the line:
614              
615             my $self = shift;
616              
617             Spiffy provides a simple, optional filter mechanism to insert that line for
618             you, resulting in cleaner code. If you figure an average method has 10 lines
619             of code, that's 10% of your code! To turn this option on, you just use the
620             C<-Base> option instead of the C<-base> option, or add the C<-selfless>
621             option. If source filtering makes you queazy, don't use the feature. I
622             personally find it addictive in my quest for writing squeaky clean,
623             maintainable code.
624              
625             A useful feature of Spiffy is that it exports two functions: C and
626             C that can be used to declare the attributes of your class, and
627             automatically generate accessor methods for them. The only difference between
628             the two functions is that C attributes can not be modified; thus the
629             accessor is much faster.
630              
631             One interesting aspect of OO programming is when a method calls the same
632             method from a parent class. This is generally known as calling a super method.
633             Perl's facility for doing this is butt ugly:
634              
635             sub cleanup {
636             my $self = shift;
637             $self->scrub;
638             $self->SUPER::cleanup(@_);
639             }
640              
641             Spiffy makes it, er, super easy to call super methods. You just use the
642             C function. You don't need to pass it any arguments because it
643             automatically passes them on for you. Here's the same function with Spiffy:
644              
645             sub cleanup {
646             $self->scrub;
647             super;
648             }
649              
650             Spiffy has a special method for parsing arguments called C,
651             that it also uses for parsing its own arguments. You declare which arguments
652             are boolean (singletons) and which ones are paired, with two special methods
653             called C and C. Parse arguments pulls out
654             the booleans and pairs and returns them in an anonymous hash, followed by a
655             list of the unmatched arguments.
656              
657             Finally, Spiffy can export a few debugging functions C, C, C
658             and C. Each of them produces a YAML dump of its arguments. WWW warns the
659             output, XXX dies with the output, YYY prints the output, and ZZZ confesses the
660             output. If YAML doesn't suit your needs, you can switch all the dumps to
661             Data::Dumper format with the C<-dumper> option.
662              
663             That's Spiffy!
664              
665             =head1 Spiffy EXPORTING
666              
667             Spiffy implements a completely new idea in Perl. Modules that act both as
668             object oriented classes and that also export functions. But it takes the
669             concept of Exporter.pm one step further; it walks the entire C<@ISA> path of a
670             class and honors the export specifications of each module. Since Spiffy calls
671             on the Exporter module to do this, you can use all the fancy interface
672             features that Exporter has, including tags and negation.
673              
674             Spiffy considers all the arguments that don't begin with a dash to comprise
675             the export specification.
676              
677             package Vehicle;
678             use Spiffy -base;
679             our $SERIAL_NUMBER = 0;
680             our @EXPORT = qw($SERIAL_NUMBER);
681             our @EXPORT_BASE = qw(tire horn);
682              
683             package Bicycle;
684             use Vehicle -base, '!field';
685             $self->inflate(tire);
686              
687             In this case, Cisa('Vehicle')> and also all the things that
688             C and C export, will go into C, except C.
689              
690             Exporting can be very helpful when you've designed a system with hundreds of
691             classes, and you want them all to have access to some functions or constants
692             or variables. Just export them in your main base class and every subclass
693             will get the functions they need.
694              
695             You can do almost everything that Exporter does because Spiffy delegates the
696             job to Exporter (after adding some Spiffy magic). Spiffy offers a
697             C<@EXPORT_BASE> variable which is like C<@EXPORT>, but only for usages that
698             use C<-base>.
699              
700             =head1 Spiffy MIXINs & ROLEs
701              
702             If you've done much OO programming in Perl you've probably used Multiple
703             Inheritance (MI), and if you've done much MI you've probably run into weird
704             problems and headaches. Some languages like Ruby, attempt to resolve MI issues
705             using a technique called mixins. Basically, all Ruby classes use only Single
706             Inheritance (SI), and then I functionality from other modules if they
707             need to.
708              
709             Mixins can be thought of at a simplistic level as I the methods of
710             another class into your subclass. But from an implementation standpoint that's
711             not the best way to do it. Spiffy does what Ruby does. It creates an empty
712             anonymous class, imports everything into that class, and then chains the new
713             class into your SI ISA path. In other words, if you say:
714              
715             package AAA;
716             use BBB -base;
717             use CCC -mixin;
718             use DDD -mixin;
719              
720             You end up with a single inheritance chain of classes like this:
721              
722             AAA << AAA-DDD << AAA-CCC << BBB;
723              
724             C and C are the actual package names of the generated
725             classes. The nice thing about this style is that mixing in CCC doesn't clobber
726             any methods in AAA, and DDD doesn't conflict with AAA or CCC either. If you
727             mixed in a method in CCC that was also in AAA, you can still get to it by
728             using C.
729              
730             When Spiffy mixes in CCC, it pulls in all the methods in CCC that do not begin
731             with an underscore. Actually it goes farther than that. If CCC is a subclass
732             it will pull in every method that CCC C do through inheritance. This is
733             very powerful, maybe too powerful.
734              
735             To limit what you mixin, Spiffy borrows the concept of Roles from Perl6. The
736             term role is used more loosely in Spiffy though. It's much like an import list
737             that the Exporter module uses, and you can use groups (tags) and negation. If
738             the first element of your list uses negation, Spiffy will start with all the
739             methods that your mixin class can do.
740              
741             use EEE -mixin => qw(:tools walk !run !:sharp_tools);
742              
743             In this example, C and C are methods that EEE can do, and C
744             and C are roles of class EEE. How does class EEE define these
745             roles? It very simply defines methods called C<_role_tools> and
746             C<_role_sharp_tools> which return lists of more methods. (And possibly other
747             roles!) The neat thing here is that since roles are just methods, they too can
748             be inherited. Take B Perl6!
749              
750             =head1 Spiffy FILTERING
751              
752             By using the C<-Base> flag instead of C<-base> you never need to write the
753             line:
754              
755             my $self = shift;
756              
757             This statement is added to every subroutine in your class by using a source
758             filter. The magic is simple and fast, so there is litte performance penalty
759             for creating clean code on par with Ruby and Python.
760              
761             package Example;
762             use Spiffy -Base;
763              
764             sub crazy {
765             $self->nuts;
766             }
767             sub wacky { }
768             sub new() {
769             bless [], shift;
770             }
771              
772             is exactly the same as:
773              
774             package Example;
775             use Spiffy -base;
776             use strict;use warnings;
777             sub crazy {my $self = shift;
778             $self->nuts;
779             }
780             sub wacky {my $self = shift; }
781             sub new {
782             bless [], shift;
783             }
784             ;1;
785              
786             Note that the empty parens after the subroutine C keep it from having a
787             $self added. Also note that the extra code is added to existing lines to
788             ensure that line numbers are not altered.
789              
790             C<-Base> also turns on the strict and warnings pragmas, and adds that annoying
791             '1;' line to your module.
792              
793             =head1 PRIVATE METHODS
794              
795             Spiffy now has support for private methods when you use the '-Base' filter
796             mechanism. You just declare the subs with the C keyword, and call them
797             with a C<'$'> in front. Like this:
798              
799             package Keen;
800             use SomethingSpiffy -Base;
801              
802             # normal public method
803             sub swell {
804             $self->$stinky;
805             }
806              
807             # private lexical method. uncallable from outside this file.
808             my sub stinky {
809             ...
810             }
811              
812             =head1 Spiffy DEBUGGING
813              
814             The XXX function is very handy for debugging because you can insert it almost
815             anywhere, and it will dump your data in nice clean YAML. Take the following
816             statement:
817              
818             my @stuff = grep { /keen/ } $self->find($a, $b);
819              
820             If you have a problem with this statement, you can debug it in any of the
821             following ways:
822              
823             XXX my @stuff = grep { /keen/ } $self->find($a, $b);
824             my @stuff = XXX grep { /keen/ } $self->find($a, $b);
825             my @stuff = grep { /keen/ } XXX $self->find($a, $b);
826             my @stuff = grep { /keen/ } $self->find(XXX $a, $b);
827              
828             XXX is easy to insert and remove. It is also a tradition to mark uncertain
829             areas of code with XXX. This will make the debugging dumpers easy to spot if
830             you forget to take them out.
831              
832             WWW and YYY are nice because they dump their arguments and then return the
833             arguments. This way you can insert them into many places and still have the
834             code run as before. Use ZZZ when you need to die with both a YAML dump and a
835             full stack trace.
836              
837             The debugging functions are exported by default if you use the C<-base>
838             option, but only if you have previously used the C<-XXX> option. To export all
839             4 functions use the export tag:
840              
841             use SomeSpiffyModule ':XXX';
842              
843             To force the debugging functions to use Data::Dumper instead of YAML:
844              
845             use SomeSpiffyModule -dumper;
846              
847             =head1 Spiffy FUNCTIONS
848              
849             This section describes the functions the Spiffy exports. The C,
850             C, C and C functions are only exported when you use the
851             C<-base> or C<-Base> options.
852              
853             =over 4
854              
855             =item * field
856              
857             Defines accessor methods for a field of your class:
858              
859             package Example;
860             use Spiffy -Base;
861              
862             field 'foo';
863             field bar => [];
864              
865             sub lalala {
866             $self->foo(42);
867             push @{$self->{bar}}, $self->foo;
868             }
869              
870             The first parameter passed to C is the name of the attribute being
871             defined. Accessors can be given an optional default value. This value will be
872             returned if no value for the field has been set in the object.
873              
874             =item * const
875              
876             const bar => 42;
877              
878             The C function is similar to except that it is immutable. It
879             also does not store data in the object. You probably always want to give a
880             C a default value, otherwise the generated method will be somewhat
881             useless.
882              
883             =item * stub
884              
885             stub 'cigar';
886              
887             The C function generates a method that will die with an appropriate
888             message. The idea is that subclasses must implement these methods so that the
889             stub methods don't get called.
890              
891             =item * super
892              
893             If this function is called without any arguments, it will call the same method
894             that it is in, higher up in the ISA tree, passing it all the same arguments.
895             If it is called with arguments, it will use those arguments with C<$self> in
896             the front. In other words, it just works like you'd expect.
897              
898             sub foo {
899             super; # Same as $self->SUPER::foo(@_);
900             super('hello'); # Same as $self->SUPER::foo('hello');
901             $self->bar(42);
902             }
903              
904             sub new() {
905             my $self = super;
906             $self->init;
907             return $self;
908             }
909              
910             C will simply do nothing if there is no super method. Finally, C
911             does the right thing in AUTOLOAD subroutines.
912              
913             =back
914              
915             =head1 Spiffy METHODS
916              
917             This section lists all of the methods that any subclass of Spiffy
918             automatically inherits.
919              
920             =over 4
921              
922             =item * mixin
923              
924             A method to mixin a class at runtime. Takes the same arguments as C
925             ...>. Makes the target class a mixin of the caller.
926              
927             $self->mixin('SomeClass');
928             $object->mixin('SomeOtherClass' => 'some_method');
929              
930             =item * parse_arguments
931              
932             This method takes a list of arguments and groups them into pairs. It allows
933             for boolean arguments which may or may not have a value (defaulting to 1). The
934             method returns a hash reference of all the pairs as keys and values in the
935             hash. Any arguments that cannot be paired, are returned as a list. Here is an
936             example:
937              
938             sub boolean_arguments { qw(-has_spots -is_yummy) }
939             sub paired_arguments { qw(-name -size) }
940             my ($pairs, @others) = $self->parse_arguments(
941             'red', 'white',
942             -name => 'Ingy',
943             -has_spots =>
944             -size => 'large',
945             'black',
946             -is_yummy => 0,
947             );
948              
949             After this call, C<$pairs> will contain:
950              
951             {
952             -name => 'Ingy',
953             -has_spots => 1,
954             -size => 'large',
955             -is_yummy => 0,
956             }
957              
958             and C<@others> will contain 'red', 'white', and 'black'.
959              
960             =item * boolean_arguments
961              
962             Returns the list of arguments that are recognized as being boolean. Override
963             this method to define your own list.
964              
965             =item * paired_arguments
966              
967             Returns the list of arguments that are recognized as being paired. Override
968             this method to define your own list.
969              
970             =back
971              
972             =head1 Spiffy ARGUMENTS
973              
974             When you C the Spiffy module or a subclass of it, you can pass it a list
975             of arguments. These arguments are parsed using the C method
976             described above. The special argument C<-base>, is used to make the current
977             package a subclass of the Spiffy module being used.
978              
979             Any non-paired parameters act like a normal import list; just like those used
980             with the Exporter module.
981              
982             =head1 USING Spiffy WITH base.pm
983              
984             The proper way to use a Spiffy module as a base class is with the C<-base>
985             parameter to the C statement. This differs from typical modules where you
986             would want to C.
987              
988             package Something;
989             use Spiffy::Module -base;
990             use base 'NonSpiffy::Module';
991              
992             Now it may be hard to keep track of what's Spiffy and what is not. Therefore
993             Spiffy has actually been made to work with base.pm. You can say:
994              
995             package Something;
996             use base 'Spiffy::Module';
997             use base 'NonSpiffy::Module';
998              
999             C is also very useful when your class is not an actual module (a
1000             separate file) but just a package in some file that has already been
1001             loaded. C will work whether the class is a module or not, while the
1002             C<-base> syntax cannot work that way, since C always tries to load a
1003             module.
1004              
1005             =head2 base.pm Caveats
1006              
1007             To make Spiffy work with base.pm, a dirty trick was played. Spiffy swaps
1008             C with its own version. If the base modules are not Spiffy,
1009             Spiffy calls the original base::import. If the base modules are Spiffy, then
1010             Spiffy does its own thing.
1011              
1012             There are two caveats.
1013              
1014             =over 4
1015              
1016             =item * Spiffy must be loaded first.
1017              
1018             If Spiffy is not loaded and C is invoked on a Spiffy module, Spiffy
1019             will die with a useful message telling the author to read this documentation.
1020             That's because Spiffy needed to do the import swap beforehand.
1021              
1022             If you get this error, simply put a statement like this up front in your code:
1023              
1024             use Spiffy ();
1025              
1026             =item * No Mixing
1027              
1028             C can take multiple arguments. And this works with Spiffy as long as
1029             all the base classes are Spiffy, or they are all non-Spiffy. If they are
1030             mixed, Spiffy will die. In this case just use separate C statements.
1031              
1032             =back
1033              
1034             =head1 Spiffy TODO LIST
1035              
1036             Spiffy is a wonderful way to do OO programming in Perl, but it is still a work
1037             in progress. New things will be added, and things that don't work well, might
1038             be removed.