File Coverage

blib/lib/Class/Tag.pm
Criterion Covered Total %
statement 74 80 92.5
branch 47 60 78.3
condition 23 41 56.1
subroutine 11 12 91.6
pod 0 1 0.0
total 155 194 79.9


line stmt bran cond sub pod time code
1             package Class::Tag;
2            
3             #use 5.006;
4            
5 1     1   24145 use strict qw[vars subs];
  1         4  
  1         206  
6             $Class::Tag::VERSION = '0.10';
7            
8             =head1 NAME
9            
10             Class::Tag - programmatically label (mark) classes, methods, roles and modules with meta-data tags (key/value pairs) and query those tags
11            
12             =head1 Warning
13            
14             Any specific interface that Class::Tag exposes may change (as it already did) until version 1.0 is reached.
15            
16             =head1 SYNOPSIS
17            
18             {
19             package Foo;
20             use Class::Tag 'tagged'; # tagging Foo class with 'tagged' tag
21             }
22            
23             # query 'tagged' tag on the Foo and Bar...
24             Class::Tag->tagged('Foo'); # true
25             Class::Tag->tagged('Bar'); # false
26            
27             {
28             package Bar;
29             use Class::Tag { class => 'is cool', author => 'metadoo' };
30             }
31            
32             Class::Tag->class( 'Bar') eq 'is cool'; # true
33             Class::Tag->author('Bar') eq 'metadoo'; # true
34            
35             See DESCRIPTION for more options.
36            
37             =head1 DESCRIPTION
38            
39             Sometimes it is necessary to programmatically tag modules and classes with some meta-data tags (arbitrary labels or key/value pairs) to be able to assert that you deal with proper classes (modules), methods and roles. Such need typically arises for plug-in modules, application component modules, complex class inheritance hierarchies, etc.
40            
41             Class::Tag allows programmatically label (mark) classes and modules with arbitrary inheritable tags (key/value pairs) without collision with methods/attributes/functions of the class/module and query those tags on arbitrary classes and modules.
42            
43             The syntax of Class::Tag usage is an interaction of B, B (class) and B (class): tagger applies tag to a target class. Names of tagger class (except Class::Tag itself) and tag can be chosen almost freely (with usual restrictions) to be read together as (subject and predicate in a) self-explanatory English sentence, with question semantics (e.g. in conditionals) optionally toggled by direct/indirect method call notation. The following synopsis illustrates.
44            
45             Directly using Class::Tag as tagger:
46            
47             {
48             package Foo;
49             use Class::Tag 'tagged'; # tagging Foo class with 'tagged' tag
50             tag Class::Tag 'tagged'; # same, but at run-time
51             }
52            
53             # query 'tagged' tag on the Foo and Bar...
54             Class::Tag->tagged('Foo'); # true
55             Class::Tag->tagged('Bar'); # false
56            
57             Tag can be removed completely from within the scope of the same package Foo:
58            
59             {
60             package Foo;
61             # remove 'tagged' tag from Foo...
62             #no Class::Tag 'tagged'; # at compile-time, so will not work - instead...
63             untag Class::Tag 'tagged'; # at run-time
64             Class::Tag->tagged('Foo'); # false
65             }
66            
67             However, since tagged() is now the read-write accessor for tag value, it may be easier to alter tag's value instead:
68            
69             Class::Tag->tagged('Foo' => 0);
70             Class::Tag->tagged('Foo'); # false
71            
72             If no tags are given, the 'is' tag is assumed:
73            
74             package Foo;
75             use Class::Tag; # equivalent to...
76             use Class::Tag 'is'; # same
77             use Class::Tag (); # no tagging
78            
79             New tagger class can be created by simply tagging package with special 'tagger_class' tag using either Class::Tag or any other tagger class, and then declaring specific tags to be used with that new tagger class. Declaration of specific tag is done by new tagger class applying this tag to itself. Declaring special 'AUTOLOAD' tag this way effectively declares that any tag can be used with new tagger class:
80            
81             {
82             # this block can be used as "inline" tagger class definition
83             # or contents of this block can be loaded from Awesome.pm
84            
85             package Awesome; # new tagger class
86             use Class::Tag 'tagger_class'; # must be before following declarations
87             use Awesome 'specific_tag'; # declares 'specific_tag' for use
88             use Awesome 'AUTOLOAD'; # declares that any tag can be used
89            
90             1;
91             }
92            
93             Class::Tag->tagger_class('Awesome'); # true
94            
95             Note that Awesome class is not required to be loaded from .pm file with use() or require(), it can be simply defined as above at any point in the code prior to using it as tagger class. Such tagger class definition is referred to as "inline" tagger class.
96            
97             The Class::Tag itself is somewhat similar to the following implicit declaration:
98            
99             package Class::Tag;
100             use Class::Tag 'tagger_class';
101             use Class::Tag 'AUTOLOAD';
102            
103             Attempt to use tag that has not been declared (assuming 'AUTOLOAD' declares any tag) raises exception. Values of declaration tags can be used to modify behavior of tags - see L section for details.
104            
105             Any tagger class can be used as follows (in all following examples the original Class::Tag and Awesome tagger classes are interchangeable), assuming tags have been declared:
106            
107             Using default 'is' tag:
108            
109             {
110             package Foo;
111             use Awesome;
112             use Awesome 'is'; # same
113             use Awesome { is => 1 }; # same
114             }
115            
116             is Awesome 'Foo'; # true
117             is Awesome 'Bar'; # false
118            
119             Awesome->is('Foo'); # true
120             Awesome->is('Bar'); # false
121            
122             $obj = bless {}, 'Foo';
123            
124             is Awesome $obj; # true
125             Awesome->is($obj); # true
126            
127             $obj = bless {}, 'Bar';
128            
129             is Awesome $obj; # false
130             Awesome->is($obj); # false
131            
132             Using tags 'class' and 'pureperl':
133            
134             {
135             package Foo;
136             # tag class Foo with tags 'class' and 'pureperl' of Awesome tagger class...
137             use Awesome 'class';
138             use Awesome 'pureperl';
139             use Awesome 'class', 'pureperl'; # same
140             use Awesome { class => 1, pureperl => 1 }; # same
141             }
142            
143             Awesome->class( 'Foo'); # true
144             Awesome->pureperl('Foo'); # true
145             Awesome->class( 'Bar'); # false
146             Awesome->pureperl('Bar'); # false
147            
148             Using key/value pairs as tags (tag values) and using read-write tag accessors:
149            
150             {
151             package Foo;
152             use Awesome { class => 'is cool', author => 'metadoo' };
153             }
154            
155             Awesome->author('Foo') eq 'metadoo' ; # true
156             Awesome->class( 'Foo') eq 'is cool' ; # true
157             Awesome->class( 'Foo' => 'pupe-perl') eq 'pupe-perl'; # true
158             Awesome->class( 'Foo') eq 'pupe-perl'; # true
159            
160             $foo = bless {}, 'Foo';
161            
162             Awesome->class( $foo) eq 'is cool'; # true
163             Awesome->author($foo) eq 'metadoo'; # true (inheriting)
164            
165             Awesome->class( $foo) eq 'pupe-perl'; # true (inheriting)
166             Awesome->class( $foo => 'pupe-perl too') eq 'pupe-perl too'; # true (copy-on-write)
167             Awesome->class( $foo) eq 'pupe-perl too'; # true (copy-on-write)
168             Awesome->class( 'Foo') eq 'pupe-perl'; # true (unmodified)
169            
170             In other words, tag values can be modified with samename accessors. Object instances from the class inherit tags from the class, so that modifying tag value on instance modifies that of a class and vice versa, except blessed-hash objects get their own, instance-specific values when modifying tag value on instance - copy-on-write approach.
171            
172             Inheriting tags, using for example the default 'is' tag:
173            
174             {
175             package Foo;
176             use Awesome;
177             use Awesome 'is'; # same
178             }
179            
180             @Bar::ISA = 'Foo';
181            
182             Awesome->is('Foo'); # true
183             Awesome->is('Bar'); # true ('is' tag inherited)
184             Awesome::is('Foo'); # true
185             Awesome::is('Bar'); # false (no tag inheritance)
186            
187             By design, Class::Tag is a generalized framework for managing meta information (tags) about inheritable behaviors. Inheritable behaviors that can have meta-data tags attached include methods, classes, roles, etc. Tags are by necessity inheritable, as they need to be inherited together with behaviors they are supposed to describe.
188            
189             Simple example of the meta-data tag is a class name, with tag's (boolean) value returned by isa(). Another simple example of meta-data tag is a method name, with its value returned by can(). Yet another meta-data tag example is a role name, with tag's value supposed to be returned by DOES(). But classes, methods and roles may also have other meta-data tags apart from their names. In particular, Class::Tag can easily be used to implement method attributes and even multiple "layers" of method attributes, for example:
190            
191             package Zoo;
192            
193             sub foo { 1 }
194             use Meta foo => { is => 'ro', returns => 'boolean' }; # 1-st "meta-layer"
195             use Meta2 foo => { author => 'metadoo', doc => 'is dead-simple' }; # 2-nd "meta-layer"
196            
197             Such use opens possibilities for meta-programming and introspection. For example, method can access its own meta-data as follows:
198            
199             sub foo { Meta->foo( ref($_[0])||$_[0] ) }
200             sub foo { Meta->foo( $_[0] ) } # nearly (but not exactly) same
201            
202             Technically, Class::Tag is the constructor for special variety of class/object attributes that are orthogonal to (isolated from) conventional attributes/methods of the class. Being the same and being orthogonal at the same time is what required to be good carrier of meta information about inheritable behavior. And use of tagger classes is a way to extend and partition class's namespace into meaningful orthogonal domains, as well as to extend the notion of the meta-data tag in the domain-specific way.
203            
204             =head1 Tagger classes
205            
206             Class::Tag itself serves as tagger class, and each tagger class is a "constructor" for other tagger classes, either loadable or inlined.
207            
208             The use() of tagger class looks as if it exports chosen named tags into packages, but in fact it doesn't - tagger class itself provides samename accessor methods for those tags. As a result, tag names can be arbitrary without risk of collision, so that together with name of tagger class they can be selected to read somewhat meaningful (see examples in L) in the problem area domain that uses that specific tagger.
209            
210             =head2 Tagger class construction
211            
212             See L for description of new tagger class creation. Tagger class can be created "inline", without using separate .pm file for it.
213            
214             The value of 'tagger_class' tag is reserved for special use in the future, so it should not be used for anything to avoid incompatibility with future versions.
215            
216             =head2 Tagger class benefits
217            
218             There are a few reasons to use multiple tagger classes in addition to or instead of Class::Tag itself:
219            
220             =over
221            
222             =item Name
223            
224             Name of the tagger class can be chosen to read naturally and meaningful, in either direct or indirect method call notations i.e. reversing order of tagger and tag names (doubling readability options), with semantically meaningful tags used in the context of given application or problem area domain.
225            
226             =item Restricted tagspace
227            
228             The original Class::Tag tagger class allows to use any tag, except tag(), untag() and Perl's specials, like import(), can(), etc. are still reserved. In contrast, custom tagger classes may allow only specific tags to be used.
229            
230             =item Isolated (orthogonal) tagspace
231            
232             Each tagger class has its own orthogonal tags namespace (tagspace), so that same tags of different tagger classes do not collide:
233            
234             {
235             package Awesome;
236             use Class::Tag 'tagger_class';
237             use Awesome 'AUTOLOAD';
238            
239             package Bad;
240             use Class::Tag 'tagger_class';
241             use Bad 'AUTOLOAD';
242            
243             package Foo;
244             use Awesome 'really';
245             use Awesome { orthogonal => 'awesome' };
246             use Bad { orthogonal => 'bad' };
247             }
248            
249             really Awesome 'Foo'; # true
250             really Bad 'Foo'; # false
251             Bad->orthogonal('Foo') eq 'bad'; # true
252             Awesome->orthogonal('Foo') eq 'awesome'; # true
253            
254             Without other tagger classes the tags namespace of Class::Tag would be exposed to higher risk of tags collision, since due to global nature of Perl classes there is always a possibility of collision when same tag is used for unrelated purposes (e.g. in the same inheritance chain, etc.).
255            
256             Since tagger class tags upon use() and classes usually do not export anything, it is often useful and possible to make some existing class a tagger to tag classes that use() it. Moreover, it can be done from a distance, without cognizance of the existing class. The same also applies to modules that are not classes.
257            
258             However, making existing (non-empty) class/module a tagger class requires care to not collide with methods of that class - Class::Tag will raise an exception when such collision happens. It is better not to declare 'AUTOLOAD' for such tagger class.
259            
260             =item Meta-data domains
261            
262             Tags of different tagger classes are intended to be dedicated to defining, managing and documenting different meta-data domains. It can be meta-data associated with specific module, application, problem, algorithm, etc. In particular, tagger class is an ideal place where to document its tags.
263            
264             =back
265            
266             =head2 Declaration of tags
267            
268             Attempt to use tag that has not been declared (assuming 'AUTOLOAD' declares any tag) raises exception.
269            
270             In addition, values of declaration tags can be used to modify behavior of tags and, thus, redefine/evolve the whole notion of the tag. If tag is declared with subroutine reference value, that subroutine is called when tag is accessed:
271            
272             {
273             package Awesome; # new tagger class
274             use Class::Tag 'tagger_class'; # must be before following declarations
275             use Awesome specific_tag => \&accessor; # use \&accessor for 'specific_tag'
276             use Awesome AUTOLOAD => \&ACCESSOR; # use \&ACCESSOR for any tag
277             }
278            
279             Awesome->specific_tag( $class_or_obj, @args); # is equivalent to...
280             &accessor('Awesome', $class_or_obj, @args);
281            
282             Awesome::specific_tag( $class_or_obj, @args); # is equivalent to...
283             &accessor( undef, $class_or_obj, @args);
284            
285             Awesome->any_other_tag($class_or_obj, @args); # is equivalent to...
286             &ACCESSOR('Awesome', $class_or_obj, @args);
287            
288             Awesome::any_other_tag($class_or_obj, @args); # is equivalent to...
289             &ACCESSOR( undef, $class_or_obj, @args);
290            
291             The Awesome class in above code may also be replaced with object of Awesome class. With custom accessors as above the entire tag syntax can be used for something different.
292            
293             =head1 Traditional alternatives
294            
295             There are three natural alternative solutions: classes-as-tags, roles-as-tags and methods-as-tags. The classes-as-tags solution uses universal isa() method to see if class has specific parent, it effectively uses specific parent classes as tags. However, using parent classes just as tags is a limited solution since @ISA is used for different things and better be used for those things exclusively to avoid interferences.
296            
297             Using roles as tags do not involve modifying @ISA, but this approach relies on using single shared congested namespace, which means possibility of accidental collision, unless you specifically choose unnatural names (long, prefixed, capitalized, etc.) that are unlikely to collide or use unique names of existing modules as tags, which is an overkill in many cases.
298            
299             Moreover, classes-as-tags and roles-as-tags solutions do not allow using values for tags (unless properly overridden).
300            
301             Using methods-as-tags approach is about defining and using specific methods as tags. This approach is far better than classes-as-tags and roles-as-tags, but if specific method-tag need to be queried on unknown class/module, the following problems may arise:
302            
303             =over
304            
305             =item Name collision
306            
307             It may be that class/module have defined samename method/attribute by coincidence. Possibility of collision is considerable for short readable names (like 'is'), especially for undocumented tags that are used internally and in case of subclassing. To avoid collision method-tags usually have some unique prefix and may be in upper-case and/or starting with '_', etc. The typical solution is using name of some module as unique suffix/prefix, and this is exactly what Class::Tag does in its own flexible way:
308            
309             Foo->is_Awesome;
310            
311             Awesome->is('Foo');
312            
313             Class::Tag allows to either dedicate specific tagger class, either loadable or inlined, just to serve as effective "prefix" with arbitrary risk-free tag names, or use some existing class/module as tagger.
314            
315             =item AUTOLOAD()ing of methods and non-tagged classes/modules
316            
317             If one tries to check tag on non-tagged class/module, there will be no tag method, so call of tag method will raise an exception. This suggests can() or eval{} wrap to be always used as a precaution.
318            
319             Moreover, potential use of AUTOLOAD defeats unique prefixes in tag method names and requires always calling tag method conditional on result of prior can() (eval{} will not help in this case) checking if tag is defined:
320            
321             $tag_value = $class->is
322             if $class->can('is');
323            
324             Awesome->is($class);
325            
326             Class::Tag solve this problem.
327            
328             =item Tagging
329            
330             Tagging is essentially defining an attribute. Applying read-only tag to class is simple enough, but applying writable tag or applying tag to blessed-hash objects either ends up in writing accessor or requires use of some attributes construction module, of which Class::Tag is essentially the one:
331            
332             {
333             package Foo;
334             my $writable = 'variable';
335             sub writable { @_ > 1 ? $writable = $_[1] : $writable }
336             sub instance { @_ > 1 ? $_[0]->{instance} = $_[1] : $_[0]->{instance} }
337             }
338            
339             {
340             package Foo;
341             use Class::Tag writable => 'variable', instance => undef;
342             }
343            
344             bless $obj = {}, 'Foo';
345             Class::Tag->writable('Foo') eq 'variable';
346             Class::Tag->writable('Foo' => 'new value');
347             Class::Tag->writable('Foo') eq 'new value';
348             Class::Tag->instance($foo => 'init value');
349             Class::Tag->instance('Foo') eq 'init value';
350            
351             except Class::Tag's default accessor implements copy-on-write tag values on blessed-hash object instances (and simple tag inheritance from class for blessed-non-hashes), rather than simplistic accessor in above alternative.
352            
353             =back
354            
355             Class::Tag solves these problems by moving tag constructors and accessors to tagger class, which is far more predictable and controlled environment.
356            
357             =head1 SEE ALSO
358            
359             The Class::DOES module provide the ability to use DOES() for tagging classes with role names - see discussion in L.
360            
361             =head1 SUPPORT
362            
363             Send bug reports, patches, ideas, suggestions, feature requests or any module-related information to L. They are welcome and each carefully considered.
364            
365             In particular, if you find certain portions of this documentation either unclear, complicated or incomplete, please let me know, so that I can try to make it better.
366            
367             If you have examples of a neat usage of Class::Tag, drop a line too.
368            
369             =head1 AUTHOR
370            
371             Alexandr Kononoff (L)
372            
373             =head1 COPYRIGHT AND LICENSE
374            
375             Copyright (c) 2010 Alexandr Kononoff (L). All rights reserved.
376            
377             This program is free software; you can use, redistribute and/or modify it either under the same terms as Perl itself or, at your discretion, under following Simplified (2-clause) BSD License terms:
378            
379             Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
380            
381             * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
382             * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
383            
384             THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
385            
386             =cut
387            
388 1     1   7 no warnings;
  1         2  
  1         38  
