X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2Fattributes.pm;h=4f6eef03761d3a5c85bbc75333368caeffa50342;hb=5290524f8b52822096b01140005d681d126b507d;hp=e49204fc76fd6302047f2466b756f624482a5534;hpb=09bef84370e90d727656ea11ba5ee8be80e361d3;p=p5sagit%2Fp5-mst-13.2.git diff --git a/lib/attributes.pm b/lib/attributes.pm index e49204f..4f6eef0 100644 --- a/lib/attributes.pm +++ b/lib/attributes.pm @@ -1,9 +1,10 @@ package attributes; -$VERSION = 0.01; +our $VERSION = '0.04_01'; -#@EXPORT_OK = qw(get reftype); -#@EXPORT = (); +@EXPORT_OK = qw(get reftype); +@EXPORT = (); +%EXPORT_TAGS = (ALL => [@EXPORT, @EXPORT_OK]); use strict; @@ -26,11 +27,13 @@ sub carp { # # 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 - croak 'Usage: use '.__PACKAGE__.' $home_stash, $ref, @attrlist'; + @_ > 2 && ref $_[2] or do { + require Exporter; + goto &Exporter::import; + }; my (undef,$home_stash,$svref,@attrs) = @_; my $svtype = uc reftype($svref); @@ -51,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); } } } @@ -62,7 +65,7 @@ sub import { croak "Invalid $svtype attribute" . (( @badattrs == 1 ) ? '' : 's') . ": " . - join(' , ', @badattrs); + join(' : ', @badattrs); } } @@ -82,12 +85,7 @@ sub get ($) { ; } -#sub export { -# require Exporter; -# goto &Exporter::import; -#} -# -#sub require_version { goto &UNIVERSAL::VERSION } +sub require_version { goto &UNIVERSAL::VERSION } 1; __END__ @@ -100,30 +98,36 @@ 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 my @attrlist = attributes::get(\&foo); + use attributes 'get'; # import the attributes::get subroutine + my @attrlist = get \&foo; + =head1 DESCRIPTION Subroutine declarations and definitions may optionally have attribute lists associated with them. (Variable C declarations also may, but see the warning below.) Perl handles these declarations by passing some information about the call site and the thing being declared along with the attribute -list to this module. In particular, first example above is equivalent to +list to this module. In particular, the first example above is equivalent to the following: use attributes __PACKAGE__, \&foo, 'method'; 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 @@ -136,7 +140,18 @@ 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 +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 @@ -168,10 +183,19 @@ 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 hackers +What about C? + =head2 Available Subroutines The following subroutines are available for general use once this module @@ -187,7 +211,7 @@ empty. If passed invalid arguments, it uses die() (via L) to raise a fatal exception. If it can find an appropriate package name for a class method lookup, it will include the results from a C_ATTRIBUTES> call in its return list, as described in -L"Package-specific Attribute Handling"> below. +L<"Package-specific Attribute Handling"> below. Otherwise, only L will be returned. =item reftype @@ -196,13 +220,11 @@ This routine expects a single parameter--a reference to a subroutine or variable. It returns the built-in type of the referenced variable, ignoring any package into which it might have been blessed. This can be useful for determining the I value which forms part of -the method names described in L"Package-specific Attribute Handling"> below. +the method names described in L<"Package-specific Attribute Handling"> below. =back -Note that these routines are I exported. This is primarily because -the C mechanism which would normally import them is already in use -by Perl itself to implement the C syntax. +Note that these routines are I exported by default. =head2 Package-specific Attribute Handling @@ -268,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.) @@ -276,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 @@ -287,7 +310,21 @@ 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 + +=head2 Default exports + +None. + +=head2 Available exports + +The routines C and C are exportable. + +=head2 Export tags defined + +The C<:ALL> tag will get all of the above exports. =head1 EXAMPLES @@ -309,7 +346,8 @@ Code: Effect: - use attributes Canine => \$spot, "Watchful"; + use attributes (); + attributes::->import(Canine => \$spot, "Watchful"); =item 2. @@ -320,7 +358,8 @@ Code: Effect: - use attributes Felis => \$cat, "Nervous"; + use attributes (); + attributes::->import(Felis => \$cat, "Nervous"); =item 3.