X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2Fattributes.pm;h=22afaef3f434f161f2c5934e91430b8b93ff6896;hb=eb6393247e5113feb0b19b71cbdee87eebedbbb7;hp=d26872f566dbd4ac06b165ea91caba762150c8c5;hpb=26f2972e6cc14b5198456611d023553a813ccb68;p=p5sagit%2Fp5-mst-13.2.git diff --git a/lib/attributes.pm b/lib/attributes.pm index d26872f..22afaef 100644 --- a/lib/attributes.pm +++ b/lib/attributes.pm @@ -1,6 +1,6 @@ package attributes; -$VERSION = 0.02; +our $VERSION = 0.08; @EXPORT_OK = qw(get reftype); @EXPORT = (); @@ -23,17 +23,16 @@ sub carp { #sub _fetch_attrs ($) ; #sub _guess_stash ($) ; #sub _modify_attrs ; -#sub _warn_reserved () ; # # The extra trips through newATTRSUB in the interpreter wipe out any savings # from avoiding the BEGIN block. Just do the bootstrap now. -BEGIN { bootstrap } +BEGIN { bootstrap attributes } sub import { @_ > 2 && ref $_[2] or do { require Exporter; goto &Exporter::import; - } + }; my (undef,$home_stash,$svref,@attrs) = @_; my $svtype = uc reftype($svref); @@ -43,9 +42,10 @@ sub import { my @badattrs; if ($pkgmeth) { my @pkgattrs = _modify_attrs($svref, @attrs); - @badattrs = $pkgmeth->($home_stash, $svref, @attrs); + @badattrs = $pkgmeth->($home_stash, $svref, @pkgattrs); if (!@badattrs && @pkgattrs) { - return unless _warn_reserved; + require warnings; + return unless warnings::enabled('reserved'); @pkgattrs = grep { m/\A[[:lower:]]+(?:\z|\()/ } @pkgattrs; if (@pkgattrs) { for my $attr (@pkgattrs) { @@ -54,7 +54,7 @@ sub import { my $s = ((@pkgattrs == 1) ? '' : 's'); carp "$svtype package attribute$s " . "may clash with future reserved word$s: " . - join(' , ' , @pkgattrs); + join(' : ' , @pkgattrs); } } } @@ -65,7 +65,7 @@ sub import { croak "Invalid $svtype attribute" . (( @badattrs == 1 ) ? '' : 's') . ": " . - join(' , ', @badattrs); + join(' : ', @badattrs); } } @@ -98,7 +98,7 @@ attributes - get/set subroutine or variable attributes =head1 SYNOPSIS sub foo : method ; - my ($x,@y,%z) : Bent ; + my ($x,@y,%z) : Bent = 1; my $s = sub : method { ... }; use attributes (); # optional, to get subroutine declarations @@ -120,15 +120,18 @@ the following: The second example in the synopsis does something equivalent to this: - use attributes __PACKAGE__, \$x, 'Bent'; - use attributes __PACKAGE__, \@y, 'Bent'; - use attributes __PACKAGE__, \%z, 'Bent'; + use attributes (); + my ($x,@y,%z); + attributes::->import(__PACKAGE__, \$x, 'Bent'); + attributes::->import(__PACKAGE__, \@y, 'Bent'); + attributes::->import(__PACKAGE__, \%z, 'Bent'); + ($x,@y,%z) = 1; -Yes, that's three invocations. +Yes, that's a lot of expansion. -B: attribute declarations for variables are an I -feature. The semantics of such declarations could change or be removed -in future versions. They are present for purposes of experimentation +B: attribute declarations for variables are still evolving. +The semantics and interfaces of such declarations could change in +future versions. They are present for purposes of experimentation with what the semantics ought to be. Do not rely on the current implementation of this feature. @@ -137,12 +140,22 @@ directly by this module, depending on how you look at it.) However, package-specific attributes are allowed by an extension mechanism. (See L<"Package-specific Attribute Handling"> below.) -The setting of attributes happens at compile time. An attempt to set -an unrecognized attribute is a fatal error. (The error is trappable, but -it still stops the compilation within that C.) Setting an attribute -with a name that's all lowercase letters that's not a built-in attribute -(such as "foo") -will result in a warning with B<-w> or C. +The setting of subroutine attributes happens at compile time. +Variable attributes in C declarations are also applied at compile time. +However, C variables get their attributes applied at run-time. +This means that you have to I the run-time component of the C +before those attributes will get applied. For example: + + my $x : Bent = 42 if 0; + +will neither assign 42 to $x I will it apply the C attribute +to the variable. + +An attempt to set an unrecognized attribute is a fatal error. (The +error is trappable, but it still stops the compilation within that +C.) Setting an attribute with a name that's all lowercase +letters that's not a built-in attribute (such as "foo") will result in +a warning with B<-w> or C. =head2 Built-in Attributes @@ -152,6 +165,10 @@ The following are the built-in attributes for subroutines: =item locked +B<5.005 threads only! The use of the "locked" attribute currently +only makes sense if you are using the deprecated "Perl 5.005 threads" +implementation of threads.> + Setting this attribute is only meaningful when the subroutine or method is to be called by multiple threads. When set on a method subroutine (i.e., one marked with the B attribute below), @@ -169,9 +186,15 @@ This has a meaning when taken together with the B attribute, as described there. It also means that a subroutine so marked will not trigger the "Ambiguous call resolved as CORE::%s" warning. +=item lvalue + +Indicates that the referenced subroutine is a valid lvalue and can +be assigned to. The subroutine must return a modifiable value such +as a scalar variable, as described in L. + =back -There are no built-in attributes for anything other than subroutines. +For global variables there is C attribute: see L. =head2 Available Subroutines @@ -232,17 +255,17 @@ The class methods invoked for modifying and fetching are these: =item FETCH_I_ATTRIBUTES -This method receives a single argument, which is a reference to the -variable or subroutine for which package-defined attributes are desired. -The expected return value is a list of associated attributes. -This list may be empty. +This method is called with two arguments: the relevant package name, +and a reference to a variable or subroutine for which package-defined +attributes are desired. The expected return value is a list of +associated attributes. This list may be empty. =item MODIFY_I_ATTRIBUTES This method is called with two fixed arguments, followed by the list of attributes from the relevant declaration. The two fixed arguments are the relevant package name and a reference to the declared subroutine or -variable. The expected return value as a list of attributes which were +variable. The expected return value is a list of attributes which were not recognized by this handler. Note that this allows for a derived class to delegate a call to its base class, and then only examine the attributes which the base class didn't already handle for it. @@ -267,7 +290,8 @@ will use that package name. =head2 Syntax of Attribute Lists An attribute list is a sequence of attribute specifications, separated by -whitespace, commas, or both. Each attribute specification is a simple +whitespace or a colon (with optional whitespace). +Each attribute specification is a simple name, optionally followed by a parenthesised parameter list. If such a parameter list is present, it is scanned past as for the rules for the C operator. (See L.) @@ -275,8 +299,8 @@ The parameter list is passed as it was found, however, and not as per C. Some examples of syntactically valid attribute lists: - switch(10,foo(7,3)) , , expensive - Ugly('\(") , Bad + switch(10,foo(7,3)) : expensive + Ugly('\(") :Bad _5x5 locked method @@ -286,7 +310,7 @@ Some examples of syntactically invalid attribute lists (with annotation): Ugly('(') # ()-string not balanced 5x5 # "5x5" not a valid identifier Y2::north # "Y2::north" not a simple identifier - foo + bar # "+" neither a comma nor whitespace + foo + bar # "+" neither a colon nor whitespace =head1 EXPORTS @@ -322,7 +346,8 @@ Code: Effect: - use attributes Canine => \$spot, "Watchful"; + use attributes (); + attributes::->import(Canine => \$spot, "Watchful"); =item 2. @@ -333,7 +358,8 @@ Code: Effect: - use attributes Felis => \$cat, "Nervous"; + use attributes (); + attributes::->import(Felis => \$cat, "Nervous"); =item 3.