389            
390 1     1   5 use Carp;
  1         6  
  1         109  
391 1     1   11 use Scalar::Util qw(blessed);
  1         1  
  1         1211  
392            
393             sub NAMESPACE () { 'aixfHgvpm7hgVziaO' }
394            
395 237     237   778 sub _tagged_accessor { _subnames( join '_', $_[0], NAMESPACE, $_[1] ) }
396            
397 237     237   251 sub _subnames { my $a; ($a = $_[0]) =~ s/:/_/g; return $a }
  237         586  
  237         623  
398            
399             *unimport = *untag = __PACKAGE__->new_import('unimport');
400             *import = *tag = __PACKAGE__->new_import();
401             import { __PACKAGE__ } 'AUTOLOAD';
402            
403             sub new_import {
404 14     14 0 24 my (undef, $unimport) = @_;
405            
406             return sub{
407 37     37   3500 my $self = shift;
408 37   33     149 my $tagger_class = ref($self)||$self;
409 37   33     131 my $tagged_class =
410             $Class::Tag::caller||caller;
411 37         39 $Class::Tag::caller = undef;
412            
413 37         38 my $tags;
414 37 100       150 ref $_[0] eq 'HASH'
415             ? ( $tags = $_[0] )
416             : ( @$tags{ @_ } = (1) x @_ );
417            
418 37 100       91 %$tags or $tags->{is} = 1;
419            
420 37         109 foreach my $tag (keys %$tags) {
421            
422             # bless()ings below are just for labeling (safe enough as nobody would check ref *GLOB{CODE} eq 'CODE', which becomes false unexpectedly)...
423            
424 49         85 my $tagged_accessor
425             = _tagged_accessor($tagger_class, $tag);
426 49         145 my $tag_value = bless \$tags->{$tag}, $tagger_class;
427            
428 49         104 my $tagger_accessor = join '::', $tagger_class, $tag;
429 49         84 my $tagged_accessor2 = join '::', $tagged_class, $tagged_accessor;
430 49 100       80 if ($unimport) {
431 8 50 33     33 croak("Error: tag accessor collision - alien $tag() in tagger class $tagger_class")
432             if *$tagger_accessor{CODE}
433             and ref *$tagger_accessor{CODE} ne $tagger_class; # means we may have been using alien thing as accessor
434            
435 8 50       23 undef *$tagger_accessor
436             and $tagged_class
437             eq $tagger_class;
438            
439 8         28 undef *$tagged_accessor2; # has rare name, so safe to unconditionally undef entire glob
440             }
441             else {
442             *$tagged_accessor2 = sub{
443 173 100   173   530 @_ > 1
    100          
    100          
    100          
444             ? ( _ref_type($_[0]) eq 'HASH'
445             ? bless \($_[0]->{$tagger_accessor} = $_[1]), $tagger_class
446             : \($$tag_value = $_[1]) )
447             : ( _ref_type($_[0]) eq 'HASH'
448             ? exists $_[0]->{$tagger_accessor}
449             ? bless \$_[0]->{$tagger_accessor}, $tagger_class
450             : $tag_value
451             : $tag_value )
452 41         334 };
453            
454 41 100       89 if ( $tagged_class
455             eq $tagger_class) {
456 7 50 33     28 *$tagger_accessor{CODE} and ref
457             *$tagger_accessor{CODE} ne $tagger_class and croak("Error: tag accessor collision - tagger class $tagger_class already defines or stubs $tag()");
458             *$tagger_accessor{CODE} or
459             *$tagger_accessor = bless sub{
460            
461 214     214   7133 my $sub_accessor;
462 214 100 100     1082 unless (@_ == 2 and $_[0] eq $_[1]) {
463 107 100       294 local $Class::Tag::AUTOLOAD
464             = 'AUTOLOAD'
465             if $tag eq 'AUTOLOAD';
466 107         318 $sub_accessor = $tagger_class->$tag($tagger_class);
467             }
468            
469 214 100 66     1349 unshift @_, undef # if called as function
      66        
470             unless @_ > 1
471             and ref($_[0])||$_[0] eq $tagger_class;
472            
473 214 100       496 goto &$sub_accessor
474             if ref $sub_accessor eq 'CODE';
475            
476 202 50 66     1177 ref $_[1]
477             or $_[1] =~ /^\w[\w\:]*$/
478             or return undef;
479             #or croak("Error: No valid class specified as first argument: '$_[1]'");
480            
481 202         291 my $tagged_accessor
482             = $tagged_accessor;
483 202 100       417 if ($tag eq 'AUTOLOAD') {
484 188         604 (my $AUTOLOAD = $Class::Tag::AUTOLOAD) =~ s/^.*:://;
485 188         369 $tagged_accessor =
486             _tagged_accessor($tagger_class, $AUTOLOAD);
487             }
488            
489 198         208 my $scalar_value = defined $_[0] # called as method
490 198 100 33     1420 ? &{ shift; $_[0]->can($tagged_accessor) or return undef }
  4         36  
491 202 100 66     1137 : &{*{join '::', ref($_[1])||$_[1], $tagged_accessor}{CODE} or return undef }
  4 100 33     6  
    50 33        
492             if $_[1] and (!ref $_[1] or blessed($_[1]))
493             or croak("Querying tag of untagable $_[1]");
494 173 50       846 return ref $scalar_value eq $tagger_class ? $$scalar_value : undef
495            
496             }
497 7 50       84 , $tagger_class;
498             }
499             else {
500 34 100 100     704 $tagger_class->isa( ref
501             $tagger_class->can($tag) ) or
502             $tagger_class->isa( ref
503             $tagger_class->can('AUTOLOAD') )
504             or croak("Error: tagger class $tagger_class declares no '$tag' tag: ", $tagged_class);
505             }
506             }
507            
508 48 100       5584 if ($tag eq 'tagger_class') {
509            
510 6         7 my $new_tagger_class = $tagged_class;
511 6   100     36 $INC{ join '/', split '::', "$new_tagger_class.pm" } ||= 1; # support inlined tag classes
512 6         13 my $new_import = join '::', $new_tagger_class, 'import';
513 6         10 my $new_import2 = join '::', $new_tagger_class, 'tag';
514 6         17 my $sub_import = *$new_import{CODE};
515 6         16 my $sub_import2 = *$new_import2{CODE};
516 6         10 my $new_unimport = join '::', $new_tagger_class, 'unimport';
517 6         8 my $new_unimport2 = join '::', $new_tagger_class, 'untag';
518 6         17 my $sub_unimport = *$new_unimport{CODE};
519 6         15 my $sub_unimport2 = *$new_unimport2{CODE};
520            
521 6 50       11 if ($unimport) {
522             }
523             else {
524             my $sub_new_import = sub{
525 0     0   0 my ($sub_import, $sub_wasimport) = @_;
526            
527             return #bless
528             ! $sub_wasimport
529             ? $sub_import
530             : sub{
531            
532             #goto &$sub_import;
533            
534 0         0 local $Class::Tag::caller = caller; # let &$sub_import know original caller...
535             # &$sub_import;
536 0         0 &$sub_import(@_);
537 0 0       0 goto &$sub_wasimport
538             if $sub_wasimport;
539 0 0       0 };
540             #, $tagger_class;
541 6         27 };
542            
543 6         16 *$new_import =
544             *$new_import2
545             = __PACKAGE__->new_import();
546            
547 6         21 *$new_unimport =
548             *$new_unimport2
549             = __PACKAGE__->new_import('unimport');
550             }
551             }
552             }
553             }
554 14         346 }
555            
556             sub _ref_type {
557 173 100   173   639 return undef if !ref $_[0];
558 26 50       281 return $1 if $_[0] =~ /=(\w+)/;
559 0           return ref $_[0]
560             }
561            
562             1;
563