use 5.006;
use Carp;
use warnings;
-$VERSION = '0.76';
+$VERSION = '0.78_03';
# $DB::single=1;
my %symcache;
my ($class) = $AUTOLOAD =~ m/(.*)::/g;
$AUTOLOAD =~ m/_ATTR_(.*?)_(.*)/ or
croak "Can't locate class method '$AUTOLOAD' via package '$class'";
- croak "Attribute handler '$3' doesn't handle $2 attributes";
+ croak "Attribute handler '$2' doesn't handle $1 attributes";
}
sub DESTROY {}
-my $builtin = qr/lvalue|method|locked/;
+my $builtin = qr/lvalue|method|locked|unique|shared/;
sub _gen_handler_AH_() {
return sub {
%lastattr=(pkg=>$pkg,ref=>$ref,type=>$data);
}
else {
- my $handler = $pkg->can($attr);
+ my $type = ref $ref;
+ my $handler = $pkg->can("_ATTR_${type}_${attr}");
next unless $handler;
my $decl = [$pkg, $ref, $attr, $data,
$raw{$handler}, $phase{$handler}];
_apply_handler_AH_($decl,$gphase)
if $global_phases{$gphase} <= $global_phase;
}
- push @declarations, $decl;
+ if ($global_phase != 0) {
+ # if _gen_handler_AH_ is being called after
+ # CHECK it's for a lexical, so make sure
+ # it didn't want to run anything later
+
+ local $Carp::CarpLevel = 2;
+ carp "Won't be able to apply END handler"
+ if $phase{$handler}{END};
+ }
+ else {
+ push @declarations, $decl
+ }
}
$_ = undef;
}
}
}
-*{"MODIFY_${_}_ATTRIBUTES"} = _gen_handler_AH_ foreach @{$validtype{ANY}};
-push @UNIVERSAL::ISA, 'Attribute::Handlers'
- unless grep /^Attribute::Handlers$/, @UNIVERSAL::ISA;
+*{"Attribute::Handlers::UNIVERSAL::MODIFY_${_}_ATTRIBUTES"} =
+ _gen_handler_AH_ foreach @{$validtype{ANY}};
+push @UNIVERSAL::ISA, 'Attribute::Handlers::UNIVERSAL'
+ unless grep /^Attribute::Handlers::UNIVERSAL$/, @UNIVERSAL::ISA;
sub _apply_handler_AH_ {
my ($declaration, $phase) = @_;
return 1;
}
-CHECK {
- $global_phase++;
- _resolve_lastattr;
- _apply_handler_AH_($_,'CHECK') foreach @declarations;
-}
+{
+ no warnings 'void';
+ CHECK {
+ $global_phase++;
+ _resolve_lastattr;
+ _apply_handler_AH_($_,'CHECK') foreach @declarations;
+ }
-INIT { $global_phase++; _apply_handler_AH_($_,'INIT') foreach @declarations }
+ INIT {
+ $global_phase++;
+ _apply_handler_AH_($_,'INIT') foreach @declarations
+ }
+}
END { $global_phase++; _apply_handler_AH_($_,'END') foreach @declarations }
=head1 VERSION
-This document describes version 0.76 of Attribute::Handlers,
-released November 15, 2001.
+This document describes version 0.78 of Attribute::Handlers,
+released October 5, 2002.
=head1 SYNOPSIS
derived from that package may be given attributes with the same names as
the attribute handler subroutines, which will then be called in one of
the compilation phases (i.e. in a C<BEGIN>, C<CHECK>, C<INIT>, or C<END>
-block).
+block). (C<UNITCHECK> blocks don't correspond to a global compilation
+phase, so they can't be specified here.)
To create a handler, define it as a subroutine with the same name as
the desired attribute, and declare the subroutine itself with the
Autoties are most commonly used in the module to which they actually tie,
and need to export their attributes to any module that calls them. To
-facilitiate this, Attribute::Handlers recognizes a special "pseudo-class" --
+facilitate this, Attribute::Handlers recognizes a special "pseudo-class" --
C<__CALLER__>, which may be specified as the qualifier of an attribute:
package Tie::Me::Kangaroo:Down::Sport;
- use Attribute::Handlers autotie => { __CALLER__::Roo => __PACKAGE__ };
+ use Attribute::Handlers autotie => { '__CALLER__::Roo' => __PACKAGE__ };
This causes Attribute::Handlers to define the C<Roo> attribute in the package
that imports the Tie::Me::Kangaroo:Down::Sport module.
+Note that it is important to quote the __CALLER__::Roo identifier because
+a bug in perl 5.8 will refuse to parse it and cause an unknown error.
+
=head3 Passing the tied object to C<tie>
Occasionally it is important to pass a reference to the object being tied
subroutine ceased to exist between the point it was declared and the point
at which its attribute handler(s) would have been called.
+=item C<Won't be able to apply END handler>
+
+You have defined an END handler for an attribute that is being applied
+to a lexical variable. Since the variable may not be available during END
+this won't happen.
+
=back
=head1 AUTHOR