File Coverage

blib/lib/Class/Tag.pm
Criterion Covered Total %
statement 67 80 83.7
branch 31 60 51.6
condition 16 41 39.0
subroutine 11 12 91.6
pod 0 1 0.0
total 125 194 64.4


line stmt bran cond sub pod time code
1             # WARNING! This file is automatically generated. Any changes here will be lost. Edit the source file in CPAN devtree instead!
2            
3            
4             package Class::Tag;
5            
6             #use 5.006;
7            
8 1     1   5 use strict qw[vars subs];
  1         2  
  1         130  
9             $Class::Tag::VERSION = '0.09';
10            
11             =head1 NAME
12            
13             Class::Tag - programmatically label (mark) classes, methods, roles and modules with meta-data tags (key/value pairs) and query those tags
14            
15             =head1 Warning
16            
17             Any specific interface that Class::Tag exposes may change (as it already did) until version 1.0 is reached.
18            
19             =head1 SYNOPSIS
20            
21             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.
22            
23             Directly using Class::Tag as tagger:
24            
25             package Foo;
26             use Class::Tag 'tagged'; # tagging Foo class with 'tagged' tag
27             tag Class::Tag 'tagged'; # same, but at run-time
28            
29             # query 'tagged' tag on the Foo and Bar...
30             require Foo; # if necessary
31             require Bar; # if necessary
32             Class::Tag->tagged('Foo'); # true
33             Class::Tag->tagged('Bar'); # false
34            
35             # remove 'tagged' tag from Foo...
36             #no Class::Tag 'tagged'; # at compile-time, so will not work - instead...
37             untag Class::Tag 'tagged'; # at run-time
38             Class::Tag->tagged('Foo'); # false
39            
40             If no tags are given, the 'is' tag is assumed:
41            
42             package Foo;
43             use Class::Tag; # equivalent to...
44             use Class::Tag 'is'; # same
45             use Class::Tag (); # no tagging
46            
47             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:
48            
49             {
50             # this block can be used as "inline" tagger class definition
51             # or contents of this block can be loaded from Awesome.pm
52            
53             package Awesome; # new tagger class
54             use Class::Tag 'tagger_class'; # must be before following declarations
55             use Awesome 'specific_tag'; # declares 'specific_tag' for use
56             use Awesome 'AUTOLOAD'; # declares that any tag can be used
57            
58             1;
59             }
60            
61             Class::Tag->tagger_class('Awesome'); # true
62            
63             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.
64            
65             The Class::Tag itself is somewhat similar to the following implicit declaration:
66            
67             package Class::Tag;
68             use Class::Tag 'tagger_class';
69             use Class::Tag 'AUTOLOAD';
70            
71             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.
72            
73             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:
74            
75             Using default 'is' tag:
76            
77             package Foo;
78             use Awesome;
79             use Awesome 'is'; # same
80             use Awesome { is => 1 }; # same
81            
82             require Foo; # required before next checks...
83             require Bar;
84            
85             is Awesome 'Foo'; # true
86             is Awesome 'Bar'; # false
87            
88             Awesome->is('Foo'); # true
89             Awesome->is('Bar'); # false
90            
91             $obj = bless {}, 'Foo';
92            
93             is Awesome $obj; # true
94             Awesome->is($obj); # true
95            
96             $obj = bless {}, 'Bar';
97            
98             is Awesome $obj; # false
99             Awesome->is($obj); # false
100            
101             Using tags 'class' and 'pureperl':
102            
103             package Foo;
104             # tag class Foo with tags 'class' and 'pureperl' of Awesome tagger class...
105             use Awesome 'class';
106             use Awesome 'pureperl';
107             use Awesome 'class', 'pureperl'; # same
108             use Awesome { class => 1, pureperl => 1 }; # same
109            
110             require Foo; # required before next checks...
111             require Bar;
112            
113             Awesome->class( 'Foo'); # true
114             Awesome->pureperl('Foo'); # true
115             Awesome->class( 'Bar'); # false
116             Awesome->pureperl('Bar'); # false
117            
118             Using key/value pairs as tags (tag values):
119            
120             package Foo;
121             use Awesome { class => 'is cool', author => 'metadoo' };
122            
123             Awesome->class( 'Foo') eq 'is cool'; # true
124             Awesome->author('Foo') eq 'metadoo'; # true
125            
126             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:
127            
128             $foo = bless {}, 'Foo';
129            
130             Awesome->class( $foo) eq 'is cool'; # true
131             Awesome->author($foo) eq 'metadoo'; # true (inheriting)
132            
133             Awesome->class( 'Foo', 'pupe-perl') eq 'pupe-perl'; # true
134             Awesome->class( 'Foo') eq 'pupe-perl'; # true
135             Awesome->class( $foo) eq 'pupe-perl'; # true (inheriting)
136             Awesome->class( $foo, 'pupe-perl too') eq 'pupe-perl too'; # true (copy-on-write)
137             Awesome->class( $foo) eq 'pupe-perl too'; # true (copy-on-write)
138             Awesome->class( 'Foo') eq 'pupe-perl'; # true (unmodified)
139            
140             Inheriting tags, using for example the default 'is' tag:
141            
142             package Foo;
143             use Awesome;
144             use Awesome 'is'; # same
145            
146             @Bar::ISA = 'Foo';
147            
148             Awesome->is('Foo'); # true
149             Awesome->is('Bar'); # true ('is' tag inherited)
150             Awesome::is('Foo'); # true
151             Awesome::is('Bar'); # false (no tag inheritance)
152            
153             =head1 DESCRIPTION
154            
155             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.
156            
157             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.
158            
159             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.
160            
161             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:
162            
163             package Zoo;
164            
165             sub foo { 1 }
166             use Meta foo => { is => 'ro', returns => 'boolean' }; # 1-st "meta-layer"
167             use Meta2 foo => { author => 'metadoo', doc => 'is dead-simple' }; # 2-nd "meta-layer"
168            
169             Such use opens possibilities for meta-programming and introspection. For example, method can access its own meta-data as follows:
170            
171             sub foo { Meta->foo( ref($_[0])||$_[0] ) }
172             sub foo { Meta->foo( $_[0] ) } # nearly (but not exactly) same
173            
174             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.
175            
176             =head1 Tagger classes
177            
178             Class::Tag itself serves as tagger class, and each tagger class is a "constructor" for other tagger classes, either loadable or inlined.
179            
180             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.
181            
182             =head2 Tagger class construction
183            
184             See L for description of new tagger class creation. Tagger class can be created "inline", without using separate .pm file for it.
185            
186             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.
187            
188             =head2 Tagger class benefits
189            
190             There are a few reasons to use multiple tagger classes in addition to or instead of Class::Tag itself:
191            
192             =over
193            
194             =item Name
195            
196             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.
197            
198             =item Restricted tagspace
199            
200             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.
201            
202             =item Isolated (orthogonal) tagspace
203            
204             Each tagger class has its own orthogonal tags namespace (tagspace), so that same tags of different tagger classes do not collide:
205            
206             package Awesome;
207             use Class::Tag 'tagger_class';
208             use Awesome 'AUTOLOAD';
209            
210             package Bad;
211             use Class::Tag 'tagger_class';
212             use Bad 'AUTOLOAD';
213            
214             package Foo;
215             use Awesome 'really';
216             use Awesome { orthogonal => 'awesome' };
217             use Bad { orthogonal => 'bad' };
218            
219             really Awesome 'Foo'; # true
220             really Bad 'Foo'; # false
221             Bad->orthogonal('Foo') eq 'bad'; # true
222             Awesome->orthogonal('Foo') eq 'awesome'; # true
223            
224             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.).
225            
226             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.
227            
228             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.
229            
230             =item Meta-data domains
231            
232             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.
233            
234             =back
235            
236             =head2 Declaration of tags
237            
238             Attempt to use tag that has not been declared (assuming 'AUTOLOAD' declares any tag) raises exception.
239            
240             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:
241            
242             package Awesome; # new tagger class
243             use Class::Tag 'tagger_class'; # must be before following declarations
244             use Awesome specific_tag => \&accessor; # use \&accessor for 'specific_tag'
245             use Awesome AUTOLOAD => \&ACCESSOR; # use \&ACCESSOR for any tag
246            
247             Awesome->specific_tag( $class_or_obj, @args); # is equivalent to...
248             &accessor('Awesome', $class_or_obj, @args);
249            
250             Awesome::specific_tag( $class_or_obj, @args); # is equivalent to...
251             &accessor( undef, $class_or_obj, @args);
252            
253             Awesome->any_other_tag($class_or_obj, @args); # is equivalent to...
254             &ACCESSOR('Awesome', $class_or_obj, @args);
255            
256             Awesome::any_other_tag($class_or_obj, @args); # is equivalent to...
257             &ACCESSOR( undef, $class_or_obj, @args);
258            
259             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.
260            
261             =head1 Traditional alternatives
262            
263             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.
264            
265             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.
266            
267             Moreover, classes-as-tags and roles-as-tags solutions do not allow using values for tags (unless properly overridden).
268            
269             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:
270            
271             =over
272            
273             =item Name collision
274            
275             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:
276            
277             Foo->is_Awesome;
278            
279             Awesome->is('Foo');
280            
281             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.
282            
283             =item AUTOLOAD()ing of methods and non-tagged classes/modules
284            
285             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.
286            
287             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:
288            
289             $tag_value = $class->is
290             if $class->can('is');
291            
292             Awesome->is($class);
293            
294             Class::Tag solve this problem.
295            
296             =item Tagging
297            
298             Tagging is essentially defining an attribute. Applying tag to class is simple enough, but applying tag to blessed-hash objects ends up in writing accessor, so it requires use of some attributes construction module, of which Class::Tag is essentially the one:
299            
300             package Foo;
301             bless $obj = {}, 'Foo';
302            
303             sub Foo::is_Awesome { 'old_value' }; # compile-time tagging
304             *Foo::is_Awesome = sub { 'old_value' };
305             *Foo::is_Awesome = sub { 'new_value' };
306             # tagging object instance of the class...
307             sub Foo::is_Awesome { @_ > 1 ? $_[0]->{is_Awesome} = $_[1] : $_[0]->{is_Awesome} }
308             $obj->is_Awesome('new_value');
309            
310             use Awesome is => 'old_value'; # compile-time tagging
311             is Awesome 'Foo' => 'old_value';
312             is Awesome 'Foo' => 'new_value';
313             is Awesome $obj => 'new_value';
314            
315             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.
316            
317             =back
318            
319             Class::Tag solves these problems by moving tag constructors and accessors to tagger class, which is far more predictable and controlled environment.
320            
321             =head1 SEE ALSO
322            
323             The Class::DOES module provide the ability to use DOES() for tagging classes with role names - see discusssion in L.
324            
325             =head1 SUPPORT
326            
327             Send bug reports, patches, ideas, suggestions, feature requests or any module-related information to L. They are welcome and each carefully considered.
328            
329             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.
330            
331             If you have examples of a neat usage of Class::Tag, drop a line too.
332            
333             =head1 AUTHOR
334            
335             Alexandr Kononoff (L)
336            
337             =head1 COPYRIGHT AND LICENSE
338            
339             Copyright (c) 2010 Alexandr Kononoff (L). All rights reserved.
340            
341             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:
342            
343             Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
344            
345             * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
346             * 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.
347            
348             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.
349            
350             =cut
351            
352 1     1   4 no warnings;
  1         2  
  1         30  
