File Coverage

blib/lib/Class/Tag.pm
Criterion Covered Total %
statement 64 77 83.1
branch 31 58 53.4
condition 13 32 40.6
subroutine 10 11 90.9
pod 0 1 0.0
total 118 179 65.9


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