1 package Attribute::Handlers;
10 my ($pkg, $ref, $type) = @_;
11 return $symcache{$pkg,$ref} if $symcache{$pkg,$ref};
14 foreach my $sym ( values %{$pkg."::"} ) {
15 return $symcache{$pkg,$ref} = \$sym
16 if *{$sym}{$type} && *{$sym}{$type} == $ref;
21 VAR => [qw[SCALAR ARRAY HASH]],
22 ANY => [qw[SCALAR ARRAY HASH CODE]],
23 "" => [qw[SCALAR ARRAY HASH CODE]],
24 SCALAR => [qw[SCALAR]],
33 my %sigil = (SCALAR=>'$', ARRAY=>'@', HASH=>'%');
36 croak "Usage: use $_[0] autotie => {AttrName => TieClassName,...}";
41 return unless $class eq "Attribute::Handlers";
44 if ($cmd eq 'autotie') {
46 _usage_AH_ $class unless ref($mapping) eq 'HASH';
47 while (my($attr, $tieclass) = each %$mapping) {
48 $tieclass =~ s/^([_a-z]\w*(::[_a-z]\w*))(.*)/$1/is;
50 usage $class unless $attr =~ m/^[_a-z]\w*(::[_a-z]\w*)*$/i
51 && $tieclass =~ m/^[_a-z]\w*(::[_a-z]\w*)/i
52 && eval "use base $tieclass; 1";
53 if ($tieclass->isa('Exporter')) {
54 local $Exporter::ExportLevel = 2;
55 $tieclass->import(eval $args);
57 $attr =~ s/__CALLER__/caller(1)/e;
58 $attr = caller()."::".$attr unless $attr =~ /::/;
60 sub $attr : ATTR(VAR) {
61 my (\$ref, \$data) = \@_[2,4];
62 \$data = [ \$data ] unless ref \$data eq 'ARRAY';
64 # use Data::Dumper 'Dumper';
65 # print Dumper [ [\$ref, \$data] ];
66 my \$type = ref(\$ref)||"value (".(\$ref||"<undef>").")";
67 (\$type eq 'SCALAR')? tie \$\$ref,'$tieclass',\@\$data
68 :(\$type eq 'ARRAY') ? tie \@\$ref,'$tieclass',\@\$data
69 :(\$type eq 'HASH') ? tie \%\$ref,'$tieclass',\@\$data
70 : die "Can't autotie a \$type\n"
72 } or die "Internal error: $@";
76 croak "Can't understand $_";
80 sub _resolve_lastattr {
81 return unless $lastattr{ref};
82 my $sym = findsym @lastattr{'pkg','ref'}
83 or die "Internal error: $lastattr{pkg} symbol went missing";
84 my $name = *{$sym}{NAME};
85 warn "Declaration of $name attribute in package $lastattr{pkg} may clash with future reserved word\n"
86 if $^W and $name !~ /[A-Z]/;
87 foreach ( @{$validtype{$lastattr{type}}} ) {
88 *{"$lastattr{pkg}::_ATTR_${_}_${name}"} = $lastattr{ref};
95 $AUTOLOAD =~ /_ATTR_(.*?)_(.*)/ or
96 croak "Can't locate class method '$AUTOLOAD' via package '$class'";
97 croak "Attribute handler '$2' doesn't handle $1 attributes";
102 my $builtin = qr/lvalue|method|locked/;
104 sub _gen_handler_AH_() {
107 my ($pkg, $ref, @attrs) = @_;
109 my ($attr, $data) = /^([a-z_]\w*)(?:[(](.*)[)])?$/i or next;
110 if ($attr eq 'ATTR') {
112 $raw{$ref} = $data =~ s/\s*,?\s*RAWDATA\s*,?\s*//;
113 $phase{$ref}{BEGIN} = 1
114 if $data =~ s/\s*,?\s*(BEGIN)\s*,?\s*//;
115 $phase{$ref}{INIT} = 1
116 if $data =~ s/\s*,?\s*(INIT)\s*,?\s*//;
117 $phase{$ref}{END} = 1
118 if $data =~ s/\s*,?\s*(END)\s*,?\s*//;
119 $phase{$ref}{CHECK} = 1
120 if $data =~ s/\s*,?\s*(CHECK)\s*,?\s*//
121 || ! keys %{$phase{$ref}};
122 croak "Can't have two ATTR specifiers on one subroutine"
124 croak "Bad attribute type: ATTR($data)"
125 unless $validtype{$data};
126 %lastattr=(pkg=>$pkg,ref=>$ref,type=>$data);
129 my $handler = $pkg->can($attr);
130 next unless $handler;
131 my $decl = [$pkg, $ref, $attr, $data,
132 $raw{$handler}, $phase{$handler}];
133 _apply_handler_AH_($decl,'BEGIN');
134 push @declarations, $decl;
138 return grep {defined && !/$builtin/} @attrs;
142 *{"MODIFY_${_}_ATTRIBUTES"} = _gen_handler_AH_ foreach @{$validtype{ANY}};
143 push @UNIVERSAL::ISA, 'Attribute::Handlers'
144 unless grep /^Attribute::Handlers$/, @UNIVERSAL::ISA;
146 sub _apply_handler_AH_ {
147 my ($declaration, $phase) = @_;
148 my ($pkg, $ref, $attr, $data, $raw, $handlerphase) = @$declaration;
149 return unless $handlerphase->{$phase};
150 # print STDERR "Handling $attr on $ref in $phase with [$data]\n";
152 my $handler = "_ATTR_${type}_${attr}";
153 my $sym = findsym($pkg, $ref);
154 $sym ||= $type eq 'CODE' ? 'ANON' : 'LEXICAL';
156 my $evaled = !$raw && eval("package $pkg; no warnings;
157 local \$SIG{__WARN__}=sub{die}; [$data]");
158 $data = ($evaled && $data =~ /^\s*\[/) ? [$evaled]
159 : ($evaled) ? $evaled
162 (ref $sym eq 'GLOB' ? *{$sym}{ref $ref}||$ref : $ref),
164 (@$data>1? $data : $data->[0]),
172 _apply_handler_AH_($_,'CHECK') foreach @declarations;
175 INIT { _apply_handler_AH_($_,'INIT') foreach @declarations }
177 END { _apply_handler_AH_($_,'END') foreach @declarations }
184 Attribute::Handlers - Simpler definition of attribute handlers
188 This document describes version 0.70 of Attribute::Handlers,
189 released June 3, 2001.
195 use Attribute::Handlers;
196 no warnings 'redefine';
199 sub Good : ATTR(SCALAR) {
200 my ($package, $symbol, $referent, $attr, $data) = @_;
202 # Invoked for any scalar variable with a :Good attribute,
203 # provided the variable was declared in MyClass (or
204 # a derived class) or typed to MyClass.
206 # Do whatever to $referent here (executed in CHECK phase).
210 sub Bad : ATTR(SCALAR) {
211 # Invoked for any scalar variable with a :Bad attribute,
212 # provided the variable was declared in MyClass (or
213 # a derived class) or typed to MyClass.
217 sub Good : ATTR(ARRAY) {
218 # Invoked for any array variable with a :Good attribute,
219 # provided the variable was declared in MyClass (or
220 # a derived class) or typed to MyClass.
224 sub Good : ATTR(HASH) {
225 # Invoked for any hash variable with a :Good attribute,
226 # provided the variable was declared in MyClass (or
227 # a derived class) or typed to MyClass.
231 sub Ugly : ATTR(CODE) {
232 # Invoked for any subroutine declared in MyClass (or a
233 # derived class) with an :Ugly attribute.
238 # Invoked for any scalar, array, hash, or subroutine
239 # with an :Omni attribute, provided the variable or
240 # subroutine was declared in MyClass (or a derived class)
241 # or the variable was typed to MyClass.
242 # Use ref($_[2]) to determine what kind of referent it was.
247 use Attribute::Handlers autotie => { Cycle => Tie::Cycle };
249 my $next : Cycle(['A'..'Z']);
254 This module, when inherited by a package, allows that package's class to
255 define attribute handler subroutines for specific attributes. Variables
256 and subroutines subsequently defined in that package, or in packages
257 derived from that package may be given attributes with the same names as
258 the attribute handler subroutines, which will then be called in one of
259 the compilation phases (i.e. in a C<BEGIN>, C<CHECK>, C<INIT>, or C<END>
262 To create a handler, define it as a subroutine with the same name as
263 the desired attribute, and declare the subroutine itself with the
264 attribute C<:ATTR>. For example:
267 use Attribute::Handlers;
270 my ($package, $symbol, $referent, $attr, $data, $phase) = @_;
273 *{$symbol}{NAME}, " ",
274 "($referent) ", "was just declared ",
275 "and ascribed the ${attr} attribute ",
276 "with data ($data)\n",
280 This creates an handler for the attribute C<:Loud> in the class LoudDecl.
281 Thereafter, any subroutine declared with a C<:Loud> attribute in the class
288 causes the above handler to be invoked, and passed:
294 the name of the package into which it was declared;
298 a reference to the symbol table entry (typeglob) containing the subroutine;
302 a reference to the subroutine;
306 the name of the attribute;
310 any data associated with that attribute;
314 the name of the phase in which the handler is being invoked.
318 Likewise, declaring any variables with the C<:Loud> attribute within the
327 will cause the handler to be called with a similar argument list (except,
328 of course, that C<$_[2]> will be a reference to the variable).
330 The package name argument will typically be the name of the class into
331 which the subroutine was declared, but it may also be the name of a derived
332 class (since handlers are inherited).
334 If a lexical variable is given an attribute, there is no symbol table to
335 which it belongs, so the symbol table argument (C<$_[1]>) is set to the
336 string C<'LEXICAL'> in that case. Likewise, ascribing an attribute to
337 an anonymous subroutine results in a symbol table argument of C<'ANON'>.
339 The data argument passes in the value (if any) associated with the
340 attribute. For example, if C<&foo> had been declared:
342 sub foo :Loud("turn it up to 11, man!") {...}
344 then the string C<"turn it up to 11, man!"> would be passed as the
347 Attribute::Handlers makes strenuous efforts to convert
348 the data argument (C<$_[4]>) to a useable form before passing it to
349 the handler (but see L<"Non-interpretive attribute handlers">).
350 For example, all of these:
352 sub foo :Loud(till=>ears=>are=>bleeding) {...}
353 sub foo :Loud(['till','ears','are','bleeding']) {...}
354 sub foo :Loud(qw/till ears are bleeding/) {...}
355 sub foo :Loud(qw/my, ears, are, bleeding/) {...}
356 sub foo :Loud(till,ears,are,bleeding) {...}
358 causes it to pass C<['till','ears','are','bleeding']> as the handler's
359 data argument. However, if the data can't be parsed as valid Perl, then
360 it is passed as an uninterpreted string. For example:
362 sub foo :Loud(my,ears,are,bleeding) {...}
363 sub foo :Loud(qw/my ears are bleeding) {...}
365 cause the strings C<'my,ears,are,bleeding'> and C<'qw/my ears are bleeding'>
366 respectively to be passed as the data argument.
368 If the attribute has only a single associated scalar data value, that value is
369 passed as a scalar. If multiple values are associated, they are passed as an
370 array reference. If no value is associated with the attribute, C<undef> is
374 =head2 Typed lexicals
376 Regardless of the package in which it is declared, if a lexical variable is
377 ascribed an attribute, the handler that is invoked is the one belonging to
378 the package to which it is typed. For example, the following declarations:
382 my LoudDecl $loudobj : Loud;
383 my LoudDecl @loudobjs : Loud;
384 my LoudDecl %loudobjex : Loud;
386 causes the LoudDecl::Loud handler to be invoked (even if OtherClass also
387 defines a handler for C<:Loud> attributes).
390 =head2 Type-specific attribute handlers
392 If an attribute handler is declared and the C<:ATTR> specifier is
393 given the name of a built-in type (C<SCALAR>, C<ARRAY>, C<HASH>, or C<CODE>),
394 the handler is only applied to declarations of that type. For example,
395 the following definition:
399 sub RealLoud :ATTR(SCALAR) { print "Yeeeeow!" }
401 creates an attribute handler that applies only to scalars:
407 my $metal : RealLoud; # invokes &LoudDecl::RealLoud
408 my @metal : RealLoud; # error: unknown attribute
409 my %metal : RealLoud; # error: unknown attribute
410 sub metal : RealLoud {...} # error: unknown attribute
412 You can, of course, declare separate handlers for these types as well
413 (but you'll need to specify C<no warnings 'redefine'> to do it quietly):
416 use Attribute::Handlers;
417 no warnings 'redefine';
419 sub RealLoud :ATTR(SCALAR) { print "Yeeeeow!" }
420 sub RealLoud :ATTR(ARRAY) { print "Urrrrrrrrrr!" }
421 sub RealLoud :ATTR(HASH) { print "Arrrrrgggghhhhhh!" }
422 sub RealLoud :ATTR(CODE) { croak "Real loud sub torpedoed" }
424 You can also explicitly indicate that a single handler is meant to be
425 used for all types of referents like so:
428 use Attribute::Handlers;
430 sub SeriousLoud :ATTR(ANY) { warn "Hearing loss imminent" }
432 (I.e. C<ATTR(ANY)> is a synonym for C<:ATTR>).
435 =head2 Non-interpretive attribute handlers
437 Occasionally the strenuous efforts Attribute::Handlers makes to convert
438 the data argument (C<$_[4]>) to a useable form before passing it to
439 the handler get in the way.
441 You can turn off that eagerness-to-help by declaring
442 an attribute handler with the the keyword C<RAWDATA>. For example:
444 sub Raw : ATTR(RAWDATA) {...}
445 sub Nekkid : ATTR(SCALAR,RAWDATA) {...}
446 sub Au::Naturale : ATTR(RAWDATA,ANY) {...}
448 Then the handler makes absolutely no attempt to interpret the data it
449 receives and simply passes it as a string:
451 my $power : Raw(1..100); # handlers receives "1..100"
453 =head2 Phase-specific attribute handlers
455 By default, attribute handlers are called at the end of the compilation
456 phase (in a C<CHECK> block). This seems to be optimal in most cases because
457 most things that can be defined are defined by that point but nothing has
460 However, it is possible to set up attribute handlers that are called at
461 other points in the program's compilation or execution, by explicitly
462 stating the phase (or phases) in which you wish the attribute handler to
463 be called. For example:
465 sub Early :ATTR(SCALAR,BEGIN) {...}
466 sub Normal :ATTR(SCALAR,CHECK) {...}
467 sub Late :ATTR(SCALAR,INIT) {...}
468 sub Final :ATTR(SCALAR,END) {...}
469 sub Bookends :ATTR(SCALAR,BEGIN,END) {...}
471 As the last example indicates, a handler may be set up to be (re)called in
472 two or more phases. The phase name is passed as the handler's final argument.
474 Note that attribute handlers that are scheduled for the C<BEGIN> phase
475 are handled as soon as the attribute is detected (i.e. before any
476 subsequently defined C<BEGIN> blocks are executed).
479 =head2 Attributes as C<tie> interfaces
481 Attributes make an excellent and intuitive interface through which to tie
482 variables. For example:
484 use Attribute::Handlers;
487 sub UNIVERSAL::Cycle : ATTR(SCALAR) {
488 my ($package, $symbol, $referent, $attr, $data, $phase) = @_;
489 $data = [ $data ] unless ref $data eq 'ARRAY';
490 tie $$referent, 'Tie::Cycle', $data;
497 my $next : Cycle('A'..'Z'); # $next is now a tied variable
503 In fact, this pattern is so widely applicable that Attribute::Handlers
504 provides a way to automate it: specifying C<'autotie'> in the
505 C<use Attribute::Handlers> statement. So, the previous example,
506 could also be written:
508 use Attribute::Handlers autotie => { Cycle => 'Tie::Cycle' };
514 my $next : Cycle('A'..'Z'); # $next is now a tied variable
519 The argument after C<'autotie'> is a reference to a hash in which each key is
520 the name of an attribute to be created, and each value is the class to which
521 variables ascribed that attribute should be tied.
523 Note that there is no longer any need to import the Tie::Cycle module --
524 Attribute::Handlers takes care of that automagically. You can even pass
525 arguments to the module's C<import> subroutine, by appending them to the
526 class name. For example:
528 use Attribute::Handlers
529 autotie => { Dir => 'Tie::Dir qw(DIR_UNLINK)' };
531 If the attribute name is unqualified, the attribute is installed in the
532 current package. Otherwise it is installed in the qualifier's package:
536 use Attribute::Handlers autotie => {
537 Other::Good => Tie::SecureHash, # tie attr installed in Other::
538 Bad => Tie::Taxes, # tie attr installed in Here::
539 UNIVERSAL::Ugly => Software::Patent # tie attr installed everywhere
542 Autoties are most commonly used in the module to which they actually tie,
543 and need to export their attributes to any module that calls them. To
544 facilitiate this, Attribute::Handlers recognizes a special "pseudo-class" --
545 C<__CALLER__>, which may be specified as the qualifier of an attribute:
547 package Tie::Me::Kangaroo:Down::Sport;
549 use Attribute::Handler autotie => { __CALLER__::Roo => __PACKAGE__ };
551 This causes Attribute::Handlers to define the C<Roo> attribute in the package
552 that imports the Tie::Me::Kangaroo:Down::Sport module.
557 If the class shown in L<SYNOPSIS> were placed in the MyClass.pm
558 module, then the following code:
563 my MyClass $slr :Good :Bad(1**1-1) :Omni(-vorous);
565 package SomeOtherClass;
570 sub fn :Ugly(sister) :Omni('po',tent()) {...}
571 my @arr :Good :Omni(s/cie/nt/);
572 my %hsh :Good(q/bye) :Omni(q/bus/);
575 would cause the following handlers to be invoked:
577 # my MyClass $slr :Good :Bad(1**1-1) :Omni(-vorous);
579 MyClass::Good:ATTR(SCALAR)( 'MyClass', # class
580 'LEXICAL', # no typeglob
584 'CHECK', # compiler phase
587 MyClass::Bad:ATTR(SCALAR)( 'MyClass', # class
588 'LEXICAL', # no typeglob
592 'CHECK', # compiler phase
595 MyClass::Omni:ATTR(SCALAR)( 'MyClass', # class
596 'LEXICAL', # no typeglob
599 '-vorous' # eval'd attr data
600 'CHECK', # compiler phase
604 # sub fn :Ugly(sister) :Omni('po',tent()) {...}
606 MyClass::UGLY:ATTR(CODE)( 'SomeOtherClass', # class
607 \*SomeOtherClass::fn, # typeglob
608 \&SomeOtherClass::fn, # referent
610 'sister' # eval'd attr data
611 'CHECK', # compiler phase
614 MyClass::Omni:ATTR(CODE)( 'SomeOtherClass', # class
615 \*SomeOtherClass::fn, # typeglob
616 \&SomeOtherClass::fn, # referent
618 ['po','acle'] # eval'd attr data
619 'CHECK', # compiler phase
623 # my @arr :Good :Omni(s/cie/nt/);
625 MyClass::Good:ATTR(ARRAY)( 'SomeOtherClass', # class
626 'LEXICAL', # no typeglob
630 'CHECK', # compiler phase
633 MyClass::Omni:ATTR(ARRAY)( 'SomeOtherClass', # class
634 'LEXICAL', # no typeglob
637 "" # eval'd attr data
638 'CHECK', # compiler phase
642 # my %hsh :Good(q/bye) :Omni(q/bus/);
644 MyClass::Good:ATTR(HASH)( 'SomeOtherClass', # class
645 'LEXICAL', # no typeglob
648 'q/bye' # raw attr data
649 'CHECK', # compiler phase
652 MyClass::Omni:ATTR(HASH)( 'SomeOtherClass', # class
653 'LEXICAL', # no typeglob
656 'bus' # eval'd attr data
657 'CHECK', # compiler phase
661 Installing handlers into UNIVERSAL, makes them...err..universal.
664 package Descriptions;
665 use Attribute::Handlers;
668 sub name { return $name{$_[2]}||*{$_[1]}{NAME} }
670 sub UNIVERSAL::Name :ATTR {
671 $name{$_[2]} = $_[4];
674 sub UNIVERSAL::Purpose :ATTR {
675 print STDERR "Purpose of ", &name, " is $_[4]\n";
678 sub UNIVERSAL::Unit :ATTR {
679 print STDERR &name, " measured in $_[4]\n";
686 my $capacity : Name(capacity)
687 : Purpose(to store max storage capacity for files)
693 sub foo : Purpose(to foo all data before barring it) { }
702 =item C<Bad attribute type: ATTR(%s)>
704 An attribute handler was specified with an C<:ATTR(I<ref_type>)>, but the
705 type of referent it was defined to handle wasn't one of the five permitted:
706 C<SCALAR>, C<ARRAY>, C<HASH>, C<CODE>, or C<ANY>.
708 =item C<Attribute handler %s doesn't handle %s attributes>
710 A handler for attributes of the specified name I<was> defined, but not
711 for the specified type of declaration. Typically encountered whe trying
712 to apply a C<VAR> attribute handler to a subroutine, or a C<SCALAR>
713 attribute handler to some other type of variable.
715 =item C<Declaration of %s attribute in package %s may clash with future reserved word>
717 A handler for an attributes with an all-lowercase name was declared. An
718 attribute with an all-lowercase name might have a meaning to Perl
719 itself some day, even though most don't yet. Use a mixed-case attribute
722 =item C<Can't have two ATTR specifiers on one subroutine>
724 You just can't, okay?
725 Instead, put all the specifications together with commas between them
726 in a single C<ATTR(I<specification>)>.
728 =item C<Can't autotie a %s>
730 You can only declare autoties for types C<"SCALAR">, C<"ARRAY">, and
731 C<"SCALAR">. They're the only things (apart from typeglobs -- which are
732 not declarable) that Perl can tie.
734 =item C<Internal error: %s symbol went missing>
736 Something is rotten in the state of the program. An attributed
737 subroutine ceased to exist between the point it was declared and the point
738 at which its attribute handler(s) would have been called.
744 Damian Conway (damian@conway.org)
748 There are undoubtedly serious bugs lurking somewhere in code this funky :-)
749 Bug reports and other feedback are most welcome.
753 Copyright (c) 2001, Damian Conway. All Rights Reserved.
754 This module is free software. It may be used, redistributed
755 and/or modified under the terms of the Perl Artistic License
756 (see http://www.perl.com/perl/misc/Artistic.html)