353            
354 1     1   4 use Carp;
  1         2  
  1         62  
355 1     1   4 use Scalar::Util qw(blessed);
  1         1  
  1         1394  
356            
357             sub NAMESPACE () { 'aixfHgvpm7hgVziaO' }
358            
359 7     7   36 sub _tagged_accessor { _subnames( join '_', $_[0], NAMESPACE, $_[1] ) }
360            
361 7     7   9 sub _subnames { my $a; ($a = $_[0]) =~ s/:/_/g; return $a }
  7         32  
  7         19  
362            
363             *unimport = *untag = __PACKAGE__->new_import('unimport');
364             *import = *tag = __PACKAGE__->new_import();
365             import { __PACKAGE__ } 'AUTOLOAD';
366            
367             sub new_import {
368 4     4 0 6 my (undef, $unimport) = @_;
369            
370             return sub{
371 7     7   13 my $self = shift;
372 7   33     37 my $tagger_class = ref($self)||$self;
373 7   33     36 my $tagged_class =
374             $Class::Tag::caller||caller;
375 7         8 $Class::Tag::caller = undef;
376            
377 7         8 my $tags;
378 7 50       39 ref $_[0] eq 'HASH'
379             ? ( $tags = $_[0] )
380             : ( @$tags{ @_ } = (1) x @_ );
381            
382 7 100       24 %$tags or $tags->{is} = 1;
383            
384 7         23 foreach my $tag (keys %$tags) {
385            
386             # bless()ings below are just for labeling (safe enough as nobody would check ref *GLOB{CODE} eq 'CODE', which becomes false unexpectedly)...
387            
388 7         16 my $tagged_accessor
389             = _tagged_accessor($tagger_class, $tag);
390 7         23 my $tag_value = bless \$tags->{$tag}, $tagger_class;
391            
392 7         18 my $tagger_accessor = join '::', $tagger_class, $tag;
393 7         22 my $tagged_accessor2 = join '::', $tagged_class, $tagged_accessor;
394 7 50       16 if ($unimport) {
395 0 0 0     0 croak("Error: tag accessor collision - alien $tag() in tagger class $tagger_class")
396             if *$tagger_accessor{CODE}
397             and ref *$tagger_accessor{CODE} ne $tagger_class; # means we may have been using alien thing as accessor
398            
399 0 0       0 undef *$tagger_accessor
400             and $tagged_class
401             eq $tagger_class;
402            
403 0         0 undef *$tagged_accessor2; # has rare name, so safe to unconditionally undef entire glob
404             }
405             else {
406             *$tagged_accessor2 = sub{
407 117 0   117   348 @_ > 1
    50          
    100          
    50          
408             ? ( _ref_type($_[0]) eq 'HASH'
409             ? bless \($_[0]->{$tagger_accessor} = $_[1]), $tagger_class
410             : \($$tag_value = $_[1]) )
411             : ( _ref_type($_[0]) eq 'HASH'
412             ? exists $_[0]->{$tagger_accessor}
413             ? bless \$_[0]->{$tagger_accessor}, $tagger_class
414             : $tag_value
415             : $tag_value )
416 7         59 };
417            
418 7 100       20 if ( $tagged_class
419             eq $tagger_class) {
420 2 50 33     10 *$tagger_accessor{CODE} and ref
421             *$tagger_accessor{CODE} ne $tagger_class and croak("Error: tag accessor collision - tagger class $tagger_class already defines or stubs $tag()");
422             *$tagger_accessor{CODE} or
423             *$tagger_accessor = bless sub{
424            
425 126     126   129 my $sub_accessor;
426 126 100 66     631 unless (@_ == 2 and $_[0] eq $_[1]) {
427 63 50       136 local $Class::Tag::AUTOLOAD
428             = 'AUTOLOAD'
429             if $tag eq 'AUTOLOAD';
430 63         238 $sub_accessor = $tagger_class->$tag($tagger_class);
431             }
432            
433 126 50 33     674 unshift @_, undef # if called as function
      33        
434             unless @_ > 1
435             and ref($_[0])||$_[0] eq $tagger_class;
436            
437 126 50       246 goto &$sub_accessor
438             if ref $sub_accessor eq 'CODE';
439            
440 126 50 66     565 ref $_[1]
441             or $_[1] =~ /^\w[\w\:]*$/
442             or return undef;
443             #or croak("Error: No valid class specified as first argument: '$_[1]'");
444            
445 126         168 my $tagged_accessor
446             = $tagged_accessor;
447 126 50       263 if ($tag eq 'AUTOLOAD') {
448 0         0 (my $AUTOLOAD = $Class::Tag::AUTOLOAD) =~ s/^.*:://;
449 0         0 $tagged_accessor =
450             _tagged_accessor($tagger_class, $AUTOLOAD);
451             }
452            
453 126         127 my $scalar_value = defined $_[0] # called as method
454 126 100 0     2000 ? &{ shift; $_[0]->can($tagged_accessor) or return undef }
  0         0  
455 126 0 66     793 : &{*{join '::', ref($_[1])||$_[1], $tagged_accessor}{CODE} or return undef }
  0 50 33     0  
    50 33        
456             if $_[1] and (!ref $_[1] or blessed($_[1]))
457             or croak("Querying tag of untagable $_[1]");
458 117 50       678 return ref $scalar_value eq $tagger_class ? $$scalar_value : undef
459            
460             }
461 2 50       21 , $tagger_class;
462             }
463             else {
464 5 50 66     77 $tagger_class->isa( ref
465             $tagger_class->can($tag) ) or
466             $tagger_class->isa( ref
467             $tagger_class->can('AUTOLOAD') )
468             or croak("Error: tagger class $tagger_class declares no '$tag' tag: ", $tagged_class);
469             }
470             }
471            
472 7 100       375 if ($tag eq 'tagger_class') {
473            
474 1         1 my $new_tagger_class = $tagged_class;
475 1   50     8 $INC{ join '/', split '::', "$new_tagger_class.pm" } ||= 1; # support inlined tag classes
476 1         3 my $new_import = join '::', $new_tagger_class, 'import';
477 1         2 my $new_import2 = join '::', $new_tagger_class, 'tag';
478 1         3 my $sub_import = *$new_import{CODE};
479 1         3 my $sub_import2 = *$new_import2{CODE};
480 1         2 my $new_unimport = join '::', $new_tagger_class, 'unimport';
481 1         2 my $new_unimport2 = join '::', $new_tagger_class, 'untag';
482 1         3 my $sub_unimport = *$new_unimport{CODE};
483 1         3 my $sub_unimport2 = *$new_unimport2{CODE};
484            
485 1 50       2 if ($unimport) {
486             }
487             else {
488             my $sub_new_import = sub{
489 0     0   0 my ($sub_import, $sub_wasimport) = @_;
490            
491             return #bless
492             ! $sub_wasimport
493             ? $sub_import
494             : sub{
495            
496             #goto &$sub_import;
497            
498 0         0 local $Class::Tag::caller = caller; # let &$sub_import know original caller...
499             # &$sub_import;
500 0         0 &$sub_import(@_);
501 0 0       0 goto &$sub_wasimport
502             if $sub_wasimport;
503 0 0       0 };
504             #, $tagger_class;
505 1         5 };
506            
507 1         3 *$new_import =
508             *$new_import2
509             = __PACKAGE__->new_import();
510            
511 1         3 *$new_unimport =
512             *$new_unimport2
513             = __PACKAGE__->new_import('unimport');
514             }
515             }
516             }
517             }
518 4         68 }
519            
520             sub _ref_type {
521 117 100   117   371 return undef if !ref $_[0];
522 54 50       588 return $1 if $_[0] =~ /=(\w+)/;
523 0           return ref $_[0]
524             }
525            
526             1;
527