| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | # This file was generated by Mousse::Maker 0.13 from Mouse 0.93. | 
| 2 |  |  |  |  |  |  | # | 
| 3 |  |  |  |  |  |  | # ANY CHANGES MADE HERE WILL BE LOST! | 
| 4 | 1 |  |  | 1 |  | 33615 | use strict; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 37 |  | 
| 5 | 1 |  |  | 1 |  | 5 | use warnings; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 206 |  | 
| 6 |  |  |  |  |  |  |  | 
| 7 |  |  |  |  |  |  | # tell Perl we already have all of the Mousse files loaded: | 
| 8 |  |  |  |  |  |  | BEGIN { | 
| 9 | 1 |  |  | 1 |  | 3 | $INC{'Mousse.pm'}                             = __FILE__; | 
| 10 | 1 |  |  |  |  | 2 | $INC{'Mousse/Util.pm'}                        = __FILE__; | 
| 11 | 1 |  |  |  |  | 3 | $INC{'Mousse/PurePerl.pm'}                    = __FILE__; | 
| 12 | 1 |  |  |  |  | 2 | $INC{'Mousse/Role.pm'}                        = __FILE__; | 
| 13 | 1 |  |  |  |  | 2 | $INC{'Mousse/Exporter.pm'}                    = __FILE__; | 
| 14 | 1 |  |  |  |  | 3 | $INC{'Mousse/Object.pm'}                      = __FILE__; | 
| 15 | 1 |  |  |  |  | 3 | $INC{'Mousse/Util/TypeConstraints.pm'}        = __FILE__; | 
| 16 | 1 |  |  |  |  | 2 | $INC{'Mousse/Util/MetaRole.pm'}               = __FILE__; | 
| 17 | 1 |  |  |  |  | 2 | $INC{'Mousse/Meta/Module.pm'}                 = __FILE__; | 
| 18 | 1 |  |  |  |  | 1 | $INC{'Mousse/Meta/TypeConstraint.pm'}         = __FILE__; | 
| 19 | 1 |  |  |  |  | 3 | $INC{'Mousse/Meta/Method.pm'}                 = __FILE__; | 
| 20 | 1 |  |  |  |  | 2 | $INC{'Mousse/Meta/Attribute.pm'}              = __FILE__; | 
| 21 | 1 |  |  |  |  | 2 | $INC{'Mousse/Meta/Role.pm'}                   = __FILE__; | 
| 22 | 1 |  |  |  |  | 3 | $INC{'Mousse/Meta/Class.pm'}                  = __FILE__; | 
| 23 | 1 |  |  |  |  | 2 | $INC{'Mousse/Meta/Method/Delegation.pm'}      = __FILE__; | 
| 24 | 1 |  |  |  |  | 2 | $INC{'Mousse/Meta/Method/Destructor.pm'}      = __FILE__; | 
| 25 | 1 |  |  |  |  | 9 | $INC{'Mousse/Meta/Method/Constructor.pm'}     = __FILE__; | 
| 26 | 1 |  |  |  |  | 2 | $INC{'Mousse/Meta/Method/Accessor.pm'}        = __FILE__; | 
| 27 | 1 |  |  |  |  | 2 | $INC{'Mousse/Meta/Role/Method.pm'}            = __FILE__; | 
| 28 | 1 |  |  |  |  | 10 | $INC{'Mousse/Meta/Role/Application.pm'}       = __FILE__; | 
| 29 | 1 |  |  |  |  | 104 | $INC{'Mousse/Meta/Role/Composite.pm'}         = __FILE__; | 
| 30 |  |  |  |  |  |  | } | 
| 31 |  |  |  |  |  |  |  | 
| 32 |  |  |  |  |  |  | # and now their contents | 
| 33 |  |  |  |  |  |  |  | 
| 34 |  |  |  |  |  |  | # Contents of Mouse::PurePerl | 
| 35 |  |  |  |  |  |  | package Mousse::PurePerl; | 
| 36 |  |  |  |  |  |  | # The pure Perl backend for Mousse | 
| 37 |  |  |  |  |  |  | package Mousse::Util; | 
| 38 | 1 |  |  | 1 |  | 21 | use strict; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 37 |  | 
| 39 | 1 |  |  | 1 |  | 6 | use warnings; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 33 |  | 
| 40 | 1 |  |  | 1 |  | 5 | use warnings FATAL => 'redefine'; # to avoid to load Mousse::PurePerl twice | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 45 |  | 
| 41 |  |  |  |  |  |  |  | 
| 42 | 1 |  |  | 1 |  | 6 | use Scalar::Util (); | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 15 |  | 
| 43 | 1 |  |  | 1 |  | 13 | use B (); | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 583 |  | 
| 44 |  |  |  |  |  |  |  | 
| 45 |  |  |  |  |  |  | require Mousse::Util; | 
| 46 |  |  |  |  |  |  |  | 
| 47 |  |  |  |  |  |  | # taken from Class/MOP.pm | 
| 48 |  |  |  |  |  |  | sub is_valid_class_name { | 
| 49 | 5 |  |  | 5 | 0 | 6 | my $class = shift; | 
| 50 |  |  |  |  |  |  |  | 
| 51 | 5 | 50 |  |  |  | 12 | return 0 if ref($class); | 
| 52 | 5 | 50 |  |  |  | 12 | return 0 unless defined($class); | 
| 53 |  |  |  |  |  |  |  | 
| 54 | 5 | 50 |  |  |  | 48 | return 1 if $class =~ /\A \w+ (?: :: \w+ )* \z/xms; | 
| 55 |  |  |  |  |  |  |  | 
| 56 | 0 |  |  |  |  | 0 | return 0; | 
| 57 |  |  |  |  |  |  | } | 
| 58 |  |  |  |  |  |  |  | 
| 59 |  |  |  |  |  |  | sub is_class_loaded { | 
| 60 | 5 |  |  | 5 | 0 | 6 | my $class = shift; | 
| 61 |  |  |  |  |  |  |  | 
| 62 | 5 | 50 | 33 |  |  | 37 | return 0 if ref($class) || !defined($class) || !length($class); | 
|  |  |  | 33 |  |  |  |  | 
| 63 |  |  |  |  |  |  |  | 
| 64 |  |  |  |  |  |  | # walk the symbol table tree to avoid autovififying | 
| 65 |  |  |  |  |  |  | # \*{${main::}{"Foo::"}{"Bar::"}} == \*main::Foo::Bar:: | 
| 66 |  |  |  |  |  |  |  | 
| 67 | 5 |  |  |  |  | 9 | my $pack = \%::; | 
| 68 | 5 |  |  |  |  | 19 | foreach my $part (split('::', $class)) { | 
| 69 | 13 |  |  |  |  | 17 | $part .= '::'; | 
| 70 | 13 | 50 |  |  |  | 30 | return 0 if !exists $pack->{$part}; | 
| 71 |  |  |  |  |  |  |  | 
| 72 | 13 |  |  |  |  | 24 | my $entry = \$pack->{$part}; | 
| 73 | 13 | 50 |  |  |  | 30 | return 0 if ref($entry) ne 'GLOB'; | 
| 74 | 13 |  |  |  |  | 12 | $pack = *{$entry}{HASH}; | 
|  | 13 |  |  |  |  | 35 |  | 
| 75 |  |  |  |  |  |  | } | 
| 76 |  |  |  |  |  |  |  | 
| 77 | 5 | 50 |  |  |  | 9 | return 0 if !%{$pack}; | 
|  | 5 |  |  |  |  | 25 |  | 
| 78 |  |  |  |  |  |  |  | 
| 79 |  |  |  |  |  |  | # check for $VERSION or @ISA | 
| 80 | 0 |  |  |  |  | 0 | return 1 if exists $pack->{VERSION} | 
| 81 | 5 | 0 | 33 |  |  | 18 | && defined *{$pack->{VERSION}}{SCALAR} && defined ${ $pack->{VERSION} }; | 
|  | 0 |  | 33 |  |  | 0 |  | 
| 82 | 1 |  |  |  |  | 15 | return 1 if exists $pack->{ISA} | 
| 83 | 5 | 50 | 66 |  |  | 17 | && defined *{$pack->{ISA}}{ARRAY} && @{ $pack->{ISA} } != 0; | 
|  | 1 |  | 66 |  |  | 9 |  | 
| 84 |  |  |  |  |  |  |  | 
| 85 |  |  |  |  |  |  | # check for any method | 
| 86 | 4 |  |  |  |  | 6 | foreach my $name( keys %{$pack} ) { | 
|  | 4 |  |  |  |  | 17 |  | 
| 87 | 8 |  |  |  |  | 16 | my $entry = \$pack->{$name}; | 
| 88 | 8 | 100 | 66 |  |  | 19 | return 1 if ref($entry) ne 'GLOB' || defined *{$entry}{CODE}; | 
|  | 8 |  |  |  |  | 41 |  | 
| 89 |  |  |  |  |  |  | } | 
| 90 |  |  |  |  |  |  |  | 
| 91 |  |  |  |  |  |  | # fail | 
| 92 | 0 |  |  |  |  | 0 | return 0; | 
| 93 |  |  |  |  |  |  | } | 
| 94 |  |  |  |  |  |  |  | 
| 95 |  |  |  |  |  |  |  | 
| 96 |  |  |  |  |  |  | # taken from Sub::Identify | 
| 97 |  |  |  |  |  |  | sub get_code_info { | 
| 98 | 6 |  |  | 6 | 0 | 9 | my ($coderef) = @_; | 
| 99 | 6 | 50 |  |  |  | 12 | ref($coderef) or return; | 
| 100 |  |  |  |  |  |  |  | 
| 101 | 6 |  |  |  |  | 31 | my $cv = B::svref_2object($coderef); | 
| 102 | 6 | 50 |  |  |  | 37 | $cv->isa('B::CV') or return; | 
| 103 |  |  |  |  |  |  |  | 
| 104 | 6 |  |  |  |  | 19 | my $gv = $cv->GV; | 
| 105 | 6 | 50 |  |  |  | 26 | $gv->isa('B::GV') or return; | 
| 106 |  |  |  |  |  |  |  | 
| 107 | 6 |  |  |  |  | 53 | return ($gv->STASH->NAME, $gv->NAME); | 
| 108 |  |  |  |  |  |  | } | 
| 109 |  |  |  |  |  |  |  | 
| 110 |  |  |  |  |  |  | sub get_code_package{ | 
| 111 | 0 |  |  | 0 | 0 | 0 | my($coderef) = @_; | 
| 112 |  |  |  |  |  |  |  | 
| 113 | 0 |  |  |  |  | 0 | my $cv = B::svref_2object($coderef); | 
| 114 | 0 | 0 |  |  |  | 0 | $cv->isa('B::CV') or return ''; | 
| 115 |  |  |  |  |  |  |  | 
| 116 | 0 |  |  |  |  | 0 | my $gv = $cv->GV; | 
| 117 | 0 | 0 |  |  |  | 0 | $gv->isa('B::GV') or return ''; | 
| 118 |  |  |  |  |  |  |  | 
| 119 | 0 |  |  |  |  | 0 | return $gv->STASH->NAME; | 
| 120 |  |  |  |  |  |  | } | 
| 121 |  |  |  |  |  |  |  | 
| 122 |  |  |  |  |  |  | sub get_code_ref{ | 
| 123 | 0 |  |  | 0 | 0 | 0 | my($package, $name) = @_; | 
| 124 | 1 |  |  | 1 |  | 6 | no strict 'refs'; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 37 |  | 
| 125 | 1 |  |  | 1 |  | 4 | no warnings 'once'; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 45 |  | 
| 126 | 1 |  |  | 1 |  | 5 | use warnings FATAL => 'uninitialized'; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 1302 |  | 
| 127 | 0 |  |  |  |  | 0 | return *{$package . '::' . $name}{CODE}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 128 |  |  |  |  |  |  | } | 
| 129 |  |  |  |  |  |  |  | 
| 130 |  |  |  |  |  |  | sub generate_isa_predicate_for { | 
| 131 | 2 |  |  | 2 | 0 | 3 | my($for_class, $name) = @_; | 
| 132 |  |  |  |  |  |  |  | 
| 133 | 2 | 0 |  | 0 |  | 8 | my $predicate = sub{ Scalar::Util::blessed($_[0]) && $_[0]->isa($for_class) }; | 
|  | 0 |  |  |  |  | 0 |  | 
| 134 |  |  |  |  |  |  |  | 
| 135 | 2 | 50 |  |  |  | 5 | if(defined $name){ | 
| 136 | 0 |  |  |  |  | 0 | Mousse::Util::install_subroutines(scalar caller, $name => $predicate); | 
| 137 | 0 |  |  |  |  | 0 | return; | 
| 138 |  |  |  |  |  |  | } | 
| 139 |  |  |  |  |  |  |  | 
| 140 | 2 |  |  |  |  | 8 | return $predicate; | 
| 141 |  |  |  |  |  |  | } | 
| 142 |  |  |  |  |  |  |  | 
| 143 |  |  |  |  |  |  | sub generate_can_predicate_for { | 
| 144 | 3 |  |  | 3 | 0 | 6 | my($methods_ref, $name) = @_; | 
| 145 |  |  |  |  |  |  |  | 
| 146 | 3 |  |  |  |  | 4 | my @methods = @{$methods_ref}; | 
|  | 3 |  |  |  |  | 7 |  | 
| 147 |  |  |  |  |  |  |  | 
| 148 |  |  |  |  |  |  | my $predicate = sub{ | 
| 149 | 5 |  |  | 5 |  | 8 | my($instance) = @_; | 
| 150 | 5 | 100 |  |  |  | 19 | if(Scalar::Util::blessed($instance)){ | 
| 151 | 1 |  |  |  |  | 3 | foreach my $method(@methods){ | 
| 152 | 1 | 50 |  |  |  | 15 | if(!$instance->can($method)){ | 
| 153 | 1 |  |  |  |  | 5 | return 0; | 
| 154 |  |  |  |  |  |  | } | 
| 155 |  |  |  |  |  |  | } | 
| 156 | 0 |  |  |  |  | 0 | return 1; | 
| 157 |  |  |  |  |  |  | } | 
| 158 | 4 |  |  |  |  | 22 | return 0; | 
| 159 | 3 |  |  |  |  | 11 | }; | 
| 160 |  |  |  |  |  |  |  | 
| 161 | 3 | 50 |  |  |  | 9 | if(defined $name){ | 
| 162 | 3 |  |  |  |  | 8 | Mousse::Util::install_subroutines(scalar caller, $name => $predicate); | 
| 163 | 3 |  |  |  |  | 5 | return; | 
| 164 |  |  |  |  |  |  | } | 
| 165 |  |  |  |  |  |  |  | 
| 166 | 0 |  |  |  |  | 0 | return $predicate; | 
| 167 |  |  |  |  |  |  | } | 
| 168 |  |  |  |  |  |  |  | 
| 169 |  |  |  |  |  |  | package Mousse::Util::TypeConstraints; | 
| 170 |  |  |  |  |  |  |  | 
| 171 |  |  |  |  |  |  |  | 
| 172 | 0 |  |  | 0 | 0 | 0 | sub Any        { 1 } | 
| 173 | 0 |  |  | 0 | 0 | 0 | sub Item       { 1 } | 
| 174 |  |  |  |  |  |  |  | 
| 175 | 0 | 0 |  | 0 | 0 | 0 | sub Bool       { !$_[0] || $_[0] eq '1' } | 
| 176 | 0 |  |  | 0 | 0 | 0 | sub Undef      { !defined($_[0]) } | 
| 177 | 0 |  |  | 0 | 0 | 0 | sub Defined    {  defined($_[0])  } | 
| 178 | 0 | 0 |  | 0 | 0 | 0 | sub Value      {  defined($_[0]) && !ref($_[0]) } | 
| 179 | 0 |  |  | 0 | 0 | 0 | sub Num        {  Scalar::Util::looks_like_number($_[0]) } | 
| 180 |  |  |  |  |  |  | sub Str        { | 
| 181 |  |  |  |  |  |  | # We need to use a copy here to flatten MAGICs, for instance as in | 
| 182 |  |  |  |  |  |  | # Str( substr($_, 0, 42) ). | 
| 183 | 0 |  |  | 0 | 0 | 0 | my($value) = @_; | 
| 184 | 0 |  | 0 |  |  | 0 | return defined($value) && ref(\$value) eq 'SCALAR'; | 
| 185 |  |  |  |  |  |  | } | 
| 186 |  |  |  |  |  |  | sub Int        { | 
| 187 |  |  |  |  |  |  | # We need to use a copy here to save the original internal SV flags. | 
| 188 | 0 |  |  | 0 | 0 | 0 | my($value) = @_; | 
| 189 | 0 |  | 0 |  |  | 0 | return defined($value) && $value =~ /\A -? [0-9]+  \z/xms; | 
| 190 |  |  |  |  |  |  | } | 
| 191 |  |  |  |  |  |  |  | 
| 192 | 0 |  |  | 0 | 0 | 0 | sub Ref        { ref($_[0]) } | 
| 193 |  |  |  |  |  |  | sub ScalarRef  { | 
| 194 | 0 |  |  | 0 | 0 | 0 | my($value) = @_; | 
| 195 | 0 |  | 0 |  |  | 0 | return ref($value) eq 'SCALAR' || ref($value) eq 'REF'; | 
| 196 |  |  |  |  |  |  | } | 
| 197 | 0 |  |  | 0 | 0 | 0 | sub ArrayRef   { ref($_[0]) eq 'ARRAY'  } | 
| 198 | 0 |  |  | 0 | 0 | 0 | sub HashRef    { ref($_[0]) eq 'HASH'   } | 
| 199 | 0 |  |  | 0 | 0 | 0 | sub CodeRef    { ref($_[0]) eq 'CODE'   } | 
| 200 | 0 |  |  | 0 | 0 | 0 | sub RegexpRef  { ref($_[0]) eq 'Regexp' } | 
| 201 | 0 |  |  | 0 | 0 | 0 | sub GlobRef    { ref($_[0]) eq 'GLOB'   } | 
| 202 |  |  |  |  |  |  |  | 
| 203 |  |  |  |  |  |  | sub FileHandle { | 
| 204 | 0 |  |  | 0 | 0 | 0 | my($value) = @_; | 
| 205 | 0 |  | 0 |  |  | 0 | return Scalar::Util::openhandle($value) | 
| 206 |  |  |  |  |  |  | || (Scalar::Util::blessed($value) && $value->isa("IO::Handle")) | 
| 207 |  |  |  |  |  |  | } | 
| 208 |  |  |  |  |  |  |  | 
| 209 | 0 | 0 |  | 0 | 0 | 0 | sub Object     { Scalar::Util::blessed($_[0]) && ref($_[0]) ne 'Regexp' } | 
| 210 |  |  |  |  |  |  |  | 
| 211 | 0 |  |  | 0 | 0 | 0 | sub ClassName  { Mousse::Util::is_class_loaded($_[0]) } | 
| 212 | 0 |  | 0 | 0 | 0 | 0 | sub RoleName   { (Mousse::Util::class_of($_[0]) || return 0)->isa('Mousse::Meta::Role') } | 
| 213 |  |  |  |  |  |  |  | 
| 214 |  |  |  |  |  |  | sub _parameterize_ArrayRef_for { | 
| 215 | 0 |  |  | 0 |  | 0 | my($type_parameter) = @_; | 
| 216 | 0 |  |  |  |  | 0 | my $check = $type_parameter->_compiled_type_constraint; | 
| 217 |  |  |  |  |  |  |  | 
| 218 |  |  |  |  |  |  | return sub { | 
| 219 | 0 |  |  | 0 |  | 0 | foreach my $value (@{$_}) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 220 | 0 | 0 |  |  |  | 0 | return undef unless $check->($value); | 
| 221 |  |  |  |  |  |  | } | 
| 222 | 0 |  |  |  |  | 0 | return 1; | 
| 223 |  |  |  |  |  |  | } | 
| 224 | 0 |  |  |  |  | 0 | } | 
| 225 |  |  |  |  |  |  |  | 
| 226 |  |  |  |  |  |  | sub _parameterize_HashRef_for { | 
| 227 | 0 |  |  | 0 |  | 0 | my($type_parameter) = @_; | 
| 228 | 0 |  |  |  |  | 0 | my $check = $type_parameter->_compiled_type_constraint; | 
| 229 |  |  |  |  |  |  |  | 
| 230 |  |  |  |  |  |  | return sub { | 
| 231 | 0 |  |  | 0 |  | 0 | foreach my $value(values %{$_}){ | 
|  | 0 |  |  |  |  | 0 |  | 
| 232 | 0 | 0 |  |  |  | 0 | return undef unless $check->($value); | 
| 233 |  |  |  |  |  |  | } | 
| 234 | 0 |  |  |  |  | 0 | return 1; | 
| 235 | 0 |  |  |  |  | 0 | }; | 
| 236 |  |  |  |  |  |  | } | 
| 237 |  |  |  |  |  |  |  | 
| 238 |  |  |  |  |  |  | # 'Maybe' type accepts 'Any', so it requires parameters | 
| 239 |  |  |  |  |  |  | sub _parameterize_Maybe_for { | 
| 240 | 0 |  |  | 0 |  | 0 | my($type_parameter) = @_; | 
| 241 | 0 |  |  |  |  | 0 | my $check = $type_parameter->_compiled_type_constraint; | 
| 242 |  |  |  |  |  |  |  | 
| 243 |  |  |  |  |  |  | return sub{ | 
| 244 | 0 |  | 0 | 0 |  | 0 | return !defined($_) || $check->($_); | 
| 245 | 0 |  |  |  |  | 0 | }; | 
| 246 |  |  |  |  |  |  | } | 
| 247 |  |  |  |  |  |  |  | 
| 248 |  |  |  |  |  |  | package Mousse::Meta::Module; | 
| 249 |  |  |  |  |  |  |  | 
| 250 | 10 |  |  | 10 | 0 | 47 | sub name          { $_[0]->{package} } | 
| 251 |  |  |  |  |  |  |  | 
| 252 | 0 |  |  | 0 |  | 0 | sub _method_map   { $_[0]->{methods} } | 
| 253 | 0 |  |  | 0 |  | 0 | sub _attribute_map{ $_[0]->{attributes} } | 
| 254 |  |  |  |  |  |  |  | 
| 255 |  |  |  |  |  |  | sub namespace{ | 
| 256 | 0 |  |  | 0 | 0 | 0 | my $name = $_[0]->{package}; | 
| 257 | 1 |  |  | 1 |  | 6 | no strict 'refs'; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 264 |  | 
| 258 | 0 |  |  |  |  | 0 | return \%{ $name . '::' }; | 
|  | 0 |  |  |  |  | 0 |  | 
| 259 |  |  |  |  |  |  | } | 
| 260 |  |  |  |  |  |  |  | 
| 261 |  |  |  |  |  |  | sub add_method { | 
| 262 | 4 |  |  | 4 | 0 | 24 | my($self, $name, $code) = @_; | 
| 263 |  |  |  |  |  |  |  | 
| 264 | 4 | 50 |  |  |  | 11 | if(!defined $name){ | 
| 265 | 0 |  |  |  |  | 0 | $self->throw_error('You must pass a defined name'); | 
| 266 |  |  |  |  |  |  | } | 
| 267 | 4 | 50 |  |  |  | 9 | if(!defined $code){ | 
| 268 | 0 |  |  |  |  | 0 | $self->throw_error('You must pass a defined code'); | 
| 269 |  |  |  |  |  |  | } | 
| 270 |  |  |  |  |  |  |  | 
| 271 | 4 | 50 |  |  |  | 13 | if(ref($code) ne 'CODE'){ | 
| 272 | 0 |  |  |  |  | 0 | $code = \&{$code}; # coerce | 
|  | 0 |  |  |  |  | 0 |  | 
| 273 |  |  |  |  |  |  | } | 
| 274 |  |  |  |  |  |  |  | 
| 275 | 4 |  |  |  |  | 13 | $self->{methods}->{$name} = $code; # Moose stores meta object here. | 
| 276 |  |  |  |  |  |  |  | 
| 277 | 4 |  |  |  |  | 13 | Mousse::Util::install_subroutines($self->name, | 
| 278 |  |  |  |  |  |  | $name => $code, | 
| 279 |  |  |  |  |  |  | ); | 
| 280 | 4 |  |  |  |  | 8 | return; | 
| 281 |  |  |  |  |  |  | } | 
| 282 |  |  |  |  |  |  |  | 
| 283 |  |  |  |  |  |  | my $generate_class_accessor = sub { | 
| 284 |  |  |  |  |  |  | my($name) = @_; | 
| 285 |  |  |  |  |  |  | return sub { | 
| 286 | 2 |  |  | 2 |  | 4 | my $self = shift; | 
| 287 | 2 | 50 |  |  |  | 6 | if(@_) { | 
| 288 | 0 |  |  |  |  | 0 | return $self->{$name} = shift; | 
| 289 |  |  |  |  |  |  | } | 
| 290 |  |  |  |  |  |  |  | 
| 291 | 2 |  |  |  |  | 5 | foreach my $class($self->linearized_isa) { | 
| 292 | 5 | 100 |  |  |  | 9 | my $meta = Mousse::Util::get_metaclass_by_name($class) | 
| 293 |  |  |  |  |  |  | or next; | 
| 294 |  |  |  |  |  |  |  | 
| 295 | 3 | 50 |  |  |  | 10 | if(exists $meta->{$name}) { | 
| 296 | 0 |  |  |  |  | 0 | return $meta->{$name}; | 
| 297 |  |  |  |  |  |  | } | 
| 298 |  |  |  |  |  |  | } | 
| 299 | 2 |  |  |  |  | 4 | return undef; | 
| 300 |  |  |  |  |  |  | }; | 
| 301 |  |  |  |  |  |  | }; | 
| 302 |  |  |  |  |  |  |  | 
| 303 |  |  |  |  |  |  |  | 
| 304 |  |  |  |  |  |  | package Mousse::Meta::Class; | 
| 305 |  |  |  |  |  |  |  | 
| 306 | 1 |  |  | 1 |  | 4 | use Mousse::Meta::Method::Constructor; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 21 |  | 
| 307 | 1 |  |  | 1 |  | 4 | use Mousse::Meta::Method::Destructor; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 2684 |  | 
| 308 |  |  |  |  |  |  |  | 
| 309 | 0 | 0 |  | 0 | 0 | 0 | sub method_metaclass    { $_[0]->{method_metaclass}    || 'Mousse::Meta::Method'    } | 
| 310 | 2 | 50 |  | 2 | 0 | 24 | sub attribute_metaclass { $_[0]->{attribute_metaclass} || 'Mousse::Meta::Attribute' } | 
| 311 |  |  |  |  |  |  |  | 
| 312 | 2 | 50 |  | 2 | 0 | 15 | sub constructor_class { $_[0]->{constructor_class} || 'Mousse::Meta::Method::Constructor' } | 
| 313 | 0 | 0 |  | 0 | 0 | 0 | sub destructor_class  { $_[0]->{destructor_class}  || 'Mousse::Meta::Method::Destructor'  } | 
| 314 |  |  |  |  |  |  |  | 
| 315 |  |  |  |  |  |  | sub is_anon_class{ | 
| 316 | 2 |  |  | 2 | 0 | 6 | return exists $_[0]->{anon_serial_id}; | 
| 317 |  |  |  |  |  |  | } | 
| 318 |  |  |  |  |  |  |  | 
| 319 | 0 |  |  | 0 | 0 | 0 | sub roles { $_[0]->{roles} } | 
| 320 |  |  |  |  |  |  |  | 
| 321 | 4 |  |  | 4 | 0 | 5 | sub linearized_isa { @{ Mousse::Util::get_linear_isa($_[0]->{package}) } } | 
|  | 4 |  |  |  |  | 29 |  | 
| 322 |  |  |  |  |  |  |  | 
| 323 |  |  |  |  |  |  | sub new_object { | 
| 324 | 2 |  |  | 2 | 0 | 5 | my $meta = shift; | 
| 325 | 2 | 50 |  |  |  | 5 | my %args = (@_ == 1 ? %{$_[0]} : @_); | 
|  | 2 |  |  |  |  | 9 |  | 
| 326 |  |  |  |  |  |  |  | 
| 327 | 2 |  |  |  |  | 6 | my $object = bless {}, $meta->name; | 
| 328 |  |  |  |  |  |  |  | 
| 329 | 2 |  |  |  |  | 7 | $meta->_initialize_object($object, \%args, 0); | 
| 330 |  |  |  |  |  |  | # BUILDALL | 
| 331 | 2 | 50 |  |  |  | 20 | if( $object->can('BUILD') ) { | 
| 332 | 0 |  |  |  |  | 0 | for my $class (reverse $meta->linearized_isa) { | 
| 333 | 0 |  | 0 |  |  | 0 | my $build = Mousse::Util::get_code_ref($class, 'BUILD') | 
| 334 |  |  |  |  |  |  | || next; | 
| 335 |  |  |  |  |  |  |  | 
| 336 | 0 |  |  |  |  | 0 | $object->$build(\%args); | 
| 337 |  |  |  |  |  |  | } | 
| 338 |  |  |  |  |  |  | } | 
| 339 | 2 |  |  |  |  | 10 | return $object; | 
| 340 |  |  |  |  |  |  | } | 
| 341 |  |  |  |  |  |  |  | 
| 342 |  |  |  |  |  |  | sub clone_object { | 
| 343 | 0 |  |  | 0 | 0 | 0 | my $class  = shift; | 
| 344 | 0 |  |  |  |  | 0 | my $object = shift; | 
| 345 | 0 |  |  |  |  | 0 | my $args   = $object->Mousse::Object::BUILDARGS(@_); | 
| 346 |  |  |  |  |  |  |  | 
| 347 | 0 | 0 | 0 |  |  | 0 | (Scalar::Util::blessed($object) && $object->isa($class->name)) | 
| 348 |  |  |  |  |  |  | || $class->throw_error("You must pass an instance of the metaclass (" . $class->name . "), not ($object)"); | 
| 349 |  |  |  |  |  |  |  | 
| 350 | 0 |  |  |  |  | 0 | my $cloned = bless { %$object }, ref $object; | 
| 351 | 0 |  |  |  |  | 0 | $class->_initialize_object($cloned, $args, 1); | 
| 352 | 0 |  |  |  |  | 0 | return $cloned; | 
| 353 |  |  |  |  |  |  | } | 
| 354 |  |  |  |  |  |  |  | 
| 355 |  |  |  |  |  |  | sub _initialize_object{ | 
| 356 | 2 |  |  | 2 |  | 6 | my($self, $object, $args, $is_cloning) = @_; | 
| 357 |  |  |  |  |  |  | # The initializer, which is used everywhere, must be clear | 
| 358 |  |  |  |  |  |  | # when an attribute is added. See Mousse::Meta::Class::add_attribute. | 
| 359 | 2 |  | 33 |  |  | 14 | my $initializer = $self->{_mouse_cache}{_initialize_object} ||= | 
| 360 |  |  |  |  |  |  | Mousse::Util::load_class($self->constructor_class) | 
| 361 |  |  |  |  |  |  | ->_generate_initialize_object($self); | 
| 362 | 2 |  |  |  |  | 4 | goto &{$initializer}; | 
|  | 2 |  |  |  |  | 5 |  | 
| 363 |  |  |  |  |  |  | } | 
| 364 |  |  |  |  |  |  |  | 
| 365 |  |  |  |  |  |  | sub get_all_attributes { | 
| 366 | 2 |  |  | 2 | 0 | 4 | my($self) = @_; | 
| 367 | 2 |  | 33 |  |  | 4 | return @{ $self->{_mouse_cache}{all_attributes} | 
|  | 2 |  |  |  |  | 21 |  | 
| 368 |  |  |  |  |  |  | ||= $self->_calculate_all_attributes }; | 
| 369 |  |  |  |  |  |  | } | 
| 370 |  |  |  |  |  |  |  | 
| 371 | 0 |  |  | 0 | 0 | 0 | sub is_immutable {  $_[0]->{is_immutable} } | 
| 372 |  |  |  |  |  |  |  | 
| 373 |  |  |  |  |  |  | sub strict_constructor; | 
| 374 |  |  |  |  |  |  | *strict_constructor = $generate_class_accessor->('strict_constructor'); | 
| 375 |  |  |  |  |  |  |  | 
| 376 |  |  |  |  |  |  | sub _invalidate_metaclass_cache { | 
| 377 | 2 |  |  | 2 |  | 3 | my($self) = @_; | 
| 378 | 2 |  |  |  |  | 5 | delete $self->{_mouse_cache}; | 
| 379 | 2 |  |  |  |  | 3 | return; | 
| 380 |  |  |  |  |  |  | } | 
| 381 |  |  |  |  |  |  |  | 
| 382 |  |  |  |  |  |  | sub _report_unknown_args { | 
| 383 | 0 |  |  | 0 |  | 0 | my($metaclass, $attrs, $args) = @_; | 
| 384 |  |  |  |  |  |  |  | 
| 385 | 0 |  |  |  |  | 0 | my @unknowns; | 
| 386 |  |  |  |  |  |  | my %init_args; | 
| 387 | 0 |  |  |  |  | 0 | foreach my $attr(@{$attrs}){ | 
|  | 0 |  |  |  |  | 0 |  | 
| 388 | 0 |  |  |  |  | 0 | my $init_arg = $attr->init_arg; | 
| 389 | 0 | 0 |  |  |  | 0 | if(defined $init_arg){ | 
| 390 | 0 |  |  |  |  | 0 | $init_args{$init_arg}++; | 
| 391 |  |  |  |  |  |  | } | 
| 392 |  |  |  |  |  |  | } | 
| 393 |  |  |  |  |  |  |  | 
| 394 | 0 |  |  |  |  | 0 | while(my $key = each %{$args}){ | 
|  | 0 |  |  |  |  | 0 |  | 
| 395 | 0 | 0 |  |  |  | 0 | if(!exists $init_args{$key}){ | 
| 396 | 0 |  |  |  |  | 0 | push @unknowns, $key; | 
| 397 |  |  |  |  |  |  | } | 
| 398 |  |  |  |  |  |  | } | 
| 399 |  |  |  |  |  |  |  | 
| 400 | 0 |  |  |  |  | 0 | $metaclass->throw_error( sprintf | 
| 401 |  |  |  |  |  |  | "Unknown attribute passed to the constructor of %s: %s", | 
| 402 |  |  |  |  |  |  | $metaclass->name, Mousse::Util::english_list(@unknowns), | 
| 403 |  |  |  |  |  |  | ); | 
| 404 |  |  |  |  |  |  | } | 
| 405 |  |  |  |  |  |  |  | 
| 406 |  |  |  |  |  |  | package Mousse::Meta::Role; | 
| 407 |  |  |  |  |  |  |  | 
| 408 | 0 | 0 |  | 0 | 0 | 0 | sub method_metaclass{ $_[0]->{method_metaclass} || 'Mousse::Meta::Role::Method' } | 
| 409 |  |  |  |  |  |  |  | 
| 410 |  |  |  |  |  |  | sub is_anon_role{ | 
| 411 | 0 |  |  | 0 | 0 | 0 | return exists $_[0]->{anon_serial_id}; | 
| 412 |  |  |  |  |  |  | } | 
| 413 |  |  |  |  |  |  |  | 
| 414 | 0 |  |  | 0 | 0 | 0 | sub get_roles { $_[0]->{roles} } | 
| 415 |  |  |  |  |  |  |  | 
| 416 |  |  |  |  |  |  | sub add_before_method_modifier { | 
| 417 | 0 |  |  | 0 | 0 | 0 | my ($self, $method_name, $method) = @_; | 
| 418 |  |  |  |  |  |  |  | 
| 419 | 0 |  | 0 |  |  | 0 | push @{ $self->{before_method_modifiers}{$method_name} ||= [] }, $method; | 
|  | 0 |  |  |  |  | 0 |  | 
| 420 | 0 |  |  |  |  | 0 | return; | 
| 421 |  |  |  |  |  |  | } | 
| 422 |  |  |  |  |  |  | sub add_around_method_modifier { | 
| 423 | 0 |  |  | 0 | 0 | 0 | my ($self, $method_name, $method) = @_; | 
| 424 |  |  |  |  |  |  |  | 
| 425 | 0 |  | 0 |  |  | 0 | push @{ $self->{around_method_modifiers}{$method_name} ||= [] }, $method; | 
|  | 0 |  |  |  |  | 0 |  | 
| 426 | 0 |  |  |  |  | 0 | return; | 
| 427 |  |  |  |  |  |  | } | 
| 428 |  |  |  |  |  |  | sub add_after_method_modifier { | 
| 429 | 0 |  |  | 0 | 0 | 0 | my ($self, $method_name, $method) = @_; | 
| 430 |  |  |  |  |  |  |  | 
| 431 | 0 |  | 0 |  |  | 0 | push @{ $self->{after_method_modifiers}{$method_name} ||= [] }, $method; | 
|  | 0 |  |  |  |  | 0 |  | 
| 432 | 0 |  |  |  |  | 0 | return; | 
| 433 |  |  |  |  |  |  | } | 
| 434 |  |  |  |  |  |  |  | 
| 435 |  |  |  |  |  |  | sub get_before_method_modifiers { | 
| 436 | 0 |  |  | 0 | 0 | 0 | my ($self, $method_name) = @_; | 
| 437 | 0 |  | 0 |  |  | 0 | return @{ $self->{before_method_modifiers}{$method_name} ||= [] } | 
|  | 0 |  |  |  |  | 0 |  | 
| 438 |  |  |  |  |  |  | } | 
| 439 |  |  |  |  |  |  | sub get_around_method_modifiers { | 
| 440 | 0 |  |  | 0 | 0 | 0 | my ($self, $method_name) = @_; | 
| 441 | 0 |  | 0 |  |  | 0 | return @{ $self->{around_method_modifiers}{$method_name} ||= [] } | 
|  | 0 |  |  |  |  | 0 |  | 
| 442 |  |  |  |  |  |  | } | 
| 443 |  |  |  |  |  |  | sub get_after_method_modifiers { | 
| 444 | 0 |  |  | 0 | 0 | 0 | my ($self, $method_name) = @_; | 
| 445 | 0 |  | 0 |  |  | 0 | return @{ $self->{after_method_modifiers}{$method_name} ||= [] } | 
|  | 0 |  |  |  |  | 0 |  | 
| 446 |  |  |  |  |  |  | } | 
| 447 |  |  |  |  |  |  |  | 
| 448 |  |  |  |  |  |  | sub add_metaclass_accessor { # for meta roles (a.k.a. traits) | 
| 449 | 0 |  |  | 0 | 0 | 0 | my($meta, $name) = @_; | 
| 450 | 0 |  |  |  |  | 0 | $meta->add_method($name => $generate_class_accessor->($name)); | 
| 451 | 0 |  |  |  |  | 0 | return; | 
| 452 |  |  |  |  |  |  | } | 
| 453 |  |  |  |  |  |  |  | 
| 454 |  |  |  |  |  |  | package Mousse::Meta::Attribute; | 
| 455 |  |  |  |  |  |  |  | 
| 456 |  |  |  |  |  |  | require Mousse::Meta::Method::Accessor; | 
| 457 |  |  |  |  |  |  |  | 
| 458 | 2 | 50 |  | 2 | 0 | 13 | sub accessor_metaclass{ $_[0]->{accessor_metaclass} || 'Mousse::Meta::Method::Accessor' } | 
| 459 |  |  |  |  |  |  |  | 
| 460 |  |  |  |  |  |  | # readers | 
| 461 |  |  |  |  |  |  |  | 
| 462 | 8 |  |  | 8 | 0 | 28 | sub name                 { $_[0]->{name}                   } | 
| 463 | 2 |  |  | 2 | 0 | 4 | sub associated_class     { $_[0]->{associated_class}       } | 
| 464 |  |  |  |  |  |  |  | 
| 465 | 0 |  |  | 0 | 0 | 0 | sub accessor             { $_[0]->{accessor}               } | 
| 466 | 0 |  |  | 0 | 0 | 0 | sub reader               { $_[0]->{reader}                 } | 
| 467 | 0 |  |  | 0 | 0 | 0 | sub writer               { $_[0]->{writer}                 } | 
| 468 | 0 |  |  | 0 | 0 | 0 | sub predicate            { $_[0]->{predicate}              } | 
| 469 | 0 |  |  | 0 | 0 | 0 | sub clearer              { $_[0]->{clearer}                } | 
| 470 | 0 |  |  | 0 | 0 | 0 | sub handles              { $_[0]->{handles}                } | 
| 471 |  |  |  |  |  |  |  | 
| 472 | 0 |  |  | 0 |  | 0 | sub _is_metadata         { $_[0]->{is}                     } | 
| 473 | 3 |  |  | 3 | 0 | 10 | sub is_required          { $_[0]->{required}               } | 
| 474 | 2 |  |  | 2 | 0 | 5 | sub default              { $_[0]->{default}                } | 
| 475 | 2 |  |  | 2 | 0 | 7 | sub is_lazy              { $_[0]->{lazy}                   } | 
| 476 | 0 |  |  | 0 | 0 | 0 | sub is_lazy_build        { $_[0]->{lazy_build}             } | 
| 477 | 5 |  |  | 5 | 0 | 9 | sub is_weak_ref          { $_[0]->{weak_ref}               } | 
| 478 | 3 |  |  | 3 | 0 | 16 | sub init_arg             { $_[0]->{init_arg}               } | 
| 479 | 8 |  |  | 8 | 0 | 18 | sub type_constraint      { $_[0]->{type_constraint}        } | 
| 480 |  |  |  |  |  |  |  | 
| 481 | 2 |  |  | 2 | 0 | 5 | sub trigger              { $_[0]->{trigger}                } | 
| 482 | 2 |  |  | 2 | 0 | 4 | sub builder              { $_[0]->{builder}                } | 
| 483 | 2 |  |  | 2 | 0 | 5 | sub should_auto_deref    { $_[0]->{auto_deref}             } | 
| 484 | 0 |  |  | 0 | 0 | 0 | sub should_coerce        { $_[0]->{coerce}                 } | 
| 485 |  |  |  |  |  |  |  | 
| 486 | 0 |  |  | 0 | 0 | 0 | sub documentation        { $_[0]->{documentation}          } | 
| 487 | 0 |  |  | 0 | 0 | 0 | sub insertion_order      { $_[0]->{insertion_order}        } | 
| 488 |  |  |  |  |  |  |  | 
| 489 |  |  |  |  |  |  | # predicates | 
| 490 |  |  |  |  |  |  |  | 
| 491 | 0 |  |  | 0 | 0 | 0 | sub has_accessor         { exists $_[0]->{accessor}        } | 
| 492 | 0 |  |  | 0 | 0 | 0 | sub has_reader           { exists $_[0]->{reader}          } | 
| 493 | 0 |  |  | 0 | 0 | 0 | sub has_writer           { exists $_[0]->{writer}          } | 
| 494 | 0 |  |  | 0 | 0 | 0 | sub has_predicate        { exists $_[0]->{predicate}       } | 
| 495 | 0 |  |  | 0 | 0 | 0 | sub has_clearer          { exists $_[0]->{clearer}         } | 
| 496 | 0 |  |  | 0 | 0 | 0 | sub has_handles          { exists $_[0]->{handles}         } | 
| 497 |  |  |  |  |  |  |  | 
| 498 | 3 |  |  | 3 | 0 | 13 | sub has_default          { exists $_[0]->{default}         } | 
| 499 | 0 |  |  | 0 | 0 | 0 | sub has_type_constraint  { exists $_[0]->{type_constraint} } | 
| 500 | 3 |  |  | 3 | 0 | 11 | sub has_trigger          { exists $_[0]->{trigger}         } | 
| 501 | 3 |  |  | 3 | 0 | 23 | sub has_builder          { exists $_[0]->{builder}         } | 
| 502 |  |  |  |  |  |  |  | 
| 503 | 0 |  |  | 0 | 0 | 0 | sub has_documentation    { exists $_[0]->{documentation}   } | 
| 504 |  |  |  |  |  |  |  | 
| 505 |  |  |  |  |  |  | sub _process_options{ | 
| 506 | 2 |  |  | 2 |  | 5 | my($class, $name, $args) = @_; | 
| 507 |  |  |  |  |  |  |  | 
| 508 |  |  |  |  |  |  | # taken from Class::MOP::Attribute::new | 
| 509 |  |  |  |  |  |  |  | 
| 510 | 2 | 50 |  |  |  | 5 | defined($name) | 
| 511 |  |  |  |  |  |  | or $class->throw_error('You must provide a name for the attribute'); | 
| 512 |  |  |  |  |  |  |  | 
| 513 | 2 | 50 |  |  |  | 7 | if(!exists $args->{init_arg}){ | 
| 514 | 2 |  |  |  |  | 6 | $args->{init_arg} = $name; | 
| 515 |  |  |  |  |  |  | } | 
| 516 |  |  |  |  |  |  |  | 
| 517 |  |  |  |  |  |  | # 'required' requires eigher 'init_arg', 'builder', or 'default' | 
| 518 | 2 |  |  |  |  | 4 | my $can_be_required = defined( $args->{init_arg} ); | 
| 519 |  |  |  |  |  |  |  | 
| 520 | 2 | 50 |  |  |  | 14 | if(exists $args->{builder}){ | 
|  |  | 50 |  |  |  |  |  | 
| 521 |  |  |  |  |  |  | # XXX: | 
| 522 |  |  |  |  |  |  | # Moose refuses a CODE ref builder, but Mousse doesn't for backward compatibility | 
| 523 |  |  |  |  |  |  | # This feature will be changed in a future. (gfx) | 
| 524 | 0 | 0 |  |  |  | 0 | $class->throw_error('builder must be a defined scalar value which is a method name') | 
| 525 |  |  |  |  |  |  | #if ref $args->{builder} || !defined $args->{builder}; | 
| 526 |  |  |  |  |  |  | if !defined $args->{builder}; | 
| 527 |  |  |  |  |  |  |  | 
| 528 | 0 |  |  |  |  | 0 | $can_be_required++; | 
| 529 |  |  |  |  |  |  | } | 
| 530 |  |  |  |  |  |  | elsif(exists $args->{default}){ | 
| 531 | 0 | 0 | 0 |  |  | 0 | if(ref $args->{default} && ref($args->{default}) ne 'CODE'){ | 
| 532 | 0 |  |  |  |  | 0 | $class->throw_error("References are not allowed as default values, you must " | 
| 533 |  |  |  |  |  |  | . "wrap the default of '$name' in a CODE reference (ex: sub { [] } and not [])"); | 
| 534 |  |  |  |  |  |  | } | 
| 535 | 0 |  |  |  |  | 0 | $can_be_required++; | 
| 536 |  |  |  |  |  |  | } | 
| 537 |  |  |  |  |  |  |  | 
| 538 | 2 | 50 | 33 |  |  | 7 | if( $args->{required} && !$can_be_required ) { | 
| 539 | 0 |  |  |  |  | 0 | $class->throw_error("You cannot have a required attribute ($name) without a default, builder, or an init_arg"); | 
| 540 |  |  |  |  |  |  | } | 
| 541 |  |  |  |  |  |  |  | 
| 542 |  |  |  |  |  |  | # taken from Mousse::Meta::Attribute->new and ->_process_args | 
| 543 |  |  |  |  |  |  |  | 
| 544 | 2 | 50 |  |  |  | 7 | if(exists $args->{is}){ | 
| 545 | 2 |  |  |  |  | 4 | my $is = $args->{is}; | 
| 546 |  |  |  |  |  |  |  | 
| 547 | 2 | 50 |  |  |  | 17 | if($is eq 'ro'){ | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 548 | 0 |  | 0 |  |  | 0 | $args->{reader} ||= $name; | 
| 549 |  |  |  |  |  |  | } | 
| 550 |  |  |  |  |  |  | elsif($is eq 'rw'){ | 
| 551 | 2 | 50 |  |  |  | 6 | if(exists $args->{writer}){ | 
| 552 | 0 |  | 0 |  |  | 0 | $args->{reader} ||= $name; | 
| 553 |  |  |  |  |  |  | } | 
| 554 |  |  |  |  |  |  | else{ | 
| 555 | 2 |  | 33 |  |  | 12 | $args->{accessor} ||= $name; | 
| 556 |  |  |  |  |  |  | } | 
| 557 |  |  |  |  |  |  | } | 
| 558 |  |  |  |  |  |  | elsif($is eq 'bare'){ | 
| 559 |  |  |  |  |  |  | # do nothing, but don't complain (later) about missing methods | 
| 560 |  |  |  |  |  |  | } | 
| 561 |  |  |  |  |  |  | else{ | 
| 562 | 0 | 0 |  |  |  | 0 | $is = 'undef' if !defined $is; | 
| 563 | 0 |  |  |  |  | 0 | $class->throw_error("I do not understand this option (is => $is) on attribute ($name)"); | 
| 564 |  |  |  |  |  |  | } | 
| 565 |  |  |  |  |  |  | } | 
| 566 |  |  |  |  |  |  |  | 
| 567 | 2 |  |  |  |  | 3 | my $tc; | 
| 568 | 2 | 50 |  |  |  | 5 | if(exists $args->{isa}){ | 
| 569 | 0 |  |  |  |  | 0 | $tc = $args->{type_constraint} = Mousse::Util::TypeConstraints::find_or_create_isa_type_constraint($args->{isa}); | 
| 570 |  |  |  |  |  |  | } | 
| 571 |  |  |  |  |  |  |  | 
| 572 | 2 | 50 |  |  |  | 6 | if(exists $args->{does}){ | 
| 573 | 0 | 0 |  |  |  | 0 | if(defined $tc){ # both isa and does supplied | 
| 574 | 0 |  |  |  |  | 0 | my $does_ok = do{ | 
| 575 | 0 |  |  |  |  | 0 | local $@; | 
| 576 | 0 |  |  |  |  | 0 | eval{ "$tc"->does($args->{does}) }; | 
|  | 0 |  |  |  |  | 0 |  | 
| 577 |  |  |  |  |  |  | }; | 
| 578 | 0 | 0 |  |  |  | 0 | if(!$does_ok){ | 
| 579 | 0 |  |  |  |  | 0 | $class->throw_error("Cannot have both an isa option and a does option because '$tc' does not do '$args->{does}' on attribute ($name)"); | 
| 580 |  |  |  |  |  |  | } | 
| 581 |  |  |  |  |  |  | } | 
| 582 |  |  |  |  |  |  | else { | 
| 583 | 0 |  |  |  |  | 0 | $tc = $args->{type_constraint} = Mousse::Util::TypeConstraints::find_or_create_does_type_constraint($args->{does}); | 
| 584 |  |  |  |  |  |  | } | 
| 585 |  |  |  |  |  |  | } | 
| 586 |  |  |  |  |  |  |  | 
| 587 | 2 | 50 |  |  |  | 6 | if($args->{coerce}){ | 
| 588 | 0 | 0 |  |  |  | 0 | defined($tc) | 
| 589 |  |  |  |  |  |  | || $class->throw_error("You cannot have coercion without specifying a type constraint on attribute ($name)"); | 
| 590 |  |  |  |  |  |  |  | 
| 591 | 0 | 0 |  |  |  | 0 | $args->{weak_ref} | 
| 592 |  |  |  |  |  |  | && $class->throw_error("You cannot have a weak reference to a coerced value on attribute ($name)"); | 
| 593 |  |  |  |  |  |  | } | 
| 594 |  |  |  |  |  |  |  | 
| 595 | 2 | 50 |  |  |  | 6 | if ($args->{lazy_build}) { | 
| 596 | 0 | 0 |  |  |  | 0 | exists($args->{default}) | 
| 597 |  |  |  |  |  |  | && $class->throw_error("You can not use lazy_build and default for the same attribute ($name)"); | 
| 598 |  |  |  |  |  |  |  | 
| 599 | 0 |  |  |  |  | 0 | $args->{lazy}      = 1; | 
| 600 | 0 |  | 0 |  |  | 0 | $args->{builder} ||= "_build_${name}"; | 
| 601 | 0 | 0 |  |  |  | 0 | if ($name =~ /^_/) { | 
| 602 | 0 |  | 0 |  |  | 0 | $args->{clearer}   ||= "_clear${name}"; | 
| 603 | 0 |  | 0 |  |  | 0 | $args->{predicate} ||= "_has${name}"; | 
| 604 |  |  |  |  |  |  | } | 
| 605 |  |  |  |  |  |  | else { | 
| 606 | 0 |  | 0 |  |  | 0 | $args->{clearer}   ||= "clear_${name}"; | 
| 607 | 0 |  | 0 |  |  | 0 | $args->{predicate} ||= "has_${name}"; | 
| 608 |  |  |  |  |  |  | } | 
| 609 |  |  |  |  |  |  | } | 
| 610 |  |  |  |  |  |  |  | 
| 611 | 2 | 50 |  |  |  | 7 | if ($args->{auto_deref}) { | 
| 612 | 0 | 0 |  |  |  | 0 | defined($tc) | 
| 613 |  |  |  |  |  |  | || $class->throw_error("You cannot auto-dereference without specifying a type constraint on attribute ($name)"); | 
| 614 |  |  |  |  |  |  |  | 
| 615 | 0 | 0 | 0 |  |  | 0 | ( $tc->is_a_type_of('ArrayRef') || $tc->is_a_type_of('HashRef') ) | 
| 616 |  |  |  |  |  |  | || $class->throw_error("You cannot auto-dereference anything other than a ArrayRef or HashRef on attribute ($name)"); | 
| 617 |  |  |  |  |  |  | } | 
| 618 |  |  |  |  |  |  |  | 
| 619 | 2 | 50 |  |  |  | 6 | if (exists $args->{trigger}) { | 
| 620 | 0 | 0 |  |  |  | 0 | ('CODE' eq ref $args->{trigger}) | 
| 621 |  |  |  |  |  |  | || $class->throw_error("Trigger must be a CODE ref on attribute ($name)"); | 
| 622 |  |  |  |  |  |  | } | 
| 623 |  |  |  |  |  |  |  | 
| 624 | 2 | 50 |  |  |  | 13 | if ($args->{lazy}) { | 
| 625 | 0 | 0 | 0 |  |  | 0 | (exists $args->{default} || defined $args->{builder}) | 
| 626 |  |  |  |  |  |  | || $class->throw_error("You cannot have a lazy attribute ($name) without specifying a default value for it"); | 
| 627 |  |  |  |  |  |  | } | 
| 628 |  |  |  |  |  |  |  | 
| 629 | 2 |  |  |  |  | 4 | return; | 
| 630 |  |  |  |  |  |  | } | 
| 631 |  |  |  |  |  |  |  | 
| 632 |  |  |  |  |  |  |  | 
| 633 |  |  |  |  |  |  | package Mousse::Meta::TypeConstraint; | 
| 634 |  |  |  |  |  |  |  | 
| 635 |  |  |  |  |  |  | use overload | 
| 636 | 1 |  |  |  |  | 6 | '""' => '_as_string', | 
| 637 |  |  |  |  |  |  | '0+' => '_identity', | 
| 638 |  |  |  |  |  |  | '|'  => '_unite', | 
| 639 |  |  |  |  |  |  |  | 
| 640 | 1 |  |  | 1 |  | 1802 | fallback => 1; | 
|  | 1 |  |  |  |  | 2775 |  | 
| 641 |  |  |  |  |  |  |  | 
| 642 | 0 |  |  | 0 | 0 | 0 | sub name    { $_[0]->{name}    } | 
| 643 | 0 |  |  | 0 | 0 | 0 | sub parent  { $_[0]->{parent}  } | 
| 644 | 0 |  |  | 0 | 0 | 0 | sub message { $_[0]->{message} } | 
| 645 |  |  |  |  |  |  |  | 
| 646 | 0 |  |  | 0 |  | 0 | sub _identity  { Scalar::Util::refaddr($_[0]) } # overload 0+ | 
| 647 |  |  |  |  |  |  |  | 
| 648 | 0 |  |  | 0 | 0 | 0 | sub type_parameter           { $_[0]->{type_parameter} } | 
| 649 | 0 |  |  | 0 |  | 0 | sub _compiled_type_constraint{ $_[0]->{compiled_type_constraint} } | 
| 650 |  |  |  |  |  |  |  | 
| 651 | 0 |  |  | 0 |  | 0 | sub __is_parameterized { exists $_[0]->{type_parameter} } | 
| 652 | 0 |  |  | 0 | 0 | 0 | sub has_coercion {       exists $_[0]->{_compiled_type_coercion} } | 
| 653 |  |  |  |  |  |  |  | 
| 654 |  |  |  |  |  |  |  | 
| 655 |  |  |  |  |  |  | sub compile_type_constraint{ | 
| 656 | 3 |  |  | 3 | 0 | 5 | my($self) = @_; | 
| 657 |  |  |  |  |  |  |  | 
| 658 |  |  |  |  |  |  | # add parents first | 
| 659 | 3 |  |  |  |  | 4 | my @checks; | 
| 660 | 3 |  |  |  |  | 53 | for(my $parent = $self->{parent}; defined $parent; $parent = $parent->{parent}){ | 
| 661 | 3 | 50 |  |  |  | 15 | if($parent->{hand_optimized_type_constraint}){ | 
|  |  | 50 |  |  |  |  |  | 
| 662 | 0 |  |  |  |  | 0 | unshift @checks, $parent->{hand_optimized_type_constraint}; | 
| 663 | 0 |  |  |  |  | 0 | last; # a hand optimized constraint must include all the parents | 
| 664 |  |  |  |  |  |  | } | 
| 665 |  |  |  |  |  |  | elsif($parent->{constraint}){ | 
| 666 | 0 |  |  |  |  | 0 | unshift @checks, $parent->{constraint}; | 
| 667 |  |  |  |  |  |  | } | 
| 668 |  |  |  |  |  |  | } | 
| 669 |  |  |  |  |  |  |  | 
| 670 |  |  |  |  |  |  | # then add child | 
| 671 | 3 | 50 |  |  |  | 10 | if($self->{constraint}){ | 
| 672 | 0 |  |  |  |  | 0 | push @checks, $self->{constraint}; | 
| 673 |  |  |  |  |  |  | } | 
| 674 |  |  |  |  |  |  |  | 
| 675 | 3 | 50 |  |  |  | 7 | if($self->{type_constraints}){ # Union | 
| 676 | 0 |  |  |  |  | 0 | my @types = map{ $_->{compiled_type_constraint} } @{ $self->{type_constraints} }; | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 677 |  |  |  |  |  |  | push @checks, sub{ | 
| 678 | 0 |  |  | 0 |  | 0 | foreach my $c(@types){ | 
| 679 | 0 | 0 |  |  |  | 0 | return 1 if $c->($_[0]); | 
| 680 |  |  |  |  |  |  | } | 
| 681 | 0 |  |  |  |  | 0 | return 0; | 
| 682 | 0 |  |  |  |  | 0 | }; | 
| 683 |  |  |  |  |  |  | } | 
| 684 |  |  |  |  |  |  |  | 
| 685 | 3 | 50 |  |  |  | 10 | if(@checks == 0){ | 
| 686 | 3 |  |  |  |  | 6 | $self->{compiled_type_constraint} = \&Mousse::Util::TypeConstraints::Any; | 
| 687 |  |  |  |  |  |  | } | 
| 688 |  |  |  |  |  |  | else{ | 
| 689 |  |  |  |  |  |  | $self->{compiled_type_constraint} =  sub{ | 
| 690 | 0 |  |  | 0 |  | 0 | my(@args) = @_; | 
| 691 | 0 |  |  |  |  | 0 | local $_ = $args[0]; | 
| 692 | 0 |  |  |  |  | 0 | foreach my $c(@checks){ | 
| 693 | 0 | 0 |  |  |  | 0 | return undef if !$c->(@args); | 
| 694 |  |  |  |  |  |  | } | 
| 695 | 0 |  |  |  |  | 0 | return 1; | 
| 696 | 0 |  |  |  |  | 0 | }; | 
| 697 |  |  |  |  |  |  | } | 
| 698 | 3 |  |  |  |  | 6 | return; | 
| 699 |  |  |  |  |  |  | } | 
| 700 |  |  |  |  |  |  |  | 
| 701 |  |  |  |  |  |  | sub check { | 
| 702 | 0 |  |  | 0 | 0 | 0 | my $self = shift; | 
| 703 | 0 |  |  |  |  | 0 | return $self->_compiled_type_constraint->(@_); | 
| 704 |  |  |  |  |  |  | } | 
| 705 |  |  |  |  |  |  |  | 
| 706 |  |  |  |  |  |  |  | 
| 707 |  |  |  |  |  |  | package Mousse::Object; | 
| 708 |  |  |  |  |  |  |  | 
| 709 |  |  |  |  |  |  | sub BUILDARGS { | 
| 710 | 4 |  |  | 4 | 0 | 8 | my $class = shift; | 
| 711 |  |  |  |  |  |  |  | 
| 712 | 4 | 50 |  |  |  | 9 | if (scalar @_ == 1) { | 
| 713 | 0 | 0 |  |  |  | 0 | (ref($_[0]) eq 'HASH') | 
| 714 |  |  |  |  |  |  | || $class->meta->throw_error("Single parameters to new() must be a HASH ref"); | 
| 715 |  |  |  |  |  |  |  | 
| 716 | 0 |  |  |  |  | 0 | return {%{$_[0]}}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 717 |  |  |  |  |  |  | } | 
| 718 |  |  |  |  |  |  | else { | 
| 719 | 4 |  |  |  |  | 15 | return {@_}; | 
| 720 |  |  |  |  |  |  | } | 
| 721 |  |  |  |  |  |  | } | 
| 722 |  |  |  |  |  |  |  | 
| 723 |  |  |  |  |  |  | sub new { | 
| 724 | 2 |  |  | 2 | 0 | 19 | my $class = shift; | 
| 725 | 2 |  |  |  |  | 11 | my $args  = $class->BUILDARGS(@_); | 
| 726 | 2 |  |  |  |  | 8 | return $class->meta->new_object($args); | 
| 727 |  |  |  |  |  |  | } | 
| 728 |  |  |  |  |  |  |  | 
| 729 |  |  |  |  |  |  | sub DESTROY { | 
| 730 | 2 |  |  | 2 |  | 1053 | my $self = shift; | 
| 731 |  |  |  |  |  |  |  | 
| 732 | 2 | 50 |  |  |  | 114 | return unless $self->can('DEMOLISH'); # short circuit | 
| 733 |  |  |  |  |  |  |  | 
| 734 | 0 |  |  |  |  | 0 | my $e = do{ | 
| 735 | 0 |  |  |  |  | 0 | local $?; | 
| 736 | 0 |  |  |  |  | 0 | local $@; | 
| 737 | 0 |  |  |  |  | 0 | eval{ | 
| 738 |  |  |  |  |  |  | # DEMOLISHALL | 
| 739 |  |  |  |  |  |  |  | 
| 740 |  |  |  |  |  |  | # We cannot count on being able to retrieve a previously made | 
| 741 |  |  |  |  |  |  | # metaclass, _or_ being able to make a new one during global | 
| 742 |  |  |  |  |  |  | # destruction. However, we should still be able to use mro at | 
| 743 |  |  |  |  |  |  | # that time (at least tests suggest so ;) | 
| 744 |  |  |  |  |  |  |  | 
| 745 | 0 |  |  |  |  | 0 | foreach my $class (@{ Mousse::Util::get_linear_isa(ref $self) }) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 746 | 0 |  | 0 |  |  | 0 | my $demolish = Mousse::Util::get_code_ref($class, 'DEMOLISH') | 
| 747 |  |  |  |  |  |  | || next; | 
| 748 |  |  |  |  |  |  |  | 
| 749 | 0 |  |  |  |  | 0 | $self->$demolish($Mousse::Util::in_global_destruction); | 
| 750 |  |  |  |  |  |  | } | 
| 751 |  |  |  |  |  |  | }; | 
| 752 | 0 |  |  |  |  | 0 | $@; | 
| 753 |  |  |  |  |  |  | }; | 
| 754 |  |  |  |  |  |  |  | 
| 755 | 1 |  |  | 1 |  | 750 | no warnings 'misc'; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 218 |  | 
| 756 | 0 | 0 |  |  |  | 0 | die $e if $e; # rethrow | 
| 757 |  |  |  |  |  |  | } | 
| 758 |  |  |  |  |  |  |  | 
| 759 |  |  |  |  |  |  | sub BUILDALL { | 
| 760 | 0 |  |  | 0 | 0 | 0 | my $self = shift; | 
| 761 |  |  |  |  |  |  |  | 
| 762 |  |  |  |  |  |  | # short circuit | 
| 763 | 0 | 0 |  |  |  | 0 | return unless $self->can('BUILD'); | 
| 764 |  |  |  |  |  |  |  | 
| 765 | 0 |  |  |  |  | 0 | for my $class (reverse $self->meta->linearized_isa) { | 
| 766 | 0 |  | 0 |  |  | 0 | my $build = Mousse::Util::get_code_ref($class, 'BUILD') | 
| 767 |  |  |  |  |  |  | || next; | 
| 768 |  |  |  |  |  |  |  | 
| 769 | 0 |  |  |  |  | 0 | $self->$build(@_); | 
| 770 |  |  |  |  |  |  | } | 
| 771 | 0 |  |  |  |  | 0 | return; | 
| 772 |  |  |  |  |  |  | } | 
| 773 |  |  |  |  |  |  |  | 
| 774 |  |  |  |  |  |  | sub DEMOLISHALL; | 
| 775 |  |  |  |  |  |  | *DEMOLISHALL = \&DESTROY; | 
| 776 |  |  |  |  |  |  |  | 
| 777 |  |  |  |  |  |  | # Contents of Mouse::Exporter | 
| 778 |  |  |  |  |  |  | package Mousse::Exporter; | 
| 779 | 1 |  |  | 1 |  | 6 | use strict; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 41 |  | 
| 780 | 1 |  |  | 1 |  | 10 | use warnings; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 22 |  | 
| 781 | 1 |  |  | 1 |  | 4 | use Carp (); | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 54 |  | 
| 782 |  |  |  |  |  |  |  | 
| 783 |  |  |  |  |  |  | my %SPEC; | 
| 784 |  |  |  |  |  |  |  | 
| 785 |  |  |  |  |  |  | my $strict_bits; | 
| 786 |  |  |  |  |  |  | my $warnings_extra_bits; | 
| 787 |  |  |  |  |  |  | BEGIN{ | 
| 788 | 1 |  |  | 1 |  | 14 | $strict_bits         = strict::bits(qw(subs refs vars)); | 
| 789 | 1 |  |  |  |  | 439 | $warnings_extra_bits = warnings::bits(FATAL => 'recursion'); | 
| 790 |  |  |  |  |  |  | } | 
| 791 |  |  |  |  |  |  |  | 
| 792 |  |  |  |  |  |  | # it must be "require", because Mousse::Util depends on Mousse::Exporter, | 
| 793 |  |  |  |  |  |  | # which depends on Mousse::Util::import() | 
| 794 |  |  |  |  |  |  | require Mousse::Util; | 
| 795 |  |  |  |  |  |  |  | 
| 796 |  |  |  |  |  |  | sub import{ | 
| 797 |  |  |  |  |  |  | # strict->import; | 
| 798 | 4 |  |  | 4 |  | 11 | $^H              |= $strict_bits; | 
| 799 |  |  |  |  |  |  | # warnings->import('all', FATAL => 'recursion'); | 
| 800 | 4 |  |  |  |  | 14 | ${^WARNING_BITS} |= $warnings::Bits{all}; | 
| 801 | 4 |  |  |  |  | 9 | ${^WARNING_BITS} |= $warnings_extra_bits; | 
| 802 | 4 |  |  |  |  | 120 | return; | 
| 803 |  |  |  |  |  |  | } | 
| 804 |  |  |  |  |  |  |  | 
| 805 |  |  |  |  |  |  |  | 
| 806 |  |  |  |  |  |  | sub setup_import_methods{ | 
| 807 | 5 |  |  | 5 | 0 | 15 | my($class, %args) = @_; | 
| 808 |  |  |  |  |  |  |  | 
| 809 | 5 |  | 33 |  |  | 29 | my $exporting_package = $args{exporting_package} ||= caller(); | 
| 810 |  |  |  |  |  |  |  | 
| 811 | 5 |  |  |  |  | 19 | my($import, $unimport) = $class->build_import_methods(%args); | 
| 812 |  |  |  |  |  |  |  | 
| 813 |  |  |  |  |  |  | Mousse::Util::install_subroutines($exporting_package, | 
| 814 |  |  |  |  |  |  | import   => $import, | 
| 815 |  |  |  |  |  |  | unimport => $unimport, | 
| 816 |  |  |  |  |  |  |  | 
| 817 |  |  |  |  |  |  | export_to_level => sub { | 
| 818 | 0 |  |  | 0 |  | 0 | my($package, $level, undef, @args) = @_; # the third argument is redundant | 
| 819 | 0 |  |  |  |  | 0 | $package->import({ into_level => $level + 1 }, @args); | 
| 820 |  |  |  |  |  |  | }, | 
| 821 |  |  |  |  |  |  | export => sub { | 
| 822 | 0 |  |  | 0 |  | 0 | my($package, $into, @args) = @_; | 
| 823 | 0 |  |  |  |  | 0 | $package->import({ into => $into }, @args); | 
| 824 |  |  |  |  |  |  | }, | 
| 825 | 5 |  |  |  |  | 38 | ); | 
| 826 | 5 |  |  |  |  | 11 | return; | 
| 827 |  |  |  |  |  |  | } | 
| 828 |  |  |  |  |  |  |  | 
| 829 |  |  |  |  |  |  | sub build_import_methods{ | 
| 830 | 5 |  |  | 5 | 0 | 13 | my($self, %args) = @_; | 
| 831 |  |  |  |  |  |  |  | 
| 832 | 5 |  | 33 |  |  | 13 | my $exporting_package = $args{exporting_package} ||= caller(); | 
| 833 |  |  |  |  |  |  |  | 
| 834 | 5 |  |  |  |  | 11 | $SPEC{$exporting_package} = \%args; | 
| 835 |  |  |  |  |  |  |  | 
| 836 |  |  |  |  |  |  | # canonicalize args | 
| 837 | 5 |  |  |  |  | 7 | my @export_from; | 
| 838 | 5 | 100 |  |  |  | 10 | if($args{also}){ | 
| 839 | 1 |  |  |  |  | 2 | my %seen; | 
| 840 | 1 |  |  |  |  | 2 | my @stack = ($exporting_package); | 
| 841 |  |  |  |  |  |  |  | 
| 842 | 1 |  |  |  |  | 4 | while(my $current = shift @stack){ | 
| 843 | 2 |  |  |  |  | 4 | push @export_from, $current; | 
| 844 |  |  |  |  |  |  |  | 
| 845 | 2 | 100 |  |  |  | 9 | my $also = $SPEC{$current}{also} or next; | 
| 846 | 1 | 50 |  |  |  | 3 | push @stack, grep{ !$seen{$_}++ } ref($also) ? @{ $also } : $also; | 
|  | 1 |  |  |  |  | 7 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 847 |  |  |  |  |  |  | } | 
| 848 |  |  |  |  |  |  | } | 
| 849 |  |  |  |  |  |  | else{ | 
| 850 | 4 |  |  |  |  | 14 | @export_from = ($exporting_package); | 
| 851 |  |  |  |  |  |  | } | 
| 852 |  |  |  |  |  |  |  | 
| 853 | 5 |  |  |  |  | 6 | my %exports; | 
| 854 |  |  |  |  |  |  | my @removables; | 
| 855 | 0 |  |  |  |  | 0 | my @all; | 
| 856 |  |  |  |  |  |  |  | 
| 857 | 0 |  |  |  |  | 0 | my @init_meta_methods; | 
| 858 |  |  |  |  |  |  |  | 
| 859 | 5 |  |  |  |  | 9 | foreach my $package(@export_from){ | 
| 860 | 6 | 50 |  |  |  | 16 | my $spec = $SPEC{$package} or next; | 
| 861 |  |  |  |  |  |  |  | 
| 862 | 6 | 100 |  |  |  | 13 | if(my $as_is = $spec->{as_is}){ | 
| 863 | 5 |  |  |  |  | 5 | foreach my $thingy (@{$as_is}){ | 
|  | 5 |  |  |  |  | 10 |  | 
| 864 | 69 |  |  |  |  | 65 | my($code_package, $code_name, $code); | 
| 865 |  |  |  |  |  |  |  | 
| 866 | 69 | 100 |  |  |  | 95 | if(ref($thingy)){ | 
| 867 | 6 |  |  |  |  | 7 | $code = $thingy; | 
| 868 | 6 |  |  |  |  | 12 | ($code_package, $code_name) = Mousse::Util::get_code_info($code); | 
| 869 |  |  |  |  |  |  | } | 
| 870 |  |  |  |  |  |  | else{ | 
| 871 | 63 |  |  |  |  | 68 | $code_package = $package; | 
| 872 | 63 |  |  |  |  | 59 | $code_name    = $thingy; | 
| 873 | 1 |  |  | 1 |  | 5 | no strict 'refs'; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 873 |  | 
| 874 | 63 |  |  |  |  | 53 | $code         = \&{ $code_package . '::' . $code_name }; | 
|  | 63 |  |  |  |  | 203 |  | 
| 875 |  |  |  |  |  |  | } | 
| 876 |  |  |  |  |  |  |  | 
| 877 | 69 |  |  |  |  | 111 | push @all, $code_name; | 
| 878 | 69 |  |  |  |  | 115 | $exports{$code_name} = $code; | 
| 879 | 69 | 100 |  |  |  | 125 | if($code_package eq $package){ | 
| 880 | 63 |  |  |  |  | 112 | push @removables, $code_name; | 
| 881 |  |  |  |  |  |  | } | 
| 882 |  |  |  |  |  |  | } | 
| 883 |  |  |  |  |  |  | } | 
| 884 |  |  |  |  |  |  |  | 
| 885 | 6 | 100 |  |  |  | 82 | if(my $init_meta = $package->can('init_meta')){ | 
| 886 | 3 | 50 |  |  |  | 8 | if(!grep{ $_ == $init_meta } @init_meta_methods){ | 
|  | 0 |  |  |  |  | 0 |  | 
| 887 | 3 |  |  |  |  | 7 | push @init_meta_methods, $init_meta; | 
| 888 |  |  |  |  |  |  | } | 
| 889 |  |  |  |  |  |  | } | 
| 890 |  |  |  |  |  |  | } | 
| 891 | 5 |  |  |  |  | 11 | $args{EXPORTS}    = \%exports; | 
| 892 | 5 |  |  |  |  | 8 | $args{REMOVABLES} = \@removables; | 
| 893 |  |  |  |  |  |  |  | 
| 894 | 5 |  | 50 |  |  | 29 | $args{groups}{all} ||= \@all; | 
| 895 |  |  |  |  |  |  |  | 
| 896 | 5 | 100 |  |  |  | 11 | if(my $default_list = $args{groups}{default}){ | 
| 897 | 1 |  |  |  |  | 2 | my %default; | 
| 898 | 1 |  |  |  |  | 2 | foreach my $keyword(@{$default_list}){ | 
|  | 1 |  |  |  |  | 2 |  | 
| 899 | 0 |  | 0 |  |  | 0 | $default{$keyword} = $exports{$keyword} | 
| 900 |  |  |  |  |  |  | || Carp::confess(qq{The $exporting_package package does not export "$keyword"}); | 
| 901 |  |  |  |  |  |  | } | 
| 902 | 1 |  |  |  |  | 4 | $args{DEFAULT} = \%default; | 
| 903 |  |  |  |  |  |  | } | 
| 904 |  |  |  |  |  |  | else{ | 
| 905 | 4 |  | 50 |  |  | 17 | $args{groups}{default} ||= \@all; | 
| 906 | 4 |  |  |  |  | 8 | $args{DEFAULT}           = $args{EXPORTS}; | 
| 907 |  |  |  |  |  |  | } | 
| 908 |  |  |  |  |  |  |  | 
| 909 | 5 | 100 |  |  |  | 12 | if(@init_meta_methods){ | 
| 910 | 3 |  |  |  |  | 6 | $args{INIT_META} = \@init_meta_methods; | 
| 911 |  |  |  |  |  |  | } | 
| 912 |  |  |  |  |  |  |  | 
| 913 | 5 |  |  |  |  | 23 | return (\&do_import, \&do_unimport); | 
| 914 |  |  |  |  |  |  | } | 
| 915 |  |  |  |  |  |  |  | 
| 916 |  |  |  |  |  |  | # the entity of general import() | 
| 917 |  |  |  |  |  |  | sub do_import { | 
| 918 | 18 |  |  | 18 | 0 | 49 | my($package, @args) = @_; | 
| 919 |  |  |  |  |  |  |  | 
| 920 | 18 |  | 33 |  |  | 66 | my $spec = $SPEC{$package} | 
| 921 |  |  |  |  |  |  | || Carp::confess("The package $package package does not use Mousse::Exporter"); | 
| 922 |  |  |  |  |  |  |  | 
| 923 | 18 | 50 |  |  |  | 63 | my $into = _get_caller_package(ref($args[0]) ? shift @args : undef); | 
| 924 |  |  |  |  |  |  |  | 
| 925 | 18 |  |  |  |  | 24 | my @exports; | 
| 926 |  |  |  |  |  |  | my @traits; | 
| 927 |  |  |  |  |  |  |  | 
| 928 | 18 |  |  |  |  | 40 | while(@args){ | 
| 929 | 14 |  |  |  |  | 20 | my $arg = shift @args; | 
| 930 | 14 | 50 |  |  |  | 79 | if($arg =~ s/^-//){ | 
|  |  | 100 |  |  |  |  |  | 
| 931 | 0 | 0 |  |  |  | 0 | if($arg eq 'traits'){ | 
| 932 | 0 | 0 |  |  |  | 0 | push @traits, ref($args[0]) ? @{shift(@args)} : shift(@args); | 
|  | 0 |  |  |  |  | 0 |  | 
| 933 |  |  |  |  |  |  | } | 
| 934 |  |  |  |  |  |  | else { | 
| 935 | 0 |  |  |  |  | 0 | Mousse::Util::not_supported("-$arg"); | 
| 936 |  |  |  |  |  |  | } | 
| 937 |  |  |  |  |  |  | } | 
| 938 |  |  |  |  |  |  | elsif($arg =~ s/^://){ | 
| 939 | 11 |  | 33 |  |  | 38 | my $group = $spec->{groups}{$arg} | 
| 940 |  |  |  |  |  |  | || Carp::confess(qq{The $package package does not export the group "$arg"}); | 
| 941 | 11 |  |  |  |  | 11 | push @exports, @{$group}; | 
|  | 11 |  |  |  |  | 204 |  | 
| 942 |  |  |  |  |  |  | } | 
| 943 |  |  |  |  |  |  | else{ | 
| 944 | 3 |  |  |  |  | 7 | push @exports, $arg; | 
| 945 |  |  |  |  |  |  | } | 
| 946 |  |  |  |  |  |  | } | 
| 947 |  |  |  |  |  |  |  | 
| 948 |  |  |  |  |  |  | # strict->import; | 
| 949 | 18 |  |  |  |  | 42 | $^H              |= $strict_bits; | 
| 950 |  |  |  |  |  |  | # warnings->import('all', FATAL => 'recursion'); | 
| 951 | 18 |  |  |  |  | 57 | ${^WARNING_BITS} |= $warnings::Bits{all}; | 
| 952 | 18 |  |  |  |  | 33 | ${^WARNING_BITS} |= $warnings_extra_bits; | 
| 953 |  |  |  |  |  |  |  | 
| 954 | 18 | 100 |  |  |  | 50 | if($spec->{INIT_META}){ | 
|  |  | 50 |  |  |  |  |  | 
| 955 | 2 |  |  |  |  | 3 | my $meta; | 
| 956 | 2 |  |  |  |  | 3 | foreach my $init_meta(@{$spec->{INIT_META}}){ | 
|  | 2 |  |  |  |  | 5 |  | 
| 957 | 2 |  |  |  |  | 5 | $meta = $package->$init_meta(for_class => $into); | 
| 958 |  |  |  |  |  |  | } | 
| 959 |  |  |  |  |  |  |  | 
| 960 | 2 | 50 |  |  |  | 7 | if(@traits){ | 
| 961 | 0 |  |  |  |  | 0 | my $type = (split /::/, ref $meta)[-1]; # e.g. "Class" for "My::Meta::Class" | 
| 962 | 0 | 0 |  |  |  | 0 | @traits = map{ | 
| 963 | 0 |  |  |  |  | 0 | ref($_) | 
| 964 |  |  |  |  |  |  | ? $_ | 
| 965 |  |  |  |  |  |  | : Mousse::Util::resolve_metaclass_alias($type => $_, trait => 1) | 
| 966 |  |  |  |  |  |  | } @traits; | 
| 967 |  |  |  |  |  |  |  | 
| 968 | 0 |  |  |  |  | 0 | require Mousse::Util::MetaRole; | 
| 969 | 0 | 0 |  |  |  | 0 | Mousse::Util::MetaRole::apply_metaroles( | 
| 970 |  |  |  |  |  |  | for => $into, | 
| 971 |  |  |  |  |  |  | Mousse::Util::is_a_metarole($into->meta) | 
| 972 |  |  |  |  |  |  | ? (role_metaroles  => { role  => \@traits }) | 
| 973 |  |  |  |  |  |  | : (class_metaroles => { class => \@traits }), | 
| 974 |  |  |  |  |  |  | ); | 
| 975 |  |  |  |  |  |  | } | 
| 976 |  |  |  |  |  |  | } | 
| 977 |  |  |  |  |  |  | elsif(@traits){ | 
| 978 | 0 |  |  |  |  | 0 | Carp::confess("Cannot provide traits when $package does not have an init_meta() method"); | 
| 979 |  |  |  |  |  |  | } | 
| 980 |  |  |  |  |  |  |  | 
| 981 | 18 | 100 |  |  |  | 32 | if(@exports){ | 
| 982 | 12 |  |  |  |  | 13 | my @export_table; | 
| 983 | 12 |  |  |  |  | 19 | foreach my $keyword(@exports){ | 
| 984 | 47 |  | 33 |  |  | 344 | push @export_table, | 
| 985 |  |  |  |  |  |  | $keyword => ($spec->{EXPORTS}{$keyword} | 
| 986 |  |  |  |  |  |  | || Carp::confess(qq{The $package package does not export "$keyword"}) | 
| 987 |  |  |  |  |  |  | ); | 
| 988 |  |  |  |  |  |  | } | 
| 989 | 12 |  |  |  |  | 32 | Mousse::Util::install_subroutines($into, @export_table); | 
| 990 |  |  |  |  |  |  | } | 
| 991 |  |  |  |  |  |  | else{ | 
| 992 | 6 |  |  |  |  | 8 | Mousse::Util::install_subroutines($into, %{$spec->{DEFAULT}}); | 
|  | 6 |  |  |  |  | 89 |  | 
| 993 |  |  |  |  |  |  | } | 
| 994 | 18 |  |  |  |  | 5838 | return; | 
| 995 |  |  |  |  |  |  | } | 
| 996 |  |  |  |  |  |  |  | 
| 997 |  |  |  |  |  |  | # the entity of general unimport() | 
| 998 |  |  |  |  |  |  | sub do_unimport { | 
| 999 | 0 |  |  | 0 | 0 | 0 | my($package, $arg) = @_; | 
| 1000 |  |  |  |  |  |  |  | 
| 1001 | 0 |  | 0 |  |  | 0 | my $spec = $SPEC{$package} | 
| 1002 |  |  |  |  |  |  | || Carp::confess("The package $package does not use Mousse::Exporter"); | 
| 1003 |  |  |  |  |  |  |  | 
| 1004 | 0 |  |  |  |  | 0 | my $from = _get_caller_package($arg); | 
| 1005 |  |  |  |  |  |  |  | 
| 1006 | 0 |  |  |  |  | 0 | my $stash = do{ | 
| 1007 | 1 |  |  | 1 |  | 4 | no strict 'refs'; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 187 |  | 
| 1008 | 0 |  |  |  |  | 0 | \%{$from . '::'} | 
|  | 0 |  |  |  |  | 0 |  | 
| 1009 |  |  |  |  |  |  | }; | 
| 1010 |  |  |  |  |  |  |  | 
| 1011 | 0 |  |  |  |  | 0 | for my $keyword (@{ $spec->{REMOVABLES} }) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 1012 | 0 | 0 |  |  |  | 0 | next if !exists $stash->{$keyword}; | 
| 1013 | 0 |  |  |  |  | 0 | my $gv = \$stash->{$keyword}; | 
| 1014 |  |  |  |  |  |  |  | 
| 1015 |  |  |  |  |  |  | # remove what is from us | 
| 1016 | 0 | 0 | 0 |  |  | 0 | if(ref($gv) eq 'GLOB' && *{$gv}{CODE} == $spec->{EXPORTS}{$keyword}){ | 
|  | 0 |  |  |  |  | 0 |  | 
| 1017 | 0 |  |  |  |  | 0 | delete $stash->{$keyword}; | 
| 1018 |  |  |  |  |  |  | } | 
| 1019 |  |  |  |  |  |  | } | 
| 1020 | 0 |  |  |  |  | 0 | return; | 
| 1021 |  |  |  |  |  |  | } | 
| 1022 |  |  |  |  |  |  |  | 
| 1023 |  |  |  |  |  |  | sub _get_caller_package { | 
| 1024 | 18 |  |  | 18 |  | 22 | my($arg) = @_; | 
| 1025 |  |  |  |  |  |  |  | 
| 1026 |  |  |  |  |  |  | # We need one extra level because it's called by import so there's a layer | 
| 1027 |  |  |  |  |  |  | # of indirection | 
| 1028 | 18 | 50 |  |  |  | 34 | if(ref $arg){ | 
| 1029 | 0 | 0 |  |  |  | 0 | return defined($arg->{into})       ? $arg->{into} | 
|  |  | 0 |  |  |  |  |  | 
| 1030 |  |  |  |  |  |  | : defined($arg->{into_level}) ? scalar caller(1 + $arg->{into_level}) | 
| 1031 |  |  |  |  |  |  | :                               scalar caller(1); | 
| 1032 |  |  |  |  |  |  | } | 
| 1033 |  |  |  |  |  |  | else{ | 
| 1034 | 18 |  |  |  |  | 56 | return scalar caller(1); | 
| 1035 |  |  |  |  |  |  | } | 
| 1036 |  |  |  |  |  |  | } | 
| 1037 |  |  |  |  |  |  |  | 
| 1038 |  |  |  |  |  |  | # Contents of Mouse::Util | 
| 1039 |  |  |  |  |  |  | package Mousse::Util; | 
| 1040 | 1 |  |  | 1 |  | 4 | use Mousse::Exporter; # enables strict and warnings | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 5 |  | 
| 1041 | 1 |  |  | 1 |  | 5 | no warnings 'once'; | 
|  | 1 |  |  |  |  | 19 |  | 
|  | 1 |  |  |  |  | 87 |  | 
| 1042 |  |  |  |  |  |  |  | 
| 1043 |  |  |  |  |  |  | # Note that those which don't exist here are defined in XS or Mousse::PurePerl | 
| 1044 |  |  |  |  |  |  |  | 
| 1045 |  |  |  |  |  |  | # must be here because it will be refered by other modules loaded | 
| 1046 |  |  |  |  |  |  | sub get_linear_isa($;$); ## no critic | 
| 1047 |  |  |  |  |  |  |  | 
| 1048 |  |  |  |  |  |  | # must be here because it will called in Mousse::Exporter | 
| 1049 |  |  |  |  |  |  | sub install_subroutines { | 
| 1050 | 30 |  |  | 30 | 0 | 41 | my $into = shift; | 
| 1051 |  |  |  |  |  |  |  | 
| 1052 | 30 |  |  |  |  | 100 | while(my($name, $code) = splice @_, 0, 2){ | 
| 1053 | 1 |  |  | 1 |  | 5 | no strict 'refs'; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 27 |  | 
| 1054 | 1 |  |  | 1 |  | 4 | no warnings 'once', 'redefine'; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 35 |  | 
| 1055 | 1 |  |  | 1 |  | 5 | use warnings FATAL => 'uninitialized'; | 
|  | 1 |  |  |  |  | 7 |  | 
|  | 1 |  |  |  |  | 305 |  | 
| 1056 | 98 |  |  |  |  | 98 | *{$into . '::' . $name} = \&{$code}; | 
|  | 98 |  |  |  |  | 744 |  | 
|  | 98 |  |  |  |  | 124 |  | 
| 1057 |  |  |  |  |  |  | } | 
| 1058 | 30 |  |  |  |  | 64 | return; | 
| 1059 |  |  |  |  |  |  | } | 
| 1060 |  |  |  |  |  |  |  | 
| 1061 |  |  |  |  |  |  | BEGIN{ | 
| 1062 |  |  |  |  |  |  | # This is used in Mousse::PurePerl | 
| 1063 | 1 |  |  | 1 |  | 10 | Mousse::Exporter->setup_import_methods( | 
| 1064 |  |  |  |  |  |  | as_is => [qw( | 
| 1065 |  |  |  |  |  |  | find_meta | 
| 1066 |  |  |  |  |  |  | does_role | 
| 1067 |  |  |  |  |  |  | resolve_metaclass_alias | 
| 1068 |  |  |  |  |  |  | apply_all_roles | 
| 1069 |  |  |  |  |  |  | english_list | 
| 1070 |  |  |  |  |  |  |  | 
| 1071 |  |  |  |  |  |  | load_class | 
| 1072 |  |  |  |  |  |  | is_class_loaded | 
| 1073 |  |  |  |  |  |  |  | 
| 1074 |  |  |  |  |  |  | get_linear_isa | 
| 1075 |  |  |  |  |  |  | get_code_info | 
| 1076 |  |  |  |  |  |  |  | 
| 1077 |  |  |  |  |  |  | get_code_package | 
| 1078 |  |  |  |  |  |  | get_code_ref | 
| 1079 |  |  |  |  |  |  |  | 
| 1080 |  |  |  |  |  |  | not_supported | 
| 1081 |  |  |  |  |  |  |  | 
| 1082 |  |  |  |  |  |  | does meta throw_error dump | 
| 1083 |  |  |  |  |  |  | )], | 
| 1084 |  |  |  |  |  |  | groups => { | 
| 1085 |  |  |  |  |  |  | default => [], # export no functions by default | 
| 1086 |  |  |  |  |  |  |  | 
| 1087 |  |  |  |  |  |  | # The ':meta' group is 'use metaclass' for Mousse | 
| 1088 |  |  |  |  |  |  | meta    => [qw(does meta dump throw_error)], | 
| 1089 |  |  |  |  |  |  | }, | 
| 1090 |  |  |  |  |  |  | ); | 
| 1091 |  |  |  |  |  |  |  | 
| 1092 | 1 |  |  |  |  | 2 | our $VERSION = '0.93'; | 
| 1093 |  |  |  |  |  |  |  | 
| 1094 | 1 |  | 33 |  |  | 17 | my $xs = !(defined(&is_valid_class_name) || $ENV{MOUSE_PUREPERL} || $ENV{PERL_ONLY}); | 
| 1095 |  |  |  |  |  |  |  | 
| 1096 |  |  |  |  |  |  | # Because Mousse::Util is loaded first in all the Mousse sub-modules, | 
| 1097 |  |  |  |  |  |  | # XSLoader must be placed here, not in Mousse.pm. | 
| 1098 | 1 | 50 |  |  |  | 11 | if($xs){ | 
| 1099 |  |  |  |  |  |  | # XXX: XSLoader tries to get the object path from caller's file name | 
| 1100 |  |  |  |  |  |  | #      $hack_mouse_file fools its mechanism | 
| 1101 | 0 |  |  |  |  | 0 | (my $hack_mouse_file = __FILE__) =~ s/.Util//; # .../Mousse/Util.pm -> .../Mousse.pm | 
| 1102 | 0 |  | 0 |  |  | 0 | $xs = eval sprintf("#line %d %s\n", __LINE__, $hack_mouse_file) . q{ | 
| 1103 |  |  |  |  |  |  | local $^W = 0; # workaround 'redefine' warning to &install_subroutines | 
| 1104 |  |  |  |  |  |  | require XSLoader; | 
| 1105 |  |  |  |  |  |  | XSLoader::load('Mousse', $VERSION); | 
| 1106 |  |  |  |  |  |  | Mousse::Util->import({ into => 'Mousse::Meta::Method::Constructor::XS' }, ':meta'); | 
| 1107 |  |  |  |  |  |  | Mousse::Util->import({ into => 'Mousse::Meta::Method::Destructor::XS'  }, ':meta'); | 
| 1108 |  |  |  |  |  |  | Mousse::Util->import({ into => 'Mousse::Meta::Method::Accessor::XS'    }, ':meta'); | 
| 1109 |  |  |  |  |  |  | return 1; | 
| 1110 |  |  |  |  |  |  | } || 0; | 
| 1111 | 0 | 0 | 0 |  |  | 0 | warn $@ if $@ && $ENV{MOUSE_XS}; | 
| 1112 |  |  |  |  |  |  | } | 
| 1113 |  |  |  |  |  |  |  | 
| 1114 | 1 | 50 |  |  |  | 4 | if(!$xs){ | 
| 1115 | 1 |  |  |  |  | 6 | require 'Mousse/PurePerl.pm'; # we don't want to create its namespace | 
| 1116 |  |  |  |  |  |  | } | 
| 1117 |  |  |  |  |  |  |  | 
| 1118 | 1 |  |  |  |  | 16 | *MOUSE_XS = sub(){ $xs }; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1119 |  |  |  |  |  |  |  | 
| 1120 |  |  |  |  |  |  | # definition of mro::get_linear_isa() | 
| 1121 | 1 |  |  |  |  | 3 | my $get_linear_isa; | 
| 1122 | 1 | 50 |  |  |  | 1 | if (eval { require mro }) { | 
|  | 1 |  |  |  |  | 1032 |  | 
| 1123 | 1 |  |  |  |  | 809 | $get_linear_isa = \&mro::get_linear_isa; | 
| 1124 |  |  |  |  |  |  | } | 
| 1125 |  |  |  |  |  |  | else { | 
| 1126 |  |  |  |  |  |  | # this code is based on MRO::Compat::__get_linear_isa | 
| 1127 | 0 |  |  |  |  | 0 | my $_get_linear_isa_dfs; # this recurses so it isn't pretty | 
| 1128 |  |  |  |  |  |  | $_get_linear_isa_dfs = sub { | 
| 1129 | 0 |  |  |  |  | 0 | my($classname) = @_; | 
| 1130 |  |  |  |  |  |  |  | 
| 1131 | 0 |  |  |  |  | 0 | my @lin = ($classname); | 
| 1132 | 0 |  |  |  |  | 0 | my %stored; | 
| 1133 |  |  |  |  |  |  |  | 
| 1134 | 1 |  |  | 1 |  | 4 | no strict 'refs'; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 240 |  | 
| 1135 | 0 |  |  |  |  | 0 | foreach my $parent (@{"$classname\::ISA"}) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 1136 | 0 |  |  |  |  | 0 | foreach  my $p(@{ $_get_linear_isa_dfs->($parent) }) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 1137 | 0 | 0 |  |  |  | 0 | next if exists $stored{$p}; | 
| 1138 | 0 |  |  |  |  | 0 | push(@lin, $p); | 
| 1139 | 0 |  |  |  |  | 0 | $stored{$p} = 1; | 
| 1140 |  |  |  |  |  |  | } | 
| 1141 |  |  |  |  |  |  | } | 
| 1142 | 0 |  |  |  |  | 0 | return \@lin; | 
| 1143 | 0 |  |  |  |  | 0 | }; | 
| 1144 |  |  |  |  |  |  |  | 
| 1145 |  |  |  |  |  |  | { | 
| 1146 | 0 |  |  |  |  | 0 | package # hide from PAUSE | 
| 1147 |  |  |  |  |  |  | Class::C3; | 
| 1148 | 0 |  |  |  |  | 0 | our %MRO; # avoid 'once' warnings | 
| 1149 |  |  |  |  |  |  | } | 
| 1150 |  |  |  |  |  |  |  | 
| 1151 |  |  |  |  |  |  | # MRO::Compat::__get_linear_isa has no prototype, so | 
| 1152 |  |  |  |  |  |  | # we define a prototyped version for compatibility with core's | 
| 1153 |  |  |  |  |  |  | # See also MRO::Compat::__get_linear_isa. | 
| 1154 |  |  |  |  |  |  | $get_linear_isa = sub ($;$){ | 
| 1155 | 0 |  |  |  |  | 0 | my($classname, $type) = @_; | 
| 1156 |  |  |  |  |  |  |  | 
| 1157 | 0 | 0 |  |  |  | 0 | if(!defined $type){ | 
| 1158 | 0 | 0 |  |  |  | 0 | $type = exists $Class::C3::MRO{$classname} ? 'c3' : 'dfs'; | 
| 1159 |  |  |  |  |  |  | } | 
| 1160 | 0 | 0 |  |  |  | 0 | if($type eq 'c3'){ | 
| 1161 | 0 |  |  |  |  | 0 | require Class::C3; | 
| 1162 | 0 |  |  |  |  | 0 | return [Class::C3::calculateMRO($classname)]; | 
| 1163 |  |  |  |  |  |  | } | 
| 1164 |  |  |  |  |  |  | else{ | 
| 1165 | 0 |  |  |  |  | 0 | return $_get_linear_isa_dfs->($classname); | 
| 1166 |  |  |  |  |  |  | } | 
| 1167 | 0 |  |  |  |  | 0 | }; | 
| 1168 |  |  |  |  |  |  | } | 
| 1169 |  |  |  |  |  |  |  | 
| 1170 | 1 |  |  |  |  | 23 | *get_linear_isa = $get_linear_isa; | 
| 1171 |  |  |  |  |  |  | } | 
| 1172 |  |  |  |  |  |  |  | 
| 1173 | 1 |  |  | 1 |  | 7 | use Carp         (); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 14 |  | 
| 1174 | 1 |  |  | 1 |  | 6 | use Scalar::Util (); | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 1588 |  | 
| 1175 |  |  |  |  |  |  |  | 
| 1176 |  |  |  |  |  |  | # aliases as public APIs | 
| 1177 |  |  |  |  |  |  | # it must be 'require', not 'use', because Mousse::Meta::Module depends on Mousse::Util | 
| 1178 |  |  |  |  |  |  | require Mousse::Meta::Module; # for the entities of metaclass cache utilities | 
| 1179 |  |  |  |  |  |  |  | 
| 1180 |  |  |  |  |  |  | # aliases | 
| 1181 |  |  |  |  |  |  | { | 
| 1182 |  |  |  |  |  |  | *class_of                    = \&Mousse::Meta::Module::_class_of; | 
| 1183 |  |  |  |  |  |  | *get_metaclass_by_name       = \&Mousse::Meta::Module::_get_metaclass_by_name; | 
| 1184 |  |  |  |  |  |  | *get_all_metaclass_instances = \&Mousse::Meta::Module::_get_all_metaclass_instances; | 
| 1185 |  |  |  |  |  |  | *get_all_metaclass_names     = \&Mousse::Meta::Module::_get_all_metaclass_names; | 
| 1186 |  |  |  |  |  |  |  | 
| 1187 |  |  |  |  |  |  | *Mousse::load_class           = \&load_class; | 
| 1188 |  |  |  |  |  |  | *Mousse::is_class_loaded      = \&is_class_loaded; | 
| 1189 |  |  |  |  |  |  |  | 
| 1190 |  |  |  |  |  |  | # is-a predicates | 
| 1191 |  |  |  |  |  |  | #generate_isa_predicate_for('Mousse::Meta::TypeConstraint' => 'is_a_type_constraint'); | 
| 1192 |  |  |  |  |  |  | #generate_isa_predicate_for('Mousse::Meta::Class'          => 'is_a_metaclass'); | 
| 1193 |  |  |  |  |  |  | #generate_isa_predicate_for('Mousse::Meta::Role'           => 'is_a_metarole'); | 
| 1194 |  |  |  |  |  |  |  | 
| 1195 |  |  |  |  |  |  | # duck type predicates | 
| 1196 |  |  |  |  |  |  | generate_can_predicate_for(['_compiled_type_constraint']  => 'is_a_type_constraint'); | 
| 1197 |  |  |  |  |  |  | generate_can_predicate_for(['create_anon_class']          => 'is_a_metaclass'); | 
| 1198 |  |  |  |  |  |  | generate_can_predicate_for(['create_anon_role']           => 'is_a_metarole'); | 
| 1199 |  |  |  |  |  |  | } | 
| 1200 |  |  |  |  |  |  |  | 
| 1201 |  |  |  |  |  |  | our $in_global_destruction = 0; | 
| 1202 | 1 |  |  | 1 |  | 7 | END{ $in_global_destruction = 1 } | 
| 1203 |  |  |  |  |  |  |  | 
| 1204 |  |  |  |  |  |  | # Moose::Util compatible utilities | 
| 1205 |  |  |  |  |  |  |  | 
| 1206 |  |  |  |  |  |  | sub find_meta{ | 
| 1207 | 0 |  |  | 0 | 0 | 0 | return class_of( $_[0] ); | 
| 1208 |  |  |  |  |  |  | } | 
| 1209 |  |  |  |  |  |  |  | 
| 1210 |  |  |  |  |  |  | sub does_role{ | 
| 1211 | 0 |  |  | 0 | 0 | 0 | my ($class_or_obj, $role_name) = @_; | 
| 1212 |  |  |  |  |  |  |  | 
| 1213 | 0 |  |  |  |  | 0 | my $meta = class_of($class_or_obj); | 
| 1214 |  |  |  |  |  |  |  | 
| 1215 | 0 | 0 | 0 |  |  | 0 | (defined $role_name) | 
| 1216 |  |  |  |  |  |  | || ($meta || 'Mousse::Meta::Class')->throw_error("You must supply a role name to does()"); | 
| 1217 |  |  |  |  |  |  |  | 
| 1218 | 0 |  | 0 |  |  | 0 | return defined($meta) && $meta->does_role($role_name); | 
| 1219 |  |  |  |  |  |  | } | 
| 1220 |  |  |  |  |  |  |  | 
| 1221 |  |  |  |  |  |  | # taken from Mousse::Util (0.90) | 
| 1222 |  |  |  |  |  |  | { | 
| 1223 |  |  |  |  |  |  | my %cache; | 
| 1224 |  |  |  |  |  |  |  | 
| 1225 |  |  |  |  |  |  | sub resolve_metaclass_alias { | 
| 1226 | 0 |  |  | 0 | 0 | 0 | my ( $type, $metaclass_name, %options ) = @_; | 
| 1227 |  |  |  |  |  |  |  | 
| 1228 | 0 | 0 |  |  |  | 0 | my $cache_key = $type . q{ } . ( $options{trait} ? '-Trait' : '' ); | 
| 1229 |  |  |  |  |  |  |  | 
| 1230 | 0 |  | 0 |  |  | 0 | return $cache{$cache_key}{$metaclass_name} ||= do{ | 
| 1231 |  |  |  |  |  |  |  | 
| 1232 | 0 | 0 |  |  |  | 0 | my $possible_full_name = join '::', | 
| 1233 |  |  |  |  |  |  | 'Mousse::Meta', $type, 'Custom', ($options{trait} ? 'Trait' : ()), $metaclass_name | 
| 1234 |  |  |  |  |  |  | ; | 
| 1235 |  |  |  |  |  |  |  | 
| 1236 | 0 |  |  |  |  | 0 | my $loaded_class = load_first_existing_class( | 
| 1237 |  |  |  |  |  |  | $possible_full_name, | 
| 1238 |  |  |  |  |  |  | $metaclass_name | 
| 1239 |  |  |  |  |  |  | ); | 
| 1240 |  |  |  |  |  |  |  | 
| 1241 | 0 | 0 |  |  |  | 0 | $loaded_class->can('register_implementation') | 
| 1242 |  |  |  |  |  |  | ? $loaded_class->register_implementation | 
| 1243 |  |  |  |  |  |  | : $loaded_class; | 
| 1244 |  |  |  |  |  |  | }; | 
| 1245 |  |  |  |  |  |  | } | 
| 1246 |  |  |  |  |  |  | } | 
| 1247 |  |  |  |  |  |  |  | 
| 1248 |  |  |  |  |  |  | # Utilities from Class::MOP | 
| 1249 |  |  |  |  |  |  |  | 
| 1250 |  |  |  |  |  |  | sub get_code_info; | 
| 1251 |  |  |  |  |  |  | sub get_code_package; | 
| 1252 |  |  |  |  |  |  |  | 
| 1253 |  |  |  |  |  |  | sub is_valid_class_name; | 
| 1254 |  |  |  |  |  |  | sub is_class_loaded; | 
| 1255 |  |  |  |  |  |  |  | 
| 1256 |  |  |  |  |  |  | # taken from Class/MOP.pm | 
| 1257 |  |  |  |  |  |  | sub load_first_existing_class { | 
| 1258 | 0 | 0 |  | 0 | 0 | 0 | my @classes = @_ | 
| 1259 |  |  |  |  |  |  | or return; | 
| 1260 |  |  |  |  |  |  |  | 
| 1261 | 0 |  |  |  |  | 0 | my %exceptions; | 
| 1262 | 0 |  |  |  |  | 0 | for my $class (@classes) { | 
| 1263 | 0 |  |  |  |  | 0 | my $e = _try_load_one_class($class); | 
| 1264 |  |  |  |  |  |  |  | 
| 1265 | 0 | 0 |  |  |  | 0 | if ($e) { | 
| 1266 | 0 |  |  |  |  | 0 | $exceptions{$class} = $e; | 
| 1267 |  |  |  |  |  |  | } | 
| 1268 |  |  |  |  |  |  | else { | 
| 1269 | 0 |  |  |  |  | 0 | return $class; | 
| 1270 |  |  |  |  |  |  | } | 
| 1271 |  |  |  |  |  |  | } | 
| 1272 |  |  |  |  |  |  |  | 
| 1273 |  |  |  |  |  |  | # not found | 
| 1274 | 0 |  |  |  |  | 0 | Carp::confess join( | 
| 1275 |  |  |  |  |  |  | "\n", | 
| 1276 |  |  |  |  |  |  | map { | 
| 1277 | 0 |  |  |  |  | 0 | sprintf( "Could not load class (%s) because : %s", | 
| 1278 |  |  |  |  |  |  | $_, $exceptions{$_} ) | 
| 1279 |  |  |  |  |  |  | } @classes | 
| 1280 |  |  |  |  |  |  | ); | 
| 1281 |  |  |  |  |  |  | } | 
| 1282 |  |  |  |  |  |  |  | 
| 1283 |  |  |  |  |  |  | # taken from Class/MOP.pm | 
| 1284 |  |  |  |  |  |  | sub _try_load_one_class { | 
| 1285 | 5 |  |  | 5 |  | 7 | my $class = shift; | 
| 1286 |  |  |  |  |  |  |  | 
| 1287 | 5 | 50 |  |  |  | 10 | unless ( is_valid_class_name($class) ) { | 
| 1288 | 0 | 0 |  |  |  | 0 | my $display = defined($class) ? $class : 'undef'; | 
| 1289 | 0 |  |  |  |  | 0 | Carp::confess "Invalid class name ($display)"; | 
| 1290 |  |  |  |  |  |  | } | 
| 1291 |  |  |  |  |  |  |  | 
| 1292 | 5 | 50 |  |  |  | 14 | return '' if is_class_loaded($class); | 
| 1293 |  |  |  |  |  |  |  | 
| 1294 | 0 |  |  |  |  | 0 | $class  =~ s{::}{/}g; | 
| 1295 | 0 |  |  |  |  | 0 | $class .= '.pm'; | 
| 1296 |  |  |  |  |  |  |  | 
| 1297 | 0 |  |  |  |  | 0 | return do { | 
| 1298 | 0 |  |  |  |  | 0 | local $@; | 
| 1299 | 0 |  |  |  |  | 0 | eval { require $class }; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1300 | 0 |  |  |  |  | 0 | $@; | 
| 1301 |  |  |  |  |  |  | }; | 
| 1302 |  |  |  |  |  |  | } | 
| 1303 |  |  |  |  |  |  |  | 
| 1304 |  |  |  |  |  |  |  | 
| 1305 |  |  |  |  |  |  | sub load_class { | 
| 1306 | 5 |  |  | 5 | 0 | 8 | my $class = shift; | 
| 1307 | 5 |  |  |  |  | 13 | my $e = _try_load_one_class($class); | 
| 1308 | 5 | 50 |  |  |  | 18 | Carp::confess "Could not load class ($class) because : $e" if $e; | 
| 1309 |  |  |  |  |  |  |  | 
| 1310 | 5 |  |  |  |  | 18 | return $class; | 
| 1311 |  |  |  |  |  |  | } | 
| 1312 |  |  |  |  |  |  |  | 
| 1313 |  |  |  |  |  |  |  | 
| 1314 |  |  |  |  |  |  | sub apply_all_roles { | 
| 1315 | 0 | 0 |  | 0 | 0 | 0 | my $consumer = Scalar::Util::blessed($_[0]) | 
| 1316 |  |  |  |  |  |  | ?                                $_[0]   # instance | 
| 1317 |  |  |  |  |  |  | : Mousse::Meta::Class->initialize($_[0]); # class or role name | 
| 1318 |  |  |  |  |  |  |  | 
| 1319 | 0 |  |  |  |  | 0 | my @roles; | 
| 1320 |  |  |  |  |  |  |  | 
| 1321 |  |  |  |  |  |  | # Basis of Data::OptList | 
| 1322 | 0 |  |  |  |  | 0 | my $max = scalar(@_); | 
| 1323 | 0 |  |  |  |  | 0 | for (my $i = 1; $i < $max ; $i++) { | 
| 1324 | 0 |  |  |  |  | 0 | my $role = $_[$i]; | 
| 1325 | 0 |  |  |  |  | 0 | my $role_name; | 
| 1326 | 0 | 0 |  |  |  | 0 | if(ref $role) { | 
| 1327 | 0 |  |  |  |  | 0 | $role_name = $role->name; | 
| 1328 |  |  |  |  |  |  | } | 
| 1329 |  |  |  |  |  |  | else { | 
| 1330 | 0 |  |  |  |  | 0 | $role_name = $role; | 
| 1331 | 0 |  |  |  |  | 0 | load_class($role_name); | 
| 1332 | 0 |  |  |  |  | 0 | $role = get_metaclass_by_name($role_name); | 
| 1333 |  |  |  |  |  |  | } | 
| 1334 |  |  |  |  |  |  |  | 
| 1335 | 0 | 0 | 0 |  |  | 0 | if ($i + 1 < $max && ref($_[$i + 1]) eq 'HASH') { | 
| 1336 | 0 |  |  |  |  | 0 | push @roles, [ $role => $_[++$i] ]; | 
| 1337 |  |  |  |  |  |  | } else { | 
| 1338 | 0 |  |  |  |  | 0 | push @roles, [ $role => undef ]; | 
| 1339 |  |  |  |  |  |  | } | 
| 1340 | 0 | 0 |  |  |  | 0 | is_a_metarole($role) | 
| 1341 |  |  |  |  |  |  | || $consumer->meta->throw_error("You can only consume roles, $role_name is not a Mousse role"); | 
| 1342 |  |  |  |  |  |  | } | 
| 1343 |  |  |  |  |  |  |  | 
| 1344 | 0 | 0 |  |  |  | 0 | if ( scalar @roles == 1 ) { | 
| 1345 | 0 |  |  |  |  | 0 | my ( $role, $params ) = @{ $roles[0] }; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1346 | 0 | 0 |  |  |  | 0 | $role->apply( $consumer, defined $params ? $params : () ); | 
| 1347 |  |  |  |  |  |  | } | 
| 1348 |  |  |  |  |  |  | else { | 
| 1349 | 0 |  |  |  |  | 0 | Mousse::Meta::Role->combine(@roles)->apply($consumer); | 
| 1350 |  |  |  |  |  |  | } | 
| 1351 | 0 |  |  |  |  | 0 | return; | 
| 1352 |  |  |  |  |  |  | } | 
| 1353 |  |  |  |  |  |  |  | 
| 1354 |  |  |  |  |  |  | # taken from Moose::Util 0.90 | 
| 1355 |  |  |  |  |  |  | sub english_list { | 
| 1356 | 0 | 0 |  | 0 | 0 | 0 | return $_[0] if @_ == 1; | 
| 1357 |  |  |  |  |  |  |  | 
| 1358 | 0 |  |  |  |  | 0 | my @items = sort @_; | 
| 1359 |  |  |  |  |  |  |  | 
| 1360 | 0 | 0 |  |  |  | 0 | return "$items[0] and $items[1]" if @items == 2; | 
| 1361 |  |  |  |  |  |  |  | 
| 1362 | 0 |  |  |  |  | 0 | my $tail = pop @items; | 
| 1363 |  |  |  |  |  |  |  | 
| 1364 | 0 |  |  |  |  | 0 | return join q{, }, @items, "and $tail"; | 
| 1365 |  |  |  |  |  |  | } | 
| 1366 |  |  |  |  |  |  |  | 
| 1367 |  |  |  |  |  |  | sub quoted_english_list { | 
| 1368 | 0 |  |  | 0 | 0 | 0 | return english_list(map { qq{'$_'} } @_); | 
|  | 0 |  |  |  |  | 0 |  | 
| 1369 |  |  |  |  |  |  | } | 
| 1370 |  |  |  |  |  |  |  | 
| 1371 |  |  |  |  |  |  | # common utilities | 
| 1372 |  |  |  |  |  |  |  | 
| 1373 |  |  |  |  |  |  | sub not_supported{ | 
| 1374 | 0 |  |  | 0 | 0 | 0 | my($feature) = @_; | 
| 1375 |  |  |  |  |  |  |  | 
| 1376 | 0 |  | 0 |  |  | 0 | $feature ||= ( caller(1) )[3] . '()'; # subroutine name | 
| 1377 |  |  |  |  |  |  |  | 
| 1378 | 0 |  |  |  |  | 0 | local $Carp::CarpLevel = $Carp::CarpLevel + 1; | 
| 1379 | 0 |  |  |  |  | 0 | Carp::confess("Mousse does not currently support $feature"); | 
| 1380 |  |  |  |  |  |  | } | 
| 1381 |  |  |  |  |  |  |  | 
| 1382 |  |  |  |  |  |  | # general meta() method | 
| 1383 |  |  |  |  |  |  | sub meta :method{ | 
| 1384 | 0 |  | 0 | 0 | 0 | 0 | return Mousse::Meta::Class->initialize(ref($_[0]) || $_[0]); | 
| 1385 |  |  |  |  |  |  | } | 
| 1386 |  |  |  |  |  |  |  | 
| 1387 |  |  |  |  |  |  | # general throw_error() method | 
| 1388 |  |  |  |  |  |  | # $o->throw_error($msg, depth => $leve, longmess => $croak_or_confess) | 
| 1389 |  |  |  |  |  |  | sub throw_error :method { | 
| 1390 | 0 |  |  | 0 | 0 | 0 | my($self, $message, %args) = @_; | 
| 1391 |  |  |  |  |  |  |  | 
| 1392 | 0 |  | 0 |  |  | 0 | local $Carp::CarpLevel  = $Carp::CarpLevel + 1 + ($args{depth} || 0); | 
| 1393 | 0 |  |  |  |  | 0 | local $Carp::MaxArgNums = 20; # default is 8, usually we use named args which gets messier though | 
| 1394 |  |  |  |  |  |  |  | 
| 1395 | 0 | 0 | 0 |  |  | 0 | if(exists $args{longmess} && !$args{longmess}) { | 
| 1396 | 0 |  |  |  |  | 0 | Carp::croak($message); | 
| 1397 |  |  |  |  |  |  | } | 
| 1398 |  |  |  |  |  |  | else{ | 
| 1399 | 0 |  |  |  |  | 0 | Carp::confess($message); | 
| 1400 |  |  |  |  |  |  | } | 
| 1401 |  |  |  |  |  |  | } | 
| 1402 |  |  |  |  |  |  |  | 
| 1403 |  |  |  |  |  |  | # general dump() method | 
| 1404 |  |  |  |  |  |  | sub dump :method { | 
| 1405 | 0 |  |  | 0 | 0 | 0 | my($self, $maxdepth) = @_; | 
| 1406 |  |  |  |  |  |  |  | 
| 1407 | 0 |  |  |  |  | 0 | require 'Data/Dumper.pm'; # we don't want to create its namespace | 
| 1408 | 0 |  |  |  |  | 0 | my $dd = Data::Dumper->new([$self]); | 
| 1409 | 0 | 0 |  |  |  | 0 | $dd->Maxdepth(defined($maxdepth) ? $maxdepth : 3); | 
| 1410 | 0 |  |  |  |  | 0 | $dd->Indent(1); | 
| 1411 | 0 |  |  |  |  | 0 | $dd->Sortkeys(1); | 
| 1412 | 0 |  |  |  |  | 0 | $dd->Quotekeys(0); | 
| 1413 | 0 |  |  |  |  | 0 | return $dd->Dump(); | 
| 1414 |  |  |  |  |  |  | } | 
| 1415 |  |  |  |  |  |  |  | 
| 1416 |  |  |  |  |  |  | # general does() method | 
| 1417 |  |  |  |  |  |  | sub does :method { | 
| 1418 | 0 |  |  | 0 | 0 | 0 | goto &does_role; | 
| 1419 |  |  |  |  |  |  | } | 
| 1420 |  |  |  |  |  |  |  | 
| 1421 |  |  |  |  |  |  | # Contents of Mouse::Meta::TypeConstraint | 
| 1422 |  |  |  |  |  |  | package Mousse::Meta::TypeConstraint; | 
| 1423 | 1 |  |  | 1 |  | 8 | use Mousse::Util qw(:meta); # enables strict and warnings | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 6 |  | 
| 1424 |  |  |  |  |  |  |  | 
| 1425 |  |  |  |  |  |  | sub new { | 
| 1426 | 23 |  |  | 23 | 0 | 26 | my $class = shift; | 
| 1427 | 23 | 50 |  |  |  | 84 | my %args  = @_ == 1 ? %{$_[0]} : @_; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1428 |  |  |  |  |  |  |  | 
| 1429 | 23 | 50 |  |  |  | 46 | $args{name} = '__ANON__' if !defined $args{name}; | 
| 1430 |  |  |  |  |  |  |  | 
| 1431 | 23 |  |  |  |  | 19 | my $type_parameter; | 
| 1432 | 23 | 100 |  |  |  | 41 | if(defined $args{parent}) { # subtyping | 
| 1433 | 22 |  |  |  |  | 21 | %args = (%{$args{parent}}, %args); | 
|  | 22 |  |  |  |  | 143 |  | 
| 1434 |  |  |  |  |  |  |  | 
| 1435 |  |  |  |  |  |  | # a child type must not inherit 'compiled_type_constraint' | 
| 1436 |  |  |  |  |  |  | # and 'hand_optimized_type_constraint' from the parent | 
| 1437 | 22 |  |  |  |  | 56 | delete $args{compiled_type_constraint};       # don't inherit it | 
| 1438 | 22 |  |  |  |  | 29 | delete $args{hand_optimized_type_constraint}; # don't inherit it | 
| 1439 |  |  |  |  |  |  |  | 
| 1440 | 22 |  |  |  |  | 24 | $type_parameter = $args{type_parameter}; | 
| 1441 | 22 | 50 |  |  |  | 53 | if(defined(my $parent_tp = $args{parent}{type_parameter})) { | 
| 1442 | 0 | 0 |  |  |  | 0 | if($parent_tp != $type_parameter) { | 
| 1443 | 0 | 0 |  |  |  | 0 | $type_parameter->is_a_type_of($parent_tp) | 
| 1444 |  |  |  |  |  |  | or $class->throw_error( | 
| 1445 |  |  |  |  |  |  | "$type_parameter is not a subtype of $parent_tp", | 
| 1446 |  |  |  |  |  |  | ); | 
| 1447 |  |  |  |  |  |  | } | 
| 1448 |  |  |  |  |  |  | else { | 
| 1449 | 0 |  |  |  |  | 0 | $type_parameter = undef; | 
| 1450 |  |  |  |  |  |  | } | 
| 1451 |  |  |  |  |  |  | } | 
| 1452 |  |  |  |  |  |  | } | 
| 1453 |  |  |  |  |  |  |  | 
| 1454 | 23 |  |  |  |  | 26 | my $check; | 
| 1455 |  |  |  |  |  |  |  | 
| 1456 | 23 | 100 |  |  |  | 49 | if($check = delete $args{optimized}) { # likely to be builtins | 
|  |  | 50 |  |  |  |  |  | 
| 1457 | 20 |  |  |  |  | 26 | $args{hand_optimized_type_constraint} = $check; | 
| 1458 | 20 |  |  |  |  | 21 | $args{compiled_type_constraint}       = $check; | 
| 1459 |  |  |  |  |  |  | } | 
| 1460 |  |  |  |  |  |  | elsif(defined $type_parameter) { # parameterizing | 
| 1461 | 0 |  | 0 |  |  | 0 | my $generator = $args{constraint_generator} | 
| 1462 |  |  |  |  |  |  | || $class->throw_error( | 
| 1463 |  |  |  |  |  |  | "The $args{name} constraint cannot be used," | 
| 1464 |  |  |  |  |  |  | . " because $type_parameter doesn't subtype" | 
| 1465 |  |  |  |  |  |  | . " from a parameterizable type"); | 
| 1466 |  |  |  |  |  |  |  | 
| 1467 | 0 |  |  |  |  | 0 | my $parameterized_check = $generator->($type_parameter); | 
| 1468 | 0 | 0 |  |  |  | 0 | if(defined(my $my_check = $args{constraint})) { | 
| 1469 |  |  |  |  |  |  | $check = sub { | 
| 1470 | 0 |  | 0 | 0 |  | 0 | return $parameterized_check->($_) && $my_check->($_); | 
| 1471 | 0 |  |  |  |  | 0 | }; | 
| 1472 |  |  |  |  |  |  | } | 
| 1473 |  |  |  |  |  |  | else { | 
| 1474 | 0 |  |  |  |  | 0 | $check = $parameterized_check; | 
| 1475 |  |  |  |  |  |  | } | 
| 1476 | 0 |  |  |  |  | 0 | $args{constraint} = $check; | 
| 1477 |  |  |  |  |  |  | } | 
| 1478 |  |  |  |  |  |  | else { # common cases | 
| 1479 | 3 |  |  |  |  | 4 | $check = $args{constraint}; | 
| 1480 |  |  |  |  |  |  | } | 
| 1481 |  |  |  |  |  |  |  | 
| 1482 | 23 | 50 | 66 |  |  | 94 | if(defined($check) && ref($check) ne 'CODE'){ | 
| 1483 | 0 |  |  |  |  | 0 | $class->throw_error( | 
| 1484 |  |  |  |  |  |  | "Constraint for $args{name} is not a CODE reference"); | 
| 1485 |  |  |  |  |  |  | } | 
| 1486 |  |  |  |  |  |  |  | 
| 1487 | 23 |  |  |  |  | 48 | my $self = bless \%args, $class; | 
| 1488 | 23 | 100 |  |  |  | 52 | $self->compile_type_constraint() | 
| 1489 |  |  |  |  |  |  | if !$args{hand_optimized_type_constraint}; | 
| 1490 |  |  |  |  |  |  |  | 
| 1491 | 23 | 50 |  |  |  | 41 | if($args{type_constraints}) { # union types | 
| 1492 | 0 |  |  |  |  | 0 | foreach my $type(@{$self->{type_constraints}}){ | 
|  | 0 |  |  |  |  | 0 |  | 
| 1493 | 0 | 0 |  |  |  | 0 | if($type->has_coercion){ | 
| 1494 |  |  |  |  |  |  | # set undef for has_coercion() | 
| 1495 | 0 |  |  |  |  | 0 | $self->{_compiled_type_coercion} = undef; | 
| 1496 | 0 |  |  |  |  | 0 | last; | 
| 1497 |  |  |  |  |  |  | } | 
| 1498 |  |  |  |  |  |  | } | 
| 1499 |  |  |  |  |  |  | } | 
| 1500 |  |  |  |  |  |  |  | 
| 1501 | 23 |  |  |  |  | 100 | return $self; | 
| 1502 |  |  |  |  |  |  | } | 
| 1503 |  |  |  |  |  |  |  | 
| 1504 |  |  |  |  |  |  | sub create_child_type { | 
| 1505 | 0 |  |  | 0 | 0 | 0 | my $self = shift; | 
| 1506 | 0 |  |  |  |  | 0 | return ref($self)->new(@_, parent => $self); | 
| 1507 |  |  |  |  |  |  | } | 
| 1508 |  |  |  |  |  |  |  | 
| 1509 |  |  |  |  |  |  | sub name; | 
| 1510 |  |  |  |  |  |  | sub parent; | 
| 1511 |  |  |  |  |  |  | sub message; | 
| 1512 |  |  |  |  |  |  | sub has_coercion; | 
| 1513 |  |  |  |  |  |  |  | 
| 1514 |  |  |  |  |  |  | sub check; | 
| 1515 |  |  |  |  |  |  |  | 
| 1516 |  |  |  |  |  |  | sub type_parameter; | 
| 1517 |  |  |  |  |  |  | sub __is_parameterized; | 
| 1518 |  |  |  |  |  |  |  | 
| 1519 |  |  |  |  |  |  | sub _compiled_type_constraint; | 
| 1520 |  |  |  |  |  |  | sub _compiled_type_coercion; | 
| 1521 |  |  |  |  |  |  |  | 
| 1522 |  |  |  |  |  |  | sub compile_type_constraint; | 
| 1523 |  |  |  |  |  |  |  | 
| 1524 |  |  |  |  |  |  |  | 
| 1525 |  |  |  |  |  |  | sub _add_type_coercions { # ($self, @pairs) | 
| 1526 | 0 |  |  | 0 |  | 0 | my $self = shift; | 
| 1527 |  |  |  |  |  |  |  | 
| 1528 | 0 | 0 |  |  |  | 0 | if(exists $self->{type_constraints}){ # union type | 
| 1529 | 0 |  |  |  |  | 0 | $self->throw_error( | 
| 1530 |  |  |  |  |  |  | "Cannot add additional type coercions to Union types '$self'"); | 
| 1531 |  |  |  |  |  |  | } | 
| 1532 |  |  |  |  |  |  |  | 
| 1533 | 0 |  | 0 |  |  | 0 | my $coercion_map = ($self->{coercion_map} ||= []); | 
| 1534 | 0 |  |  |  |  | 0 | my %has          = map{ $_->[0]->name => undef } @{$coercion_map}; | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 1535 |  |  |  |  |  |  |  | 
| 1536 | 0 |  |  |  |  | 0 | for(my $i = 0; $i < @_; $i++){ | 
| 1537 | 0 |  |  |  |  | 0 | my $from   = $_[  $i]; | 
| 1538 | 0 |  |  |  |  | 0 | my $action = $_[++$i]; | 
| 1539 |  |  |  |  |  |  |  | 
| 1540 | 0 | 0 |  |  |  | 0 | if(exists $has{$from}){ | 
| 1541 | 0 |  |  |  |  | 0 | $self->throw_error("A coercion action already exists for '$from'"); | 
| 1542 |  |  |  |  |  |  | } | 
| 1543 |  |  |  |  |  |  |  | 
| 1544 | 0 | 0 |  |  |  | 0 | my $type = Mousse::Util::TypeConstraints::find_or_parse_type_constraint($from) | 
| 1545 |  |  |  |  |  |  | or $self->throw_error( | 
| 1546 |  |  |  |  |  |  | "Could not find the type constraint ($from) to coerce from"); | 
| 1547 |  |  |  |  |  |  |  | 
| 1548 | 0 |  |  |  |  | 0 | push @{$coercion_map}, [ $type => $action ]; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1549 |  |  |  |  |  |  | } | 
| 1550 |  |  |  |  |  |  |  | 
| 1551 | 0 |  |  |  |  | 0 | $self->{_compiled_type_coercion} = undef; | 
| 1552 | 0 |  |  |  |  | 0 | return; | 
| 1553 |  |  |  |  |  |  | } | 
| 1554 |  |  |  |  |  |  |  | 
| 1555 |  |  |  |  |  |  | sub _compiled_type_coercion { | 
| 1556 | 0 |  |  | 0 |  | 0 | my($self) = @_; | 
| 1557 |  |  |  |  |  |  |  | 
| 1558 | 0 |  |  |  |  | 0 | my $coercion = $self->{_compiled_type_coercion}; | 
| 1559 | 0 | 0 |  |  |  | 0 | return $coercion if defined $coercion; | 
| 1560 |  |  |  |  |  |  |  | 
| 1561 | 0 | 0 |  |  |  | 0 | if(!$self->{type_constraints}) { | 
| 1562 | 0 |  |  |  |  | 0 | my @coercions; | 
| 1563 | 0 |  |  |  |  | 0 | foreach my $pair(@{$self->{coercion_map}}) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 1564 | 0 |  |  |  |  | 0 | push @coercions, | 
| 1565 |  |  |  |  |  |  | [ $pair->[0]->_compiled_type_constraint, $pair->[1] ]; | 
| 1566 |  |  |  |  |  |  | } | 
| 1567 |  |  |  |  |  |  |  | 
| 1568 |  |  |  |  |  |  | $coercion = sub { | 
| 1569 | 0 |  |  | 0 |  | 0 | my($thing) = @_; | 
| 1570 | 0 |  |  |  |  | 0 | foreach my $pair (@coercions) { | 
| 1571 |  |  |  |  |  |  | #my ($constraint, $converter) = @$pair; | 
| 1572 | 0 | 0 |  |  |  | 0 | if ($pair->[0]->($thing)) { | 
| 1573 | 0 |  |  |  |  | 0 | local $_ = $thing; | 
| 1574 | 0 |  |  |  |  | 0 | return $pair->[1]->($thing); | 
| 1575 |  |  |  |  |  |  | } | 
| 1576 |  |  |  |  |  |  | } | 
| 1577 | 0 |  |  |  |  | 0 | return $thing; | 
| 1578 | 0 |  |  |  |  | 0 | }; | 
| 1579 |  |  |  |  |  |  | } | 
| 1580 |  |  |  |  |  |  | else { # for union type | 
| 1581 | 0 |  |  |  |  | 0 | my @coercions; | 
| 1582 | 0 |  |  |  |  | 0 | foreach my $type(@{$self->{type_constraints}}){ | 
|  | 0 |  |  |  |  | 0 |  | 
| 1583 | 0 | 0 |  |  |  | 0 | if($type->has_coercion){ | 
| 1584 | 0 |  |  |  |  | 0 | push @coercions, $type; | 
| 1585 |  |  |  |  |  |  | } | 
| 1586 |  |  |  |  |  |  | } | 
| 1587 | 0 | 0 |  |  |  | 0 | if(@coercions){ | 
| 1588 |  |  |  |  |  |  | $coercion = sub { | 
| 1589 | 0 |  |  | 0 |  | 0 | my($thing) = @_; | 
| 1590 | 0 |  |  |  |  | 0 | foreach my $type(@coercions){ | 
| 1591 | 0 |  |  |  |  | 0 | my $value = $type->coerce($thing); | 
| 1592 | 0 | 0 |  |  |  | 0 | return $value if $self->check($value); | 
| 1593 |  |  |  |  |  |  | } | 
| 1594 | 0 |  |  |  |  | 0 | return $thing; | 
| 1595 | 0 |  |  |  |  | 0 | }; | 
| 1596 |  |  |  |  |  |  | } | 
| 1597 |  |  |  |  |  |  | } | 
| 1598 |  |  |  |  |  |  |  | 
| 1599 | 0 |  |  |  |  | 0 | return( $self->{_compiled_type_coercion} = $coercion ); | 
| 1600 |  |  |  |  |  |  | } | 
| 1601 |  |  |  |  |  |  |  | 
| 1602 |  |  |  |  |  |  | sub coerce { | 
| 1603 | 0 |  |  | 0 | 0 | 0 | my $self = shift; | 
| 1604 | 0 | 0 |  |  |  | 0 | return $_[0] if $self->check(@_); | 
| 1605 |  |  |  |  |  |  |  | 
| 1606 | 0 | 0 |  |  |  | 0 | my $coercion = $self->_compiled_type_coercion | 
| 1607 |  |  |  |  |  |  | or $self->throw_error("Cannot coerce without a type coercion"); | 
| 1608 | 0 |  |  |  |  | 0 | return  $coercion->(@_); | 
| 1609 |  |  |  |  |  |  | } | 
| 1610 |  |  |  |  |  |  |  | 
| 1611 |  |  |  |  |  |  | sub get_message { | 
| 1612 | 0 |  |  | 0 | 0 | 0 | my ($self, $value) = @_; | 
| 1613 | 0 | 0 |  |  |  | 0 | if ( my $msg = $self->message ) { | 
| 1614 | 0 |  |  |  |  | 0 | local $_ = $value; | 
| 1615 | 0 |  |  |  |  | 0 | return $msg->($value); | 
| 1616 |  |  |  |  |  |  | } | 
| 1617 |  |  |  |  |  |  | else { | 
| 1618 | 0 | 0 | 0 |  |  | 0 | if(not defined $value) { | 
|  |  | 0 |  |  |  |  |  | 
| 1619 | 0 |  |  |  |  | 0 | $value = 'undef'; | 
| 1620 |  |  |  |  |  |  | } | 
| 1621 |  |  |  |  |  |  | elsif( ref($value) && defined(&overload::StrVal) ) { | 
| 1622 | 0 |  |  |  |  | 0 | $value = overload::StrVal($value); | 
| 1623 |  |  |  |  |  |  | } | 
| 1624 | 0 |  |  |  |  | 0 | return "Validation failed for '$self' with value $value"; | 
| 1625 |  |  |  |  |  |  | } | 
| 1626 |  |  |  |  |  |  | } | 
| 1627 |  |  |  |  |  |  |  | 
| 1628 |  |  |  |  |  |  | sub is_a_type_of { | 
| 1629 | 0 |  |  | 0 | 0 | 0 | my($self, $other) = @_; | 
| 1630 |  |  |  |  |  |  |  | 
| 1631 |  |  |  |  |  |  | # ->is_a_type_of('__ANON__') is always false | 
| 1632 | 0 | 0 | 0 |  |  | 0 | return 0 if !ref($other) && $other eq '__ANON__'; | 
| 1633 |  |  |  |  |  |  |  | 
| 1634 | 0 |  |  |  |  | 0 | (my $other_name = $other) =~ s/\s+//g; | 
| 1635 |  |  |  |  |  |  |  | 
| 1636 | 0 | 0 |  |  |  | 0 | return 1 if $self->name eq $other_name; | 
| 1637 |  |  |  |  |  |  |  | 
| 1638 | 0 | 0 |  |  |  | 0 | if(exists $self->{type_constraints}){ # union | 
| 1639 | 0 |  |  |  |  | 0 | foreach my $type(@{$self->{type_constraints}}) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 1640 | 0 | 0 |  |  |  | 0 | return 1 if $type->name eq $other_name; | 
| 1641 |  |  |  |  |  |  | } | 
| 1642 |  |  |  |  |  |  | } | 
| 1643 |  |  |  |  |  |  |  | 
| 1644 | 0 |  |  |  |  | 0 | for(my $p = $self->parent; defined $p; $p = $p->parent) { | 
| 1645 | 0 | 0 |  |  |  | 0 | return 1 if $p->name eq $other_name; | 
| 1646 |  |  |  |  |  |  | } | 
| 1647 |  |  |  |  |  |  |  | 
| 1648 | 0 |  |  |  |  | 0 | return 0; | 
| 1649 |  |  |  |  |  |  | } | 
| 1650 |  |  |  |  |  |  |  | 
| 1651 |  |  |  |  |  |  | # See also Moose::Meta::TypeConstraint::Parameterizable | 
| 1652 |  |  |  |  |  |  | sub parameterize { | 
| 1653 | 0 |  |  | 0 | 0 | 0 | my($self, $param, $name) = @_; | 
| 1654 |  |  |  |  |  |  |  | 
| 1655 | 0 | 0 |  |  |  | 0 | if(!ref $param){ | 
| 1656 | 0 |  |  |  |  | 0 | require Mousse::Util::TypeConstraints; | 
| 1657 | 0 |  |  |  |  | 0 | $param = Mousse::Util::TypeConstraints::find_or_create_isa_type_constraint($param); | 
| 1658 |  |  |  |  |  |  | } | 
| 1659 |  |  |  |  |  |  |  | 
| 1660 | 0 |  | 0 |  |  | 0 | $name ||= sprintf '%s[%s]', $self->name, $param->name; | 
| 1661 | 0 |  |  |  |  | 0 | return Mousse::Meta::TypeConstraint->new( | 
| 1662 |  |  |  |  |  |  | name           => $name, | 
| 1663 |  |  |  |  |  |  | parent         => $self, | 
| 1664 |  |  |  |  |  |  | type_parameter => $param, | 
| 1665 |  |  |  |  |  |  | ); | 
| 1666 |  |  |  |  |  |  | } | 
| 1667 |  |  |  |  |  |  |  | 
| 1668 |  |  |  |  |  |  | sub assert_valid { | 
| 1669 | 0 |  |  | 0 | 0 | 0 | my ($self, $value) = @_; | 
| 1670 |  |  |  |  |  |  |  | 
| 1671 | 0 | 0 |  |  |  | 0 | if(!$self->check($value)){ | 
| 1672 | 0 |  |  |  |  | 0 | $self->throw_error($self->get_message($value)); | 
| 1673 |  |  |  |  |  |  | } | 
| 1674 | 0 |  |  |  |  | 0 | return 1; | 
| 1675 |  |  |  |  |  |  | } | 
| 1676 |  |  |  |  |  |  |  | 
| 1677 |  |  |  |  |  |  | # overloading stuff | 
| 1678 |  |  |  |  |  |  |  | 
| 1679 | 0 |  |  | 0 |  | 0 | sub _as_string { $_[0]->name } # overload "" | 
| 1680 |  |  |  |  |  |  | sub _identity;                 # overload 0+ | 
| 1681 |  |  |  |  |  |  |  | 
| 1682 |  |  |  |  |  |  | sub _unite { # overload infix:<|> | 
| 1683 | 0 |  |  | 0 |  | 0 | my($lhs, $rhs) = @_; | 
| 1684 | 0 |  |  |  |  | 0 | require Mousse::Util::TypeConstraints; | 
| 1685 | 0 |  |  |  |  | 0 | return Mousse::Util::TypeConstraints::_find_or_create_union_type( | 
| 1686 |  |  |  |  |  |  | $lhs, | 
| 1687 |  |  |  |  |  |  | Mousse::Util::TypeConstraints::find_or_create_isa_type_constraint($rhs), | 
| 1688 |  |  |  |  |  |  | ); | 
| 1689 |  |  |  |  |  |  | } | 
| 1690 |  |  |  |  |  |  |  | 
| 1691 |  |  |  |  |  |  | # Contents of Mouse::Util::TypeConstraints | 
| 1692 |  |  |  |  |  |  | package Mousse::Util::TypeConstraints; | 
| 1693 | 1 |  |  | 1 |  | 8 | use Mousse::Util; # enables strict and warnings | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 3 |  | 
| 1694 |  |  |  |  |  |  |  | 
| 1695 | 1 |  |  | 1 |  | 6 | use Mousse::Meta::TypeConstraint; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 44 |  | 
| 1696 | 1 |  |  | 1 |  | 5 | use Mousse::Exporter; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 6 |  | 
| 1697 |  |  |  |  |  |  |  | 
| 1698 | 1 |  |  | 1 |  | 6 | use Carp         (); | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 16 |  | 
| 1699 | 1 |  |  | 1 |  | 5 | use Scalar::Util (); | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 4075 |  | 
| 1700 |  |  |  |  |  |  |  | 
| 1701 |  |  |  |  |  |  | Mousse::Exporter->setup_import_methods( | 
| 1702 |  |  |  |  |  |  | as_is => [qw( | 
| 1703 |  |  |  |  |  |  | as where message optimize_as | 
| 1704 |  |  |  |  |  |  | from via | 
| 1705 |  |  |  |  |  |  |  | 
| 1706 |  |  |  |  |  |  | type subtype class_type role_type duck_type | 
| 1707 |  |  |  |  |  |  | enum | 
| 1708 |  |  |  |  |  |  | coerce | 
| 1709 |  |  |  |  |  |  |  | 
| 1710 |  |  |  |  |  |  | find_type_constraint | 
| 1711 |  |  |  |  |  |  | register_type_constraint | 
| 1712 |  |  |  |  |  |  | )], | 
| 1713 |  |  |  |  |  |  | ); | 
| 1714 |  |  |  |  |  |  |  | 
| 1715 |  |  |  |  |  |  | our @CARP_NOT = qw(Mousse::Meta::Attribute); | 
| 1716 |  |  |  |  |  |  |  | 
| 1717 |  |  |  |  |  |  | my %TYPE; | 
| 1718 |  |  |  |  |  |  |  | 
| 1719 |  |  |  |  |  |  | # The root type | 
| 1720 |  |  |  |  |  |  | $TYPE{Any} = Mousse::Meta::TypeConstraint->new( | 
| 1721 |  |  |  |  |  |  | name => 'Any', | 
| 1722 |  |  |  |  |  |  | ); | 
| 1723 |  |  |  |  |  |  |  | 
| 1724 |  |  |  |  |  |  | my @builtins = ( | 
| 1725 |  |  |  |  |  |  | # $name    => $parent,   $code, | 
| 1726 |  |  |  |  |  |  |  | 
| 1727 |  |  |  |  |  |  | # the base type | 
| 1728 |  |  |  |  |  |  | Item       => 'Any',     undef, | 
| 1729 |  |  |  |  |  |  |  | 
| 1730 |  |  |  |  |  |  | # the maybe[] type | 
| 1731 |  |  |  |  |  |  | Maybe      => 'Item',    undef, | 
| 1732 |  |  |  |  |  |  |  | 
| 1733 |  |  |  |  |  |  | # value types | 
| 1734 |  |  |  |  |  |  | Undef      => 'Item',    \&Undef, | 
| 1735 |  |  |  |  |  |  | Defined    => 'Item',    \&Defined, | 
| 1736 |  |  |  |  |  |  | Bool       => 'Item',    \&Bool, | 
| 1737 |  |  |  |  |  |  | Value      => 'Defined', \&Value, | 
| 1738 |  |  |  |  |  |  | Str        => 'Value',   \&Str, | 
| 1739 |  |  |  |  |  |  | Num        => 'Str',     \&Num, | 
| 1740 |  |  |  |  |  |  | Int        => 'Num',     \&Int, | 
| 1741 |  |  |  |  |  |  |  | 
| 1742 |  |  |  |  |  |  | # ref types | 
| 1743 |  |  |  |  |  |  | Ref        => 'Defined', \&Ref, | 
| 1744 |  |  |  |  |  |  | ScalarRef  => 'Ref',     \&ScalarRef, | 
| 1745 |  |  |  |  |  |  | ArrayRef   => 'Ref',     \&ArrayRef, | 
| 1746 |  |  |  |  |  |  | HashRef    => 'Ref',     \&HashRef, | 
| 1747 |  |  |  |  |  |  | CodeRef    => 'Ref',     \&CodeRef, | 
| 1748 |  |  |  |  |  |  | RegexpRef  => 'Ref',     \&RegexpRef, | 
| 1749 |  |  |  |  |  |  | GlobRef    => 'Ref',     \&GlobRef, | 
| 1750 |  |  |  |  |  |  |  | 
| 1751 |  |  |  |  |  |  | # object types | 
| 1752 |  |  |  |  |  |  | FileHandle => 'GlobRef', \&FileHandle, | 
| 1753 |  |  |  |  |  |  | Object     => 'Ref',     \&Object, | 
| 1754 |  |  |  |  |  |  |  | 
| 1755 |  |  |  |  |  |  | # special string types | 
| 1756 |  |  |  |  |  |  | ClassName  => 'Str',       \&ClassName, | 
| 1757 |  |  |  |  |  |  | RoleName   => 'ClassName', \&RoleName, | 
| 1758 |  |  |  |  |  |  | ); | 
| 1759 |  |  |  |  |  |  |  | 
| 1760 |  |  |  |  |  |  | while (my ($name, $parent, $code) = splice @builtins, 0, 3) { | 
| 1761 |  |  |  |  |  |  | $TYPE{$name} = Mousse::Meta::TypeConstraint->new( | 
| 1762 |  |  |  |  |  |  | name      => $name, | 
| 1763 |  |  |  |  |  |  | parent    => $TYPE{$parent}, | 
| 1764 |  |  |  |  |  |  | optimized => $code, | 
| 1765 |  |  |  |  |  |  | ); | 
| 1766 |  |  |  |  |  |  | } | 
| 1767 |  |  |  |  |  |  |  | 
| 1768 |  |  |  |  |  |  | # parametarizable types | 
| 1769 |  |  |  |  |  |  | $TYPE{Maybe}   {constraint_generator} = \&_parameterize_Maybe_for; | 
| 1770 |  |  |  |  |  |  | $TYPE{ArrayRef}{constraint_generator} = \&_parameterize_ArrayRef_for; | 
| 1771 |  |  |  |  |  |  | $TYPE{HashRef} {constraint_generator} = \&_parameterize_HashRef_for; | 
| 1772 |  |  |  |  |  |  |  | 
| 1773 |  |  |  |  |  |  | # sugars | 
| 1774 | 0 |  |  | 0 | 0 | 0 | sub as          ($) { (as          => $_[0]) } ## no critic | 
| 1775 | 0 |  |  | 0 | 0 | 0 | sub where       (&) { (where       => $_[0]) } ## no critic | 
| 1776 | 0 |  |  | 0 | 0 | 0 | sub message     (&) { (message     => $_[0]) } ## no critic | 
| 1777 | 0 |  |  | 0 | 0 | 0 | sub optimize_as (&) { (optimize_as => $_[0]) } ## no critic | 
| 1778 |  |  |  |  |  |  |  | 
| 1779 | 0 |  |  | 0 | 0 | 0 | sub from    { @_ } | 
| 1780 | 0 |  |  | 0 | 0 | 0 | sub via (&) { $_[0] } ## no critic | 
| 1781 |  |  |  |  |  |  |  | 
| 1782 |  |  |  |  |  |  | # type utilities | 
| 1783 |  |  |  |  |  |  |  | 
| 1784 |  |  |  |  |  |  | sub optimized_constraints { # DEPRECATED | 
| 1785 | 0 |  |  | 0 | 0 | 0 | Carp::cluck('optimized_constraints() has been deprecated'); | 
| 1786 | 0 |  |  |  |  | 0 | return \%TYPE; | 
| 1787 |  |  |  |  |  |  | } | 
| 1788 |  |  |  |  |  |  |  | 
| 1789 |  |  |  |  |  |  | undef @builtins;        # free the allocated memory | 
| 1790 |  |  |  |  |  |  | @builtins = keys %TYPE; # reuse it | 
| 1791 | 0 |  |  | 0 | 0 | 0 | sub list_all_builtin_type_constraints { @builtins } | 
| 1792 | 0 |  |  | 0 | 0 | 0 | sub list_all_type_constraints         { keys %TYPE } | 
| 1793 |  |  |  |  |  |  |  | 
| 1794 |  |  |  |  |  |  | sub _define_type { | 
| 1795 | 2 |  |  | 2 |  | 3 | my $is_subtype = shift; | 
| 1796 | 2 |  |  |  |  | 3 | my $name; | 
| 1797 |  |  |  |  |  |  | my %args; | 
| 1798 |  |  |  |  |  |  |  | 
| 1799 | 2 | 50 | 33 |  |  | 17 | if(@_ == 1 && ref $_[0] ){    # @_ : { name => $name, where => ... } | 
|  |  | 50 | 33 |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 1800 | 0 |  |  |  |  | 0 | %args = %{$_[0]}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1801 |  |  |  |  |  |  | } | 
| 1802 |  |  |  |  |  |  | elsif(@_ == 2 && ref $_[1]) { # @_ : $name => { where => ... } | 
| 1803 | 0 |  |  |  |  | 0 | $name = $_[0]; | 
| 1804 | 0 |  |  |  |  | 0 | %args = %{$_[1]}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1805 |  |  |  |  |  |  | } | 
| 1806 |  |  |  |  |  |  | elsif(@_ % 2) {               # @_ : $name => ( where => ... ) | 
| 1807 | 2 |  |  |  |  | 10 | ($name, %args) = @_; | 
| 1808 |  |  |  |  |  |  | } | 
| 1809 |  |  |  |  |  |  | else{                         # @_ : (name => $name, where => ...) | 
| 1810 | 0 |  |  |  |  | 0 | %args = @_; | 
| 1811 |  |  |  |  |  |  | } | 
| 1812 |  |  |  |  |  |  |  | 
| 1813 | 2 | 50 |  |  |  | 7 | if(!defined $name){ | 
| 1814 | 0 |  |  |  |  | 0 | $name = $args{name}; | 
| 1815 |  |  |  |  |  |  | } | 
| 1816 |  |  |  |  |  |  |  | 
| 1817 | 2 |  |  |  |  | 5 | $args{name} = $name; | 
| 1818 |  |  |  |  |  |  |  | 
| 1819 | 2 |  |  |  |  | 5 | my $parent = delete $args{as}; | 
| 1820 | 2 | 50 | 33 |  |  | 12 | if($is_subtype && !$parent){ | 
| 1821 | 0 |  |  |  |  | 0 | $parent = delete $args{name}; | 
| 1822 | 0 |  |  |  |  | 0 | $name   = undef; | 
| 1823 |  |  |  |  |  |  | } | 
| 1824 |  |  |  |  |  |  |  | 
| 1825 | 2 | 50 |  |  |  | 5 | if(defined $parent) { | 
| 1826 | 2 |  |  |  |  | 6 | $args{parent} = find_or_create_isa_type_constraint($parent); | 
| 1827 |  |  |  |  |  |  | } | 
| 1828 |  |  |  |  |  |  |  | 
| 1829 | 2 | 50 |  |  |  | 6 | if(defined $name){ | 
| 1830 |  |  |  |  |  |  | # set 'package_defined_in' only if it is not a core package | 
| 1831 | 2 |  |  |  |  | 4 | my $this = $args{package_defined_in}; | 
| 1832 | 2 | 50 |  |  |  | 5 | if(!$this){ | 
| 1833 | 2 |  |  |  |  | 4 | $this = caller(1); | 
| 1834 | 2 | 50 |  |  |  | 10 | if($this !~ /\A Mousse \b/xms){ | 
| 1835 | 0 |  |  |  |  | 0 | $args{package_defined_in} = $this; | 
| 1836 |  |  |  |  |  |  | } | 
| 1837 |  |  |  |  |  |  | } | 
| 1838 |  |  |  |  |  |  |  | 
| 1839 | 2 | 50 |  |  |  | 6 | if(defined $TYPE{$name}){ | 
| 1840 | 0 |  | 0 |  |  | 0 | my $that = $TYPE{$name}->{package_defined_in} || __PACKAGE__; | 
| 1841 | 0 | 0 |  |  |  | 0 | if($this ne $that) { | 
| 1842 | 0 |  |  |  |  | 0 | my $note = ''; | 
| 1843 | 0 | 0 |  |  |  | 0 | if($that eq __PACKAGE__) { | 
| 1844 | 0 |  |  |  |  | 0 | $note = sprintf " ('%s' is %s type constraint)", | 
| 1845 |  |  |  |  |  |  | $name, | 
| 1846 | 0 | 0 |  |  |  | 0 | scalar(grep { $name eq $_ } list_all_builtin_type_constraints()) | 
| 1847 |  |  |  |  |  |  | ? 'a builtin' | 
| 1848 |  |  |  |  |  |  | : 'an implicitly created'; | 
| 1849 |  |  |  |  |  |  | } | 
| 1850 | 0 |  |  |  |  | 0 | Carp::croak("The type constraint '$name' has already been created in $that" | 
| 1851 |  |  |  |  |  |  | . " and cannot be created again in $this" . $note); | 
| 1852 |  |  |  |  |  |  | } | 
| 1853 |  |  |  |  |  |  | } | 
| 1854 |  |  |  |  |  |  | } | 
| 1855 |  |  |  |  |  |  |  | 
| 1856 | 2 | 50 |  |  |  | 6 | $args{constraint} = delete $args{where}        if exists $args{where}; | 
| 1857 | 2 | 50 |  |  |  | 9 | $args{optimized}  = delete $args{optimized_as} if exists $args{optimized_as}; | 
| 1858 |  |  |  |  |  |  |  | 
| 1859 | 2 |  |  |  |  | 10 | my $constraint = Mousse::Meta::TypeConstraint->new(%args); | 
| 1860 |  |  |  |  |  |  |  | 
| 1861 | 2 | 50 |  |  |  | 8 | if(defined $name){ | 
| 1862 | 2 |  |  |  |  | 9 | return $TYPE{$name} = $constraint; | 
| 1863 |  |  |  |  |  |  | } | 
| 1864 |  |  |  |  |  |  | else{ | 
| 1865 | 0 |  |  |  |  | 0 | return $constraint; | 
| 1866 |  |  |  |  |  |  | } | 
| 1867 |  |  |  |  |  |  | } | 
| 1868 |  |  |  |  |  |  |  | 
| 1869 |  |  |  |  |  |  | sub type { | 
| 1870 | 0 |  |  | 0 | 0 | 0 | return _define_type 0, @_; | 
| 1871 |  |  |  |  |  |  | } | 
| 1872 |  |  |  |  |  |  |  | 
| 1873 |  |  |  |  |  |  | sub subtype { | 
| 1874 | 2 |  |  | 2 | 0 | 6 | return _define_type 1, @_; | 
| 1875 |  |  |  |  |  |  | } | 
| 1876 |  |  |  |  |  |  |  | 
| 1877 |  |  |  |  |  |  | sub coerce { # coerce $type, from $from, via { ... }, ... | 
| 1878 | 0 |  |  | 0 | 0 | 0 | my $type_name = shift; | 
| 1879 | 0 | 0 |  |  |  | 0 | my $type = find_type_constraint($type_name) | 
| 1880 |  |  |  |  |  |  | or Carp::croak("Cannot find type '$type_name', perhaps you forgot to load it"); | 
| 1881 |  |  |  |  |  |  |  | 
| 1882 | 0 |  |  |  |  | 0 | $type->_add_type_coercions(@_); | 
| 1883 | 0 |  |  |  |  | 0 | return; | 
| 1884 |  |  |  |  |  |  | } | 
| 1885 |  |  |  |  |  |  |  | 
| 1886 |  |  |  |  |  |  | sub class_type { | 
| 1887 | 2 |  |  | 2 | 0 | 4 | my($name, $options) = @_; | 
| 1888 | 2 |  | 33 |  |  | 94 | my $class = $options->{class} || $name; | 
| 1889 |  |  |  |  |  |  |  | 
| 1890 |  |  |  |  |  |  | # ClassType | 
| 1891 | 2 |  |  |  |  | 7 | return subtype $name => ( | 
| 1892 |  |  |  |  |  |  | as           => 'Object', | 
| 1893 |  |  |  |  |  |  | optimized_as => Mousse::Util::generate_isa_predicate_for($class), | 
| 1894 |  |  |  |  |  |  | class        => $class, | 
| 1895 |  |  |  |  |  |  | ); | 
| 1896 |  |  |  |  |  |  | } | 
| 1897 |  |  |  |  |  |  |  | 
| 1898 |  |  |  |  |  |  | sub role_type { | 
| 1899 | 0 |  |  | 0 | 0 | 0 | my($name, $options) = @_; | 
| 1900 | 0 |  | 0 |  |  | 0 | my $role = $options->{role} || $name; | 
| 1901 |  |  |  |  |  |  |  | 
| 1902 |  |  |  |  |  |  | # RoleType | 
| 1903 |  |  |  |  |  |  | return subtype $name => ( | 
| 1904 |  |  |  |  |  |  | as           => 'Object', | 
| 1905 |  |  |  |  |  |  | optimized_as => sub { | 
| 1906 | 0 |  | 0 | 0 |  | 0 | return Scalar::Util::blessed($_[0]) | 
| 1907 |  |  |  |  |  |  | && Mousse::Util::does_role($_[0], $role); | 
| 1908 |  |  |  |  |  |  | }, | 
| 1909 | 0 |  |  |  |  | 0 | role         => $role, | 
| 1910 |  |  |  |  |  |  | ); | 
| 1911 |  |  |  |  |  |  | } | 
| 1912 |  |  |  |  |  |  |  | 
| 1913 |  |  |  |  |  |  | sub duck_type { | 
| 1914 | 0 |  |  | 0 | 0 | 0 | my($name, @methods); | 
| 1915 |  |  |  |  |  |  |  | 
| 1916 | 0 | 0 |  |  |  | 0 | if(ref($_[0]) ne 'ARRAY'){ | 
| 1917 | 0 |  |  |  |  | 0 | $name = shift; | 
| 1918 |  |  |  |  |  |  | } | 
| 1919 |  |  |  |  |  |  |  | 
| 1920 | 0 | 0 | 0 |  |  | 0 | @methods = (@_ == 1 && ref($_[0]) eq 'ARRAY') ? @{$_[0]} : @_; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1921 |  |  |  |  |  |  |  | 
| 1922 |  |  |  |  |  |  | # DuckType | 
| 1923 |  |  |  |  |  |  | return _define_type 1, $name => ( | 
| 1924 |  |  |  |  |  |  | as           => 'Object', | 
| 1925 |  |  |  |  |  |  | optimized_as => Mousse::Util::generate_can_predicate_for(\@methods), | 
| 1926 |  |  |  |  |  |  | message      => sub { | 
| 1927 | 0 |  |  | 0 |  | 0 | my($object) = @_; | 
| 1928 | 0 |  |  |  |  | 0 | my @missing = grep { !$object->can($_) } @methods; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1929 | 0 |  |  |  |  | 0 | return ref($object) | 
| 1930 |  |  |  |  |  |  | . ' is missing methods ' | 
| 1931 |  |  |  |  |  |  | . Mousse::Util::quoted_english_list(@missing); | 
| 1932 |  |  |  |  |  |  | }, | 
| 1933 | 0 |  |  |  |  | 0 | methods      => \@methods, | 
| 1934 |  |  |  |  |  |  | ); | 
| 1935 |  |  |  |  |  |  | } | 
| 1936 |  |  |  |  |  |  |  | 
| 1937 |  |  |  |  |  |  | sub enum { | 
| 1938 | 0 |  |  | 0 | 0 | 0 | my($name, %valid); | 
| 1939 |  |  |  |  |  |  |  | 
| 1940 | 0 | 0 | 0 |  |  | 0 | if(!(@_ == 1 && ref($_[0]) eq 'ARRAY')){ | 
| 1941 | 0 |  |  |  |  | 0 | $name = shift; | 
| 1942 |  |  |  |  |  |  | } | 
| 1943 |  |  |  |  |  |  |  | 
| 1944 | 0 |  |  |  |  | 0 | %valid = map{ $_ => undef } | 
|  | 0 |  |  |  |  | 0 |  | 
| 1945 | 0 | 0 | 0 |  |  | 0 | (@_ == 1 && ref($_[0]) eq 'ARRAY' ? @{$_[0]} : @_); | 
| 1946 |  |  |  |  |  |  |  | 
| 1947 |  |  |  |  |  |  | # EnumType | 
| 1948 |  |  |  |  |  |  | return _define_type 1, $name => ( | 
| 1949 |  |  |  |  |  |  | as            => 'Str', | 
| 1950 |  |  |  |  |  |  | optimized_as  => sub{ | 
| 1951 | 0 |  | 0 | 0 |  | 0 | return defined($_[0]) && !ref($_[0]) && exists $valid{$_[0]}; | 
| 1952 |  |  |  |  |  |  | }, | 
| 1953 | 0 |  |  |  |  | 0 | ); | 
| 1954 |  |  |  |  |  |  | } | 
| 1955 |  |  |  |  |  |  |  | 
| 1956 |  |  |  |  |  |  | sub _find_or_create_regular_type{ | 
| 1957 | 0 |  |  | 0 |  | 0 | my($spec, $create)  = @_; | 
| 1958 |  |  |  |  |  |  |  | 
| 1959 | 0 | 0 |  |  |  | 0 | return $TYPE{$spec} if exists $TYPE{$spec}; | 
| 1960 |  |  |  |  |  |  |  | 
| 1961 | 0 |  |  |  |  | 0 | my $meta = Mousse::Util::get_metaclass_by_name($spec); | 
| 1962 |  |  |  |  |  |  |  | 
| 1963 | 0 | 0 |  |  |  | 0 | if(!defined $meta){ | 
| 1964 | 0 | 0 |  |  |  | 0 | return $create ? class_type($spec) : undef; | 
| 1965 |  |  |  |  |  |  | } | 
| 1966 |  |  |  |  |  |  |  | 
| 1967 | 0 | 0 |  |  |  | 0 | if(Mousse::Util::is_a_metarole($meta)){ | 
| 1968 | 0 |  |  |  |  | 0 | return role_type($spec); | 
| 1969 |  |  |  |  |  |  | } | 
| 1970 |  |  |  |  |  |  | else{ | 
| 1971 | 0 |  |  |  |  | 0 | return class_type($spec); | 
| 1972 |  |  |  |  |  |  | } | 
| 1973 |  |  |  |  |  |  | } | 
| 1974 |  |  |  |  |  |  |  | 
| 1975 |  |  |  |  |  |  | sub _find_or_create_parameterized_type{ | 
| 1976 | 0 |  |  | 0 |  | 0 | my($base, $param) = @_; | 
| 1977 |  |  |  |  |  |  |  | 
| 1978 | 0 |  |  |  |  | 0 | my $name = sprintf '%s[%s]', $base->name, $param->name; | 
| 1979 |  |  |  |  |  |  |  | 
| 1980 | 0 |  | 0 |  |  | 0 | $TYPE{$name} ||= $base->parameterize($param, $name); | 
| 1981 |  |  |  |  |  |  | } | 
| 1982 |  |  |  |  |  |  |  | 
| 1983 |  |  |  |  |  |  | sub _find_or_create_union_type{ | 
| 1984 | 0 | 0 |  | 0 |  | 0 | return if grep{ not defined } @_; # all things must be defined | 
|  | 0 |  |  |  |  | 0 |  | 
| 1985 | 0 |  |  |  |  | 0 | my @types = sort | 
| 1986 | 0 | 0 |  |  |  | 0 | map{ $_->{type_constraints} ? @{$_->{type_constraints}} : $_ } @_; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1987 |  |  |  |  |  |  |  | 
| 1988 | 0 |  |  |  |  | 0 | my $name = join '|', @types; | 
| 1989 |  |  |  |  |  |  |  | 
| 1990 |  |  |  |  |  |  | # UnionType | 
| 1991 | 0 |  | 0 |  |  | 0 | $TYPE{$name} ||= Mousse::Meta::TypeConstraint->new( | 
| 1992 |  |  |  |  |  |  | name              => $name, | 
| 1993 |  |  |  |  |  |  | type_constraints  => \@types, | 
| 1994 |  |  |  |  |  |  | ); | 
| 1995 |  |  |  |  |  |  | } | 
| 1996 |  |  |  |  |  |  |  | 
| 1997 |  |  |  |  |  |  | # The type parser | 
| 1998 |  |  |  |  |  |  |  | 
| 1999 |  |  |  |  |  |  | # param : '[' type ']' | NOTHING | 
| 2000 |  |  |  |  |  |  | sub _parse_param { | 
| 2001 | 0 |  |  | 0 |  | 0 | my($c) = @_; | 
| 2002 |  |  |  |  |  |  |  | 
| 2003 | 0 | 0 |  |  |  | 0 | if($c->{spec} =~ s/^\[//){ | 
| 2004 | 0 |  |  |  |  | 0 | my $type = _parse_type($c, 1); | 
| 2005 |  |  |  |  |  |  |  | 
| 2006 | 0 | 0 |  |  |  | 0 | if($c->{spec} =~ s/^\]//){ | 
| 2007 | 0 |  |  |  |  | 0 | return $type; | 
| 2008 |  |  |  |  |  |  | } | 
| 2009 | 0 |  |  |  |  | 0 | Carp::croak("Syntax error in type: missing right square bracket in '$c->{orig}'"); | 
| 2010 |  |  |  |  |  |  | } | 
| 2011 |  |  |  |  |  |  |  | 
| 2012 | 0 |  |  |  |  | 0 | return undef; | 
| 2013 |  |  |  |  |  |  | } | 
| 2014 |  |  |  |  |  |  |  | 
| 2015 |  |  |  |  |  |  | # name : [\w.:]+ | 
| 2016 |  |  |  |  |  |  | sub _parse_name { | 
| 2017 | 0 |  |  | 0 |  | 0 | my($c, $create) = @_; | 
| 2018 |  |  |  |  |  |  |  | 
| 2019 | 0 | 0 |  |  |  | 0 | if($c->{spec} =~ s/\A ([\w.:]+) //xms){ | 
| 2020 | 0 |  |  |  |  | 0 | return _find_or_create_regular_type($1, $create); | 
| 2021 |  |  |  |  |  |  | } | 
| 2022 | 0 |  |  |  |  | 0 | Carp::croak("Syntax error in type: expect type name near '$c->{spec}' in '$c->{orig}'"); | 
| 2023 |  |  |  |  |  |  | } | 
| 2024 |  |  |  |  |  |  |  | 
| 2025 |  |  |  |  |  |  | # single_type : name param | 
| 2026 |  |  |  |  |  |  | sub _parse_single_type { | 
| 2027 | 0 |  |  | 0 |  | 0 | my($c, $create) = @_; | 
| 2028 |  |  |  |  |  |  |  | 
| 2029 | 0 |  |  |  |  | 0 | my $type  = _parse_name($c, $create); | 
| 2030 | 0 |  |  |  |  | 0 | my $param = _parse_param($c); | 
| 2031 |  |  |  |  |  |  |  | 
| 2032 | 0 | 0 |  |  |  | 0 | if(defined $type){ | 
|  |  | 0 |  |  |  |  |  | 
| 2033 | 0 | 0 |  |  |  | 0 | if(defined $param){ | 
| 2034 | 0 |  |  |  |  | 0 | return _find_or_create_parameterized_type($type, $param); | 
| 2035 |  |  |  |  |  |  | } | 
| 2036 |  |  |  |  |  |  | else { | 
| 2037 | 0 |  |  |  |  | 0 | return $type; | 
| 2038 |  |  |  |  |  |  | } | 
| 2039 |  |  |  |  |  |  | } | 
| 2040 |  |  |  |  |  |  | elsif(defined $param){ | 
| 2041 | 0 |  |  |  |  | 0 | Carp::croak("Undefined type with parameter [$param] in '$c->{orig}'"); | 
| 2042 |  |  |  |  |  |  | } | 
| 2043 |  |  |  |  |  |  | else{ | 
| 2044 | 0 |  |  |  |  | 0 | return undef; | 
| 2045 |  |  |  |  |  |  | } | 
| 2046 |  |  |  |  |  |  | } | 
| 2047 |  |  |  |  |  |  |  | 
| 2048 |  |  |  |  |  |  | # type : single_type  ('|' single_type)* | 
| 2049 |  |  |  |  |  |  | sub _parse_type { | 
| 2050 | 0 |  |  | 0 |  | 0 | my($c, $create) = @_; | 
| 2051 |  |  |  |  |  |  |  | 
| 2052 | 0 |  |  |  |  | 0 | my $type = _parse_single_type($c, $create); | 
| 2053 | 0 | 0 |  |  |  | 0 | if($c->{spec}){ # can be an union type | 
| 2054 | 0 |  |  |  |  | 0 | my @types; | 
| 2055 | 0 |  |  |  |  | 0 | while($c->{spec} =~ s/^\|//){ | 
| 2056 | 0 |  |  |  |  | 0 | push @types, _parse_single_type($c, $create); | 
| 2057 |  |  |  |  |  |  | } | 
| 2058 | 0 | 0 |  |  |  | 0 | if(@types){ | 
| 2059 | 0 |  |  |  |  | 0 | return _find_or_create_union_type($type, @types); | 
| 2060 |  |  |  |  |  |  | } | 
| 2061 |  |  |  |  |  |  | } | 
| 2062 | 0 |  |  |  |  | 0 | return $type; | 
| 2063 |  |  |  |  |  |  | } | 
| 2064 |  |  |  |  |  |  |  | 
| 2065 |  |  |  |  |  |  |  | 
| 2066 |  |  |  |  |  |  | sub find_type_constraint { | 
| 2067 | 2 |  |  | 2 | 0 | 4 | my($spec) = @_; | 
| 2068 | 2 | 50 | 33 |  |  | 4 | return $spec if Mousse::Util::is_a_type_constraint($spec) or not defined $spec; | 
| 2069 |  |  |  |  |  |  |  | 
| 2070 | 2 |  |  |  |  | 4 | $spec =~ s/\s+//g; | 
| 2071 | 2 |  |  |  |  | 12 | return $TYPE{$spec}; | 
| 2072 |  |  |  |  |  |  | } | 
| 2073 |  |  |  |  |  |  |  | 
| 2074 |  |  |  |  |  |  | sub register_type_constraint { | 
| 2075 | 0 |  |  | 0 | 0 | 0 | my($constraint) = @_; | 
| 2076 | 0 | 0 |  |  |  | 0 | Carp::croak("No type supplied / type is not a valid type constraint") | 
| 2077 |  |  |  |  |  |  | unless Mousse::Util::is_a_type_constraint($constraint); | 
| 2078 | 0 |  |  |  |  | 0 | return $TYPE{$constraint->name} = $constraint; | 
| 2079 |  |  |  |  |  |  | } | 
| 2080 |  |  |  |  |  |  |  | 
| 2081 |  |  |  |  |  |  | sub find_or_parse_type_constraint { | 
| 2082 | 2 |  |  | 2 | 0 | 3 | my($spec) = @_; | 
| 2083 | 2 | 50 | 33 |  |  | 4 | return $spec if Mousse::Util::is_a_type_constraint($spec) or not defined $spec; | 
| 2084 |  |  |  |  |  |  |  | 
| 2085 | 2 |  |  |  |  | 5 | $spec =~ tr/ \t\r\n//d; | 
| 2086 |  |  |  |  |  |  |  | 
| 2087 | 2 |  |  |  |  | 4 | my $tc = $TYPE{$spec}; | 
| 2088 | 2 | 50 |  |  |  | 5 | if(defined $tc) { | 
| 2089 | 2 |  |  |  |  | 4 | return $tc; | 
| 2090 |  |  |  |  |  |  | } | 
| 2091 |  |  |  |  |  |  |  | 
| 2092 | 0 |  |  |  |  | 0 | my %context = ( | 
| 2093 |  |  |  |  |  |  | spec => $spec, | 
| 2094 |  |  |  |  |  |  | orig => $spec, | 
| 2095 |  |  |  |  |  |  | ); | 
| 2096 | 0 |  |  |  |  | 0 | $tc = _parse_type(\%context); | 
| 2097 |  |  |  |  |  |  |  | 
| 2098 | 0 | 0 |  |  |  | 0 | if($context{spec}){ | 
| 2099 | 0 |  |  |  |  | 0 | Carp::croak("Syntax error: extra elements '$context{spec}' in '$context{orig}'"); | 
| 2100 |  |  |  |  |  |  | } | 
| 2101 |  |  |  |  |  |  |  | 
| 2102 | 0 |  |  |  |  | 0 | return $TYPE{$spec} = $tc; | 
| 2103 |  |  |  |  |  |  | } | 
| 2104 |  |  |  |  |  |  |  | 
| 2105 |  |  |  |  |  |  | sub find_or_create_does_type_constraint{ | 
| 2106 |  |  |  |  |  |  | # XXX: Moose does not register a new role_type, but Mousse does. | 
| 2107 | 0 |  |  | 0 | 0 | 0 | my $tc = find_or_parse_type_constraint(@_); | 
| 2108 | 0 | 0 |  |  |  | 0 | return defined($tc) ? $tc : role_type(@_); | 
| 2109 |  |  |  |  |  |  | } | 
| 2110 |  |  |  |  |  |  |  | 
| 2111 |  |  |  |  |  |  | sub find_or_create_isa_type_constraint { | 
| 2112 |  |  |  |  |  |  | # XXX: Moose does not register a new class_type, but Mousse does. | 
| 2113 | 2 |  |  | 2 | 0 | 7 | my $tc = find_or_parse_type_constraint(@_); | 
| 2114 | 2 | 50 |  |  |  | 9 | return defined($tc) ? $tc : class_type(@_); | 
| 2115 |  |  |  |  |  |  | } | 
| 2116 |  |  |  |  |  |  |  | 
| 2117 |  |  |  |  |  |  | # Contents of Mouse | 
| 2118 |  |  |  |  |  |  | package Mousse::TOP; | 
| 2119 | 1 |  |  | 1 |  | 29 | use 5.006_002; | 
|  | 1 |  |  |  |  | 4 |  | 
|  | 1 |  |  |  |  | 67 |  | 
| 2120 |  |  |  |  |  |  |  | 
| 2121 | 1 |  |  | 1 |  | 40 | use Mousse::Exporter; # enables strict and warnings | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 4 |  | 
| 2122 |  |  |  |  |  |  |  | 
| 2123 |  |  |  |  |  |  | our $VERSION = '0.93'; | 
| 2124 |  |  |  |  |  |  |  | 
| 2125 | 1 |  |  | 1 |  | 5 | use Carp         (); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 15 |  | 
| 2126 | 1 |  |  | 1 |  | 50 | use Scalar::Util (); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 18 |  | 
| 2127 |  |  |  |  |  |  |  | 
| 2128 | 1 |  |  | 1 |  | 5 | use Mousse::Util (); | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 16 |  | 
| 2129 |  |  |  |  |  |  |  | 
| 2130 | 1 |  |  | 1 |  | 5 | use Mousse::Meta::Module; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 36 |  | 
| 2131 | 1 |  |  | 1 |  | 5 | use Mousse::Meta::Class; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 31 |  | 
| 2132 | 1 |  |  | 1 |  | 4 | use Mousse::Meta::Role; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 28 |  | 
| 2133 | 1 |  |  | 1 |  | 5 | use Mousse::Meta::Attribute; | 
|  | 1 |  |  |  |  | 14 |  | 
|  | 1 |  |  |  |  | 30 |  | 
| 2134 | 1 |  |  | 1 |  | 5 | use Mousse::Object; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 28 |  | 
| 2135 | 1 |  |  | 1 |  | 5 | use Mousse::Util::TypeConstraints (); | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 851 |  | 
| 2136 |  |  |  |  |  |  |  | 
| 2137 |  |  |  |  |  |  | Mousse::Exporter->setup_import_methods( | 
| 2138 |  |  |  |  |  |  | as_is => [qw( | 
| 2139 |  |  |  |  |  |  | extends with | 
| 2140 |  |  |  |  |  |  | has | 
| 2141 |  |  |  |  |  |  | before after around | 
| 2142 |  |  |  |  |  |  | override super | 
| 2143 |  |  |  |  |  |  | augment  inner | 
| 2144 |  |  |  |  |  |  | ), | 
| 2145 |  |  |  |  |  |  | \&Scalar::Util::blessed, | 
| 2146 |  |  |  |  |  |  | \&Carp::confess, | 
| 2147 |  |  |  |  |  |  | ], | 
| 2148 |  |  |  |  |  |  | ); | 
| 2149 |  |  |  |  |  |  |  | 
| 2150 |  |  |  |  |  |  |  | 
| 2151 |  |  |  |  |  |  | sub extends { | 
| 2152 | 1 |  |  | 1 |  | 11 | Mousse::Meta::Class->initialize(scalar caller)->superclasses(@_); | 
| 2153 | 1 |  |  |  |  | 4 | return; | 
| 2154 |  |  |  |  |  |  | } | 
| 2155 |  |  |  |  |  |  |  | 
| 2156 |  |  |  |  |  |  | sub with { | 
| 2157 | 0 |  |  | 0 |  | 0 | Mousse::Util::apply_all_roles(scalar(caller), @_); | 
| 2158 | 0 |  |  |  |  | 0 | return; | 
| 2159 |  |  |  |  |  |  | } | 
| 2160 |  |  |  |  |  |  |  | 
| 2161 |  |  |  |  |  |  | sub has { | 
| 2162 | 2 |  |  | 2 |  | 29 | my $meta = Mousse::Meta::Class->initialize(scalar caller); | 
| 2163 | 2 |  |  |  |  | 6 | my $name = shift; | 
| 2164 |  |  |  |  |  |  |  | 
| 2165 | 2 | 50 |  |  |  | 9 | $meta->throw_error(q{Usage: has 'name' => ( key => value, ... )}) | 
| 2166 |  |  |  |  |  |  | if @_ % 2; # odd number of arguments | 
| 2167 |  |  |  |  |  |  |  | 
| 2168 | 2 | 50 |  |  |  | 7 | for my $n(ref($name) ? @{$name} : $name){ | 
|  | 0 |  |  |  |  | 0 |  | 
| 2169 | 2 |  |  |  |  | 10 | $meta->add_attribute($n => @_); | 
| 2170 |  |  |  |  |  |  | } | 
| 2171 | 2 |  |  |  |  | 7 | return; | 
| 2172 |  |  |  |  |  |  | } | 
| 2173 |  |  |  |  |  |  |  | 
| 2174 |  |  |  |  |  |  | sub before { | 
| 2175 | 0 |  |  | 0 |  | 0 | my $meta = Mousse::Meta::Class->initialize(scalar caller); | 
| 2176 | 0 |  |  |  |  | 0 | my $code = pop; | 
| 2177 | 0 |  |  |  |  | 0 | for my $name($meta->_collect_methods(@_)) { | 
| 2178 | 0 |  |  |  |  | 0 | $meta->add_before_method_modifier($name => $code); | 
| 2179 |  |  |  |  |  |  | } | 
| 2180 | 0 |  |  |  |  | 0 | return; | 
| 2181 |  |  |  |  |  |  | } | 
| 2182 |  |  |  |  |  |  |  | 
| 2183 |  |  |  |  |  |  | sub after { | 
| 2184 | 0 |  |  | 0 |  | 0 | my $meta = Mousse::Meta::Class->initialize(scalar caller); | 
| 2185 | 0 |  |  |  |  | 0 | my $code = pop; | 
| 2186 | 0 |  |  |  |  | 0 | for my $name($meta->_collect_methods(@_)) { | 
| 2187 | 0 |  |  |  |  | 0 | $meta->add_after_method_modifier($name => $code); | 
| 2188 |  |  |  |  |  |  | } | 
| 2189 | 0 |  |  |  |  | 0 | return; | 
| 2190 |  |  |  |  |  |  | } | 
| 2191 |  |  |  |  |  |  |  | 
| 2192 |  |  |  |  |  |  | sub around { | 
| 2193 | 0 |  |  | 0 |  | 0 | my $meta = Mousse::Meta::Class->initialize(scalar caller); | 
| 2194 | 0 |  |  |  |  | 0 | my $code = pop; | 
| 2195 | 0 |  |  |  |  | 0 | for my $name($meta->_collect_methods(@_)) { | 
| 2196 | 0 |  |  |  |  | 0 | $meta->add_around_method_modifier($name => $code); | 
| 2197 |  |  |  |  |  |  | } | 
| 2198 | 0 |  |  |  |  | 0 | return; | 
| 2199 |  |  |  |  |  |  | } | 
| 2200 |  |  |  |  |  |  |  | 
| 2201 |  |  |  |  |  |  | our $SUPER_PACKAGE; | 
| 2202 |  |  |  |  |  |  | our $SUPER_BODY; | 
| 2203 |  |  |  |  |  |  | our @SUPER_ARGS; | 
| 2204 |  |  |  |  |  |  |  | 
| 2205 |  |  |  |  |  |  | sub super { | 
| 2206 |  |  |  |  |  |  | # This check avoids a recursion loop - see | 
| 2207 |  |  |  |  |  |  | # t/100_bugs/020_super_recursion.t | 
| 2208 | 0 | 0 | 0 | 0 |  | 0 | return if  defined $SUPER_PACKAGE && $SUPER_PACKAGE ne caller(); | 
| 2209 | 0 | 0 |  |  |  | 0 | return if !defined $SUPER_BODY; | 
| 2210 | 0 |  |  |  |  | 0 | $SUPER_BODY->(@SUPER_ARGS); | 
| 2211 |  |  |  |  |  |  | } | 
| 2212 |  |  |  |  |  |  |  | 
| 2213 |  |  |  |  |  |  | sub override { | 
| 2214 |  |  |  |  |  |  | # my($name, $method) = @_; | 
| 2215 | 0 |  |  | 0 |  | 0 | Mousse::Meta::Class->initialize(scalar caller)->add_override_method_modifier(@_); | 
| 2216 |  |  |  |  |  |  | } | 
| 2217 |  |  |  |  |  |  |  | 
| 2218 |  |  |  |  |  |  | our %INNER_BODY; | 
| 2219 |  |  |  |  |  |  | our %INNER_ARGS; | 
| 2220 |  |  |  |  |  |  |  | 
| 2221 |  |  |  |  |  |  | sub inner { | 
| 2222 | 0 |  |  | 0 |  | 0 | my $pkg = caller(); | 
| 2223 | 0 | 0 |  |  |  | 0 | if ( my $body = $INNER_BODY{$pkg} ) { | 
| 2224 | 0 |  |  |  |  | 0 | my $args = $INNER_ARGS{$pkg}; | 
| 2225 | 0 |  |  |  |  | 0 | local $INNER_ARGS{$pkg}; | 
| 2226 | 0 |  |  |  |  | 0 | local $INNER_BODY{$pkg}; | 
| 2227 | 0 |  |  |  |  | 0 | return $body->(@{$args}); | 
|  | 0 |  |  |  |  | 0 |  | 
| 2228 |  |  |  |  |  |  | } | 
| 2229 |  |  |  |  |  |  | else { | 
| 2230 | 0 |  |  |  |  | 0 | return; | 
| 2231 |  |  |  |  |  |  | } | 
| 2232 |  |  |  |  |  |  | } | 
| 2233 |  |  |  |  |  |  |  | 
| 2234 |  |  |  |  |  |  | sub augment { | 
| 2235 |  |  |  |  |  |  | #my($name, $method) = @_; | 
| 2236 | 0 |  |  | 0 |  | 0 | Mousse::Meta::Class->initialize(scalar caller)->add_augment_method_modifier(@_); | 
| 2237 | 0 |  |  |  |  | 0 | return; | 
| 2238 |  |  |  |  |  |  | } | 
| 2239 |  |  |  |  |  |  |  | 
| 2240 |  |  |  |  |  |  | sub init_meta { | 
| 2241 | 2 |  |  | 2 |  | 2 | shift; | 
| 2242 | 2 |  |  |  |  | 5 | my %args = @_; | 
| 2243 |  |  |  |  |  |  |  | 
| 2244 | 2 | 50 |  |  |  | 7 | my $class = $args{for_class} | 
| 2245 |  |  |  |  |  |  | or confess("Cannot call init_meta without specifying a for_class"); | 
| 2246 |  |  |  |  |  |  |  | 
| 2247 | 2 |  | 50 |  |  | 9 | my $base_class = $args{base_class} || 'Mousse::Object'; | 
| 2248 | 2 |  | 50 |  |  | 9 | my $metaclass  = $args{metaclass}  || 'Mousse::Meta::Class'; | 
| 2249 |  |  |  |  |  |  |  | 
| 2250 | 2 |  |  |  |  | 11 | my $meta = $metaclass->initialize($class); | 
| 2251 |  |  |  |  |  |  |  | 
| 2252 |  |  |  |  |  |  | $meta->add_method(meta => sub{ | 
| 2253 | 2 |  | 33 | 2 |  | 15 | return $metaclass->initialize(ref($_[0]) || $_[0]); | 
| 2254 | 2 |  |  |  |  | 15 | }); | 
| 2255 |  |  |  |  |  |  |  | 
| 2256 | 2 | 50 |  |  |  | 6 | $meta->superclasses($base_class) | 
| 2257 |  |  |  |  |  |  | unless $meta->superclasses; | 
| 2258 |  |  |  |  |  |  |  | 
| 2259 |  |  |  |  |  |  | # make a class type for each Mousse class | 
| 2260 | 2 | 50 |  |  |  | 6 | Mousse::Util::TypeConstraints::class_type($class) | 
| 2261 |  |  |  |  |  |  | unless Mousse::Util::TypeConstraints::find_type_constraint($class); | 
| 2262 |  |  |  |  |  |  |  | 
| 2263 | 2 |  |  |  |  | 8 | return $meta; | 
| 2264 |  |  |  |  |  |  | } | 
| 2265 |  |  |  |  |  |  |  | 
| 2266 |  |  |  |  |  |  | # Contents of Mouse::Meta::Attribute | 
| 2267 |  |  |  |  |  |  | package Mousse::Meta::Attribute; | 
| 2268 | 1 |  |  | 1 |  | 7 | use Mousse::Util qw(:meta); # enables strict and warnings | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 6 |  | 
| 2269 |  |  |  |  |  |  |  | 
| 2270 | 1 |  |  | 1 |  | 12 | use Carp (); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 18 |  | 
| 2271 |  |  |  |  |  |  |  | 
| 2272 | 1 |  |  | 1 |  | 4 | use Mousse::Meta::TypeConstraint; | 
|  | 1 |  |  |  |  | 8 |  | 
|  | 1 |  |  |  |  | 2267 |  | 
| 2273 |  |  |  |  |  |  |  | 
| 2274 |  |  |  |  |  |  | my %valid_options = map { $_ => undef } ( | 
| 2275 |  |  |  |  |  |  | 'accessor', | 
| 2276 |  |  |  |  |  |  | 'auto_deref', | 
| 2277 |  |  |  |  |  |  | 'builder', | 
| 2278 |  |  |  |  |  |  | 'clearer', | 
| 2279 |  |  |  |  |  |  | 'coerce', | 
| 2280 |  |  |  |  |  |  | 'default', | 
| 2281 |  |  |  |  |  |  | 'documentation', | 
| 2282 |  |  |  |  |  |  | 'does', | 
| 2283 |  |  |  |  |  |  | 'handles', | 
| 2284 |  |  |  |  |  |  | 'init_arg', | 
| 2285 |  |  |  |  |  |  | 'insertion_order', | 
| 2286 |  |  |  |  |  |  | 'is', | 
| 2287 |  |  |  |  |  |  | 'isa', | 
| 2288 |  |  |  |  |  |  | 'lazy', | 
| 2289 |  |  |  |  |  |  | 'lazy_build', | 
| 2290 |  |  |  |  |  |  | 'name', | 
| 2291 |  |  |  |  |  |  | 'predicate', | 
| 2292 |  |  |  |  |  |  | 'reader', | 
| 2293 |  |  |  |  |  |  | 'required', | 
| 2294 |  |  |  |  |  |  | 'traits', | 
| 2295 |  |  |  |  |  |  | 'trigger', | 
| 2296 |  |  |  |  |  |  | 'type_constraint', | 
| 2297 |  |  |  |  |  |  | 'weak_ref', | 
| 2298 |  |  |  |  |  |  | 'writer', | 
| 2299 |  |  |  |  |  |  |  | 
| 2300 |  |  |  |  |  |  | # internally used | 
| 2301 |  |  |  |  |  |  | 'associated_class', | 
| 2302 |  |  |  |  |  |  | 'associated_methods', | 
| 2303 |  |  |  |  |  |  | '__METACLASS__', | 
| 2304 |  |  |  |  |  |  |  | 
| 2305 |  |  |  |  |  |  | # Moose defines, but Mousse doesn't | 
| 2306 |  |  |  |  |  |  | #'definition_context', | 
| 2307 |  |  |  |  |  |  | #'initializer', | 
| 2308 |  |  |  |  |  |  |  | 
| 2309 |  |  |  |  |  |  | # special case for AttributeHelpers | 
| 2310 |  |  |  |  |  |  | 'provides', | 
| 2311 |  |  |  |  |  |  | 'curries', | 
| 2312 |  |  |  |  |  |  | ); | 
| 2313 |  |  |  |  |  |  |  | 
| 2314 |  |  |  |  |  |  | our @CARP_NOT = qw(Mousse::Meta::Class); | 
| 2315 |  |  |  |  |  |  |  | 
| 2316 |  |  |  |  |  |  | sub new { | 
| 2317 | 2 |  |  | 2 | 0 | 4 | my $class = shift; | 
| 2318 | 2 |  |  |  |  | 4 | my $name  = shift; | 
| 2319 |  |  |  |  |  |  |  | 
| 2320 | 2 |  |  |  |  | 11 | my $args  = $class->Mousse::Object::BUILDARGS(@_); | 
| 2321 |  |  |  |  |  |  |  | 
| 2322 | 2 |  |  |  |  | 7 | $class->_process_options($name, $args); | 
| 2323 |  |  |  |  |  |  |  | 
| 2324 | 2 |  |  |  |  | 3 | $args->{name} = $name; | 
| 2325 |  |  |  |  |  |  |  | 
| 2326 |  |  |  |  |  |  | # check options | 
| 2327 |  |  |  |  |  |  | # (1) known by core | 
| 2328 | 2 |  |  |  |  | 5 | my @bad = grep{ !exists $valid_options{$_} } keys %{$args}; | 
|  | 8 |  |  |  |  | 19 |  | 
|  | 2 |  |  |  |  | 7 |  | 
| 2329 |  |  |  |  |  |  |  | 
| 2330 |  |  |  |  |  |  | # (2) known by subclasses | 
| 2331 | 2 | 50 | 33 |  |  | 26 | if(@bad && $class ne __PACKAGE__){ | 
| 2332 | 0 |  |  |  |  | 0 | my %valid_attrs = ( | 
| 2333 | 0 |  |  |  |  | 0 | map { $_ => undef } | 
| 2334 | 0 |  |  |  |  | 0 | grep { defined } | 
| 2335 | 0 |  |  |  |  | 0 | map { $_->init_arg() } | 
| 2336 |  |  |  |  |  |  | $class->meta->get_all_attributes() | 
| 2337 |  |  |  |  |  |  | ); | 
| 2338 | 0 |  |  |  |  | 0 | @bad = grep{ !exists $valid_attrs{$_} } @bad; | 
|  | 0 |  |  |  |  | 0 |  | 
| 2339 |  |  |  |  |  |  | } | 
| 2340 |  |  |  |  |  |  |  | 
| 2341 |  |  |  |  |  |  | # (3) bad options found | 
| 2342 | 2 | 50 |  |  |  | 5 | if(@bad){ | 
| 2343 | 0 |  |  |  |  | 0 | Carp::carp( | 
| 2344 |  |  |  |  |  |  | "Found unknown argument(s) passed to '$name' attribute constructor in '$class': " | 
| 2345 |  |  |  |  |  |  | . Mousse::Util::english_list(@bad)); | 
| 2346 |  |  |  |  |  |  | } | 
| 2347 |  |  |  |  |  |  |  | 
| 2348 | 2 |  |  |  |  | 6 | my $self = bless $args, $class; | 
| 2349 | 2 | 50 |  |  |  | 7 | if($class ne __PACKAGE__){ | 
| 2350 | 0 |  |  |  |  | 0 | $class->meta->_initialize_object($self, $args); | 
| 2351 |  |  |  |  |  |  | } | 
| 2352 | 2 |  |  |  |  | 7 | return $self; | 
| 2353 |  |  |  |  |  |  | } | 
| 2354 |  |  |  |  |  |  |  | 
| 2355 | 0 | 0 |  | 0 | 0 | 0 | sub has_read_method   { $_[0]->has_reader || $_[0]->has_accessor } | 
| 2356 | 0 | 0 |  | 0 | 0 | 0 | sub has_write_method  { $_[0]->has_writer || $_[0]->has_accessor } | 
| 2357 |  |  |  |  |  |  |  | 
| 2358 | 0 | 0 |  | 0 | 0 | 0 | sub get_read_method   { $_[0]->reader || $_[0]->accessor } | 
| 2359 | 0 | 0 |  | 0 | 0 | 0 | sub get_write_method  { $_[0]->writer || $_[0]->accessor } | 
| 2360 |  |  |  |  |  |  |  | 
| 2361 |  |  |  |  |  |  | sub get_read_method_ref{ | 
| 2362 | 0 |  |  | 0 | 0 | 0 | my($self) = @_; | 
| 2363 | 0 |  | 0 |  |  | 0 | return $self->{_mouse_cache_read_method_ref} | 
| 2364 |  |  |  |  |  |  | ||= $self->_get_accessor_method_ref('get_read_method', '_generate_reader'); | 
| 2365 |  |  |  |  |  |  | } | 
| 2366 |  |  |  |  |  |  |  | 
| 2367 |  |  |  |  |  |  | sub get_write_method_ref{ | 
| 2368 | 0 |  |  | 0 | 0 | 0 | my($self) = @_; | 
| 2369 | 0 |  | 0 |  |  | 0 | return $self->{_mouse_cache_write_method_ref} | 
| 2370 |  |  |  |  |  |  | ||= $self->_get_accessor_method_ref('get_write_method', '_generate_writer'); | 
| 2371 |  |  |  |  |  |  | } | 
| 2372 |  |  |  |  |  |  |  | 
| 2373 |  |  |  |  |  |  | sub interpolate_class{ | 
| 2374 | 2 |  |  | 2 | 0 | 3 | my($class, $args) = @_; | 
| 2375 |  |  |  |  |  |  |  | 
| 2376 | 2 | 50 |  |  |  | 8 | if(my $metaclass = delete $args->{metaclass}){ | 
| 2377 | 0 |  |  |  |  | 0 | $class = Mousse::Util::resolve_metaclass_alias( Attribute => $metaclass ); | 
| 2378 |  |  |  |  |  |  | } | 
| 2379 |  |  |  |  |  |  |  | 
| 2380 | 2 |  |  |  |  | 4 | my @traits; | 
| 2381 | 2 | 50 |  |  |  | 10 | if(my $traits_ref = delete $args->{traits}){ | 
| 2382 |  |  |  |  |  |  |  | 
| 2383 | 0 |  |  |  |  | 0 | for (my $i = 0; $i < @{$traits_ref}; $i++) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 2384 | 0 |  |  |  |  | 0 | my $trait = Mousse::Util::resolve_metaclass_alias(Attribute => $traits_ref->[$i], trait => 1); | 
| 2385 |  |  |  |  |  |  |  | 
| 2386 | 0 | 0 |  |  |  | 0 | next if $class->does($trait); | 
| 2387 |  |  |  |  |  |  |  | 
| 2388 | 0 |  |  |  |  | 0 | push @traits, $trait; | 
| 2389 |  |  |  |  |  |  |  | 
| 2390 |  |  |  |  |  |  | # are there options? | 
| 2391 | 0 | 0 |  |  |  | 0 | push @traits, $traits_ref->[++$i] | 
| 2392 |  |  |  |  |  |  | if ref($traits_ref->[$i+1]); | 
| 2393 |  |  |  |  |  |  | } | 
| 2394 |  |  |  |  |  |  |  | 
| 2395 | 0 | 0 |  |  |  | 0 | if (@traits) { | 
| 2396 | 0 |  |  |  |  | 0 | $class = Mousse::Meta::Class->create_anon_class( | 
| 2397 |  |  |  |  |  |  | superclasses => [ $class ], | 
| 2398 |  |  |  |  |  |  | roles        => \@traits, | 
| 2399 |  |  |  |  |  |  | cache        => 1, | 
| 2400 |  |  |  |  |  |  | )->name; | 
| 2401 |  |  |  |  |  |  | } | 
| 2402 |  |  |  |  |  |  | } | 
| 2403 |  |  |  |  |  |  |  | 
| 2404 | 2 |  |  |  |  | 6 | return( $class, @traits ); | 
| 2405 |  |  |  |  |  |  | } | 
| 2406 |  |  |  |  |  |  |  | 
| 2407 |  |  |  |  |  |  | sub verify_against_type_constraint { | 
| 2408 | 0 |  |  | 0 | 0 | 0 | my ($self, $value) = @_; | 
| 2409 |  |  |  |  |  |  |  | 
| 2410 | 0 |  |  |  |  | 0 | my $type_constraint = $self->{type_constraint}; | 
| 2411 | 0 | 0 |  |  |  | 0 | return 1 if !$type_constraint; | 
| 2412 | 0 | 0 |  |  |  | 0 | return 1 if $type_constraint->check($value); | 
| 2413 |  |  |  |  |  |  |  | 
| 2414 | 0 |  |  |  |  | 0 | $self->_throw_type_constraint_error($value, $type_constraint); | 
| 2415 |  |  |  |  |  |  | } | 
| 2416 |  |  |  |  |  |  |  | 
| 2417 |  |  |  |  |  |  | sub _throw_type_constraint_error { | 
| 2418 | 0 |  |  | 0 |  | 0 | my($self, $value, $type) = @_; | 
| 2419 |  |  |  |  |  |  |  | 
| 2420 | 0 |  |  |  |  | 0 | $self->throw_error( | 
| 2421 |  |  |  |  |  |  | sprintf q{Attribute (%s) does not pass the type constraint because: %s}, | 
| 2422 |  |  |  |  |  |  | $self->name, | 
| 2423 |  |  |  |  |  |  | $type->get_message($value), | 
| 2424 |  |  |  |  |  |  | ); | 
| 2425 |  |  |  |  |  |  | } | 
| 2426 |  |  |  |  |  |  |  | 
| 2427 |  |  |  |  |  |  | sub illegal_options_for_inheritance { | 
| 2428 | 0 |  |  | 0 | 0 | 0 | return qw(reader writer accessor clearer predicate); | 
| 2429 |  |  |  |  |  |  | } | 
| 2430 |  |  |  |  |  |  |  | 
| 2431 |  |  |  |  |  |  | sub clone_and_inherit_options{ | 
| 2432 | 0 |  |  | 0 | 0 | 0 | my $self = shift; | 
| 2433 | 0 |  |  |  |  | 0 | my $args = $self->Mousse::Object::BUILDARGS(@_); | 
| 2434 |  |  |  |  |  |  |  | 
| 2435 | 0 |  |  |  |  | 0 | foreach my $illegal($self->illegal_options_for_inheritance) { | 
| 2436 | 0 | 0 | 0 |  |  | 0 | if(exists $args->{$illegal} and exists $self->{$illegal}) { | 
| 2437 | 0 |  |  |  |  | 0 | $self->throw_error("Illegal inherited option: $illegal"); | 
| 2438 |  |  |  |  |  |  | } | 
| 2439 |  |  |  |  |  |  | } | 
| 2440 |  |  |  |  |  |  |  | 
| 2441 | 0 |  |  |  |  | 0 | foreach my $name(keys %{$self}){ | 
|  | 0 |  |  |  |  | 0 |  | 
| 2442 | 0 | 0 |  |  |  | 0 | if(!exists $args->{$name}){ | 
| 2443 | 0 |  |  |  |  | 0 | $args->{$name} = $self->{$name}; # inherit from self | 
| 2444 |  |  |  |  |  |  | } | 
| 2445 |  |  |  |  |  |  | } | 
| 2446 |  |  |  |  |  |  |  | 
| 2447 | 0 |  |  |  |  | 0 | my($attribute_class, @traits) = ref($self)->interpolate_class($args); | 
| 2448 | 0 | 0 |  |  |  | 0 | $args->{traits} = \@traits if @traits; | 
| 2449 |  |  |  |  |  |  |  | 
| 2450 |  |  |  |  |  |  | # remove temporary caches | 
| 2451 | 0 |  |  |  |  | 0 | foreach my $attr(keys %{$args}){ | 
|  | 0 |  |  |  |  | 0 |  | 
| 2452 | 0 | 0 |  |  |  | 0 | if($attr =~ /\A _mouse_cache_/xms){ | 
| 2453 | 0 |  |  |  |  | 0 | delete $args->{$attr}; | 
| 2454 |  |  |  |  |  |  | } | 
| 2455 |  |  |  |  |  |  | } | 
| 2456 |  |  |  |  |  |  |  | 
| 2457 |  |  |  |  |  |  | # remove default if lazy_build => 1 | 
| 2458 | 0 | 0 |  |  |  | 0 | if($args->{lazy_build}) { | 
| 2459 | 0 |  |  |  |  | 0 | delete $args->{default}; | 
| 2460 |  |  |  |  |  |  | } | 
| 2461 |  |  |  |  |  |  |  | 
| 2462 | 0 |  |  |  |  | 0 | return $attribute_class->new($self->name, $args); | 
| 2463 |  |  |  |  |  |  | } | 
| 2464 |  |  |  |  |  |  |  | 
| 2465 |  |  |  |  |  |  |  | 
| 2466 |  |  |  |  |  |  | sub _get_accessor_method_ref { | 
| 2467 | 0 |  |  | 0 |  | 0 | my($self, $type, $generator) = @_; | 
| 2468 |  |  |  |  |  |  |  | 
| 2469 | 0 |  | 0 |  |  | 0 | my $metaclass = $self->associated_class | 
| 2470 |  |  |  |  |  |  | || $self->throw_error('No asocciated class for ' . $self->name); | 
| 2471 |  |  |  |  |  |  |  | 
| 2472 | 0 |  |  |  |  | 0 | my $accessor = $self->$type(); | 
| 2473 | 0 | 0 |  |  |  | 0 | if($accessor){ | 
| 2474 | 0 |  |  |  |  | 0 | return $metaclass->get_method_body($accessor); | 
| 2475 |  |  |  |  |  |  | } | 
| 2476 |  |  |  |  |  |  | else{ | 
| 2477 | 0 |  |  |  |  | 0 | return $self->accessor_metaclass->$generator($self, $metaclass); | 
| 2478 |  |  |  |  |  |  | } | 
| 2479 |  |  |  |  |  |  | } | 
| 2480 |  |  |  |  |  |  |  | 
| 2481 |  |  |  |  |  |  | sub set_value { | 
| 2482 | 0 |  |  | 0 | 0 | 0 | my($self, $object, $value) = @_; | 
| 2483 | 0 |  |  |  |  | 0 | return $self->get_write_method_ref()->($object, $value); | 
| 2484 |  |  |  |  |  |  | } | 
| 2485 |  |  |  |  |  |  |  | 
| 2486 |  |  |  |  |  |  | sub get_value { | 
| 2487 | 0 |  |  | 0 | 0 | 0 | my($self, $object) = @_; | 
| 2488 | 0 |  |  |  |  | 0 | return $self->get_read_method_ref()->($object); | 
| 2489 |  |  |  |  |  |  | } | 
| 2490 |  |  |  |  |  |  |  | 
| 2491 |  |  |  |  |  |  | sub has_value { | 
| 2492 | 0 |  |  | 0 | 0 | 0 | my($self, $object) = @_; | 
| 2493 | 0 |  | 0 |  |  | 0 | my $accessor_ref = $self->{_mouse_cache_predicate_ref} | 
| 2494 |  |  |  |  |  |  | ||= $self->_get_accessor_method_ref('predicate', '_generate_predicate'); | 
| 2495 |  |  |  |  |  |  |  | 
| 2496 | 0 |  |  |  |  | 0 | return $accessor_ref->($object); | 
| 2497 |  |  |  |  |  |  | } | 
| 2498 |  |  |  |  |  |  |  | 
| 2499 |  |  |  |  |  |  | sub clear_value { | 
| 2500 | 0 |  |  | 0 | 0 | 0 | my($self, $object) = @_; | 
| 2501 | 0 |  | 0 |  |  | 0 | my $accessor_ref = $self->{_mouse_cache_crealer_ref} | 
| 2502 |  |  |  |  |  |  | ||= $self->_get_accessor_method_ref('clearer', '_generate_clearer'); | 
| 2503 |  |  |  |  |  |  |  | 
| 2504 | 0 |  |  |  |  | 0 | return $accessor_ref->($object); | 
| 2505 |  |  |  |  |  |  | } | 
| 2506 |  |  |  |  |  |  |  | 
| 2507 |  |  |  |  |  |  | sub associate_method{ | 
| 2508 |  |  |  |  |  |  | #my($attribute, $method_name) = @_; | 
| 2509 | 2 |  |  | 2 | 0 | 3 | my($attribute) = @_; | 
| 2510 | 2 |  |  |  |  | 5 | $attribute->{associated_methods}++; | 
| 2511 | 2 |  |  |  |  | 4 | return; | 
| 2512 |  |  |  |  |  |  | } | 
| 2513 |  |  |  |  |  |  |  | 
| 2514 |  |  |  |  |  |  | sub install_accessors{ | 
| 2515 | 2 |  |  | 2 | 0 | 4 | my($attribute) = @_; | 
| 2516 |  |  |  |  |  |  |  | 
| 2517 | 2 |  |  |  |  | 7 | my $metaclass      = $attribute->associated_class; | 
| 2518 | 2 |  |  |  |  | 19 | my $accessor_class = $attribute->accessor_metaclass; | 
| 2519 |  |  |  |  |  |  |  | 
| 2520 | 2 |  |  |  |  | 4 | foreach my $type(qw(accessor reader writer predicate clearer)){ | 
| 2521 | 10 | 100 |  |  |  | 27 | if(exists $attribute->{$type}){ | 
| 2522 | 2 |  |  |  |  | 4 | my $generator = '_generate_' . $type; | 
| 2523 | 2 |  |  |  |  | 15 | my $code      = $accessor_class->$generator($attribute, $metaclass); | 
| 2524 | 2 |  |  |  |  | 6 | my $name      = $attribute->{$type}; | 
| 2525 |  |  |  |  |  |  | # TODO: do something for compatibility | 
| 2526 |  |  |  |  |  |  | #            if( $metaclass->name->can($name) ) { | 
| 2527 |  |  |  |  |  |  | #                my $t = $metaclass->has_method($name) ? 'method' : 'function'; | 
| 2528 |  |  |  |  |  |  | #                Carp::cluck("You are overwriting a locally defined $t" | 
| 2529 |  |  |  |  |  |  | #                    . " ($name) with an accessor"); | 
| 2530 |  |  |  |  |  |  | #            } | 
| 2531 | 2 |  |  |  |  | 9 | $metaclass->add_method($name => $code); | 
| 2532 | 2 |  |  |  |  | 7 | $attribute->associate_method($name); | 
| 2533 |  |  |  |  |  |  | } | 
| 2534 |  |  |  |  |  |  | } | 
| 2535 |  |  |  |  |  |  |  | 
| 2536 |  |  |  |  |  |  | # install delegation | 
| 2537 | 2 | 50 |  |  |  | 8 | if(exists $attribute->{handles}){ | 
| 2538 | 0 |  |  |  |  | 0 | my %handles = $attribute->_canonicalize_handles(); | 
| 2539 | 0 |  |  |  |  | 0 | while(my($handle, $method_to_call) = each %handles){ | 
| 2540 | 0 | 0 |  |  |  | 0 | next if Mousse::Object->can($handle); | 
| 2541 |  |  |  |  |  |  |  | 
| 2542 | 0 | 0 |  |  |  | 0 | if($metaclass->has_method($handle)) { | 
| 2543 | 0 |  |  |  |  | 0 | $attribute->throw_error("You cannot overwrite a locally defined method ($handle) with a delegation"); | 
| 2544 |  |  |  |  |  |  | } | 
| 2545 |  |  |  |  |  |  |  | 
| 2546 | 0 |  |  |  |  | 0 | $metaclass->add_method($handle => | 
| 2547 |  |  |  |  |  |  | $attribute->_make_delegation_method( | 
| 2548 |  |  |  |  |  |  | $handle, $method_to_call)); | 
| 2549 |  |  |  |  |  |  |  | 
| 2550 | 0 |  |  |  |  | 0 | $attribute->associate_method($handle); | 
| 2551 |  |  |  |  |  |  | } | 
| 2552 |  |  |  |  |  |  | } | 
| 2553 |  |  |  |  |  |  |  | 
| 2554 | 2 |  |  |  |  | 3 | return; | 
| 2555 |  |  |  |  |  |  | } | 
| 2556 |  |  |  |  |  |  |  | 
| 2557 |  |  |  |  |  |  | sub delegation_metaclass() { ## no critic | 
| 2558 |  |  |  |  |  |  | 'Mousse::Meta::Method::Delegation' | 
| 2559 |  |  |  |  |  |  | } | 
| 2560 |  |  |  |  |  |  |  | 
| 2561 |  |  |  |  |  |  | sub _canonicalize_handles { | 
| 2562 | 0 |  |  | 0 |  | 0 | my($self) = @_; | 
| 2563 | 0 |  |  |  |  | 0 | my $handles = $self->{handles}; | 
| 2564 |  |  |  |  |  |  |  | 
| 2565 | 0 |  |  |  |  | 0 | my $handle_type = ref $handles; | 
| 2566 | 0 | 0 |  |  |  | 0 | if ($handle_type eq 'HASH') { | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 2567 | 0 |  |  |  |  | 0 | return %$handles; | 
| 2568 |  |  |  |  |  |  | } | 
| 2569 |  |  |  |  |  |  | elsif ($handle_type eq 'ARRAY') { | 
| 2570 | 0 |  |  |  |  | 0 | return map { $_ => $_ } @$handles; | 
|  | 0 |  |  |  |  | 0 |  | 
| 2571 |  |  |  |  |  |  | } | 
| 2572 |  |  |  |  |  |  | elsif ($handle_type eq 'Regexp') { | 
| 2573 | 0 |  |  |  |  | 0 | my $meta = $self->_find_delegate_metaclass(); | 
| 2574 | 0 |  |  |  |  | 0 | return map  { $_ => $_ } | 
|  | 0 |  |  |  |  | 0 |  | 
| 2575 | 0 | 0 |  |  |  | 0 | grep { /$handles/ } | 
| 2576 |  |  |  |  |  |  | Mousse::Util::is_a_metarole($meta) | 
| 2577 |  |  |  |  |  |  | ? $meta->get_method_list | 
| 2578 |  |  |  |  |  |  | : $meta->get_all_method_names; | 
| 2579 |  |  |  |  |  |  | } | 
| 2580 |  |  |  |  |  |  | elsif ($handle_type eq 'CODE') { | 
| 2581 | 0 |  |  |  |  | 0 | return $handles->( $self, $self->_find_delegate_metaclass() ); | 
| 2582 |  |  |  |  |  |  | } | 
| 2583 |  |  |  |  |  |  | else { | 
| 2584 | 0 |  |  |  |  | 0 | $self->throw_error("Unable to canonicalize the 'handles' option with $handles"); | 
| 2585 |  |  |  |  |  |  | } | 
| 2586 |  |  |  |  |  |  | } | 
| 2587 |  |  |  |  |  |  |  | 
| 2588 |  |  |  |  |  |  | sub _find_delegate_metaclass { | 
| 2589 | 0 |  |  | 0 |  | 0 | my($self) = @_; | 
| 2590 | 0 |  |  |  |  | 0 | my $meta; | 
| 2591 | 0 | 0 |  |  |  | 0 | if($self->{isa}) { | 
|  |  | 0 |  |  |  |  |  | 
| 2592 | 0 |  |  |  |  | 0 | $meta = Mousse::Meta::Class->initialize("$self->{isa}"); | 
| 2593 |  |  |  |  |  |  | } | 
| 2594 |  |  |  |  |  |  | elsif($self->{does}) { | 
| 2595 | 0 |  |  |  |  | 0 | $meta = Mousse::Util::get_metaclass_by_name("$self->{does}"); | 
| 2596 |  |  |  |  |  |  | } | 
| 2597 | 0 | 0 |  |  |  | 0 | defined($meta) or $self->throw_error( | 
| 2598 |  |  |  |  |  |  | "Cannot find delegate metaclass for attribute " . $self->name); | 
| 2599 | 0 |  |  |  |  | 0 | return $meta; | 
| 2600 |  |  |  |  |  |  | } | 
| 2601 |  |  |  |  |  |  |  | 
| 2602 |  |  |  |  |  |  |  | 
| 2603 |  |  |  |  |  |  | sub _make_delegation_method { | 
| 2604 | 0 |  |  | 0 |  | 0 | my($self, $handle, $method_to_call) = @_; | 
| 2605 | 0 |  |  |  |  | 0 | return Mousse::Util::load_class($self->delegation_metaclass) | 
| 2606 |  |  |  |  |  |  | ->_generate_delegation($self, $handle, $method_to_call); | 
| 2607 |  |  |  |  |  |  | } | 
| 2608 |  |  |  |  |  |  |  | 
| 2609 |  |  |  |  |  |  | # Contents of Mouse::Meta::Class | 
| 2610 |  |  |  |  |  |  | package Mousse::Meta::Class; | 
| 2611 | 1 |  |  | 1 |  | 7 | use Mousse::Util qw/:meta/; # enables strict and warnings | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 6 |  | 
| 2612 | 1 |  |  | 1 |  | 5 | no warnings 'once'; | 
|  | 1 |  |  |  |  | 8 |  | 
|  | 1 |  |  |  |  | 36 |  | 
| 2613 |  |  |  |  |  |  |  | 
| 2614 | 1 |  |  | 1 |  | 5 | use Scalar::Util (); | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 20 |  | 
| 2615 |  |  |  |  |  |  |  | 
| 2616 | 1 |  |  | 1 |  | 5 | use Mousse::Meta::Module; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 150 |  | 
| 2617 |  |  |  |  |  |  | our @ISA = qw(Mousse::Meta::Module); | 
| 2618 |  |  |  |  |  |  |  | 
| 2619 |  |  |  |  |  |  | our @CARP_NOT = qw(Mousse); # trust Mousse | 
| 2620 |  |  |  |  |  |  |  | 
| 2621 |  |  |  |  |  |  | sub attribute_metaclass; | 
| 2622 |  |  |  |  |  |  | sub method_metaclass; | 
| 2623 |  |  |  |  |  |  |  | 
| 2624 |  |  |  |  |  |  | sub constructor_class; | 
| 2625 |  |  |  |  |  |  | sub destructor_class; | 
| 2626 |  |  |  |  |  |  |  | 
| 2627 |  |  |  |  |  |  |  | 
| 2628 |  |  |  |  |  |  | sub _construct_meta { | 
| 2629 | 2 |  |  | 2 |  | 5 | my($class, %args) = @_; | 
| 2630 |  |  |  |  |  |  |  | 
| 2631 | 2 |  |  |  |  | 5 | $args{attributes} = {}; | 
| 2632 | 2 |  |  |  |  | 4 | $args{methods}    = {}; | 
| 2633 | 2 |  |  |  |  | 3 | $args{roles}      = []; | 
| 2634 |  |  |  |  |  |  |  | 
| 2635 | 2 |  |  |  |  | 3 | $args{superclasses} = do { | 
| 2636 | 1 |  |  | 1 |  | 5 | no strict 'refs'; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 3022 |  | 
| 2637 | 2 |  |  |  |  | 3 | \@{ $args{package} . '::ISA' }; | 
|  | 2 |  |  |  |  | 12 |  | 
| 2638 |  |  |  |  |  |  | }; | 
| 2639 |  |  |  |  |  |  |  | 
| 2640 | 2 |  | 33 |  |  | 12 | my $self = bless \%args, ref($class) || $class; | 
| 2641 | 2 | 50 |  |  |  | 7 | if(ref($self) ne __PACKAGE__){ | 
| 2642 | 0 |  |  |  |  | 0 | $self->meta->_initialize_object($self, \%args); | 
| 2643 |  |  |  |  |  |  | } | 
| 2644 | 2 |  |  |  |  | 14 | return $self; | 
| 2645 |  |  |  |  |  |  | } | 
| 2646 |  |  |  |  |  |  |  | 
| 2647 |  |  |  |  |  |  | sub create_anon_class{ | 
| 2648 | 0 |  |  | 0 | 0 | 0 | my $self = shift; | 
| 2649 | 0 |  |  |  |  | 0 | return $self->create(undef, @_); | 
| 2650 |  |  |  |  |  |  | } | 
| 2651 |  |  |  |  |  |  |  | 
| 2652 |  |  |  |  |  |  | sub is_anon_class; | 
| 2653 |  |  |  |  |  |  |  | 
| 2654 |  |  |  |  |  |  | sub roles; | 
| 2655 |  |  |  |  |  |  |  | 
| 2656 |  |  |  |  |  |  | sub calculate_all_roles { | 
| 2657 | 0 |  |  | 0 | 0 | 0 | my $self = shift; | 
| 2658 | 0 |  |  |  |  | 0 | my %seen; | 
| 2659 | 0 |  |  |  |  | 0 | return grep { !$seen{ $_->name }++ } | 
|  | 0 |  |  |  |  | 0 |  | 
| 2660 | 0 |  |  |  |  | 0 | map  { $_->calculate_all_roles } @{ $self->roles }; | 
|  | 0 |  |  |  |  | 0 |  | 
| 2661 |  |  |  |  |  |  | } | 
| 2662 |  |  |  |  |  |  |  | 
| 2663 |  |  |  |  |  |  | sub superclasses { | 
| 2664 | 5 |  |  | 5 | 0 | 7 | my $self = shift; | 
| 2665 |  |  |  |  |  |  |  | 
| 2666 | 5 | 100 |  |  |  | 14 | if (@_) { | 
| 2667 | 3 |  |  |  |  | 5 | foreach my $super(@_){ | 
| 2668 | 3 |  |  |  |  | 9 | Mousse::Util::load_class($super); | 
| 2669 | 3 |  |  |  |  | 7 | my $meta = Mousse::Util::get_metaclass_by_name($super); | 
| 2670 | 3 | 50 |  |  |  | 10 | next if $self->verify_superclass($super, $meta); | 
| 2671 | 0 |  |  |  |  | 0 | $self->_reconcile_with_superclass_meta($meta); | 
| 2672 |  |  |  |  |  |  | } | 
| 2673 | 3 |  |  |  |  | 6 | return @{ $self->{superclasses} } = @_; | 
|  | 3 |  |  |  |  | 61 |  | 
| 2674 |  |  |  |  |  |  | } | 
| 2675 |  |  |  |  |  |  |  | 
| 2676 | 2 |  |  |  |  | 3 | return @{ $self->{superclasses} }; | 
|  | 2 |  |  |  |  | 10 |  | 
| 2677 |  |  |  |  |  |  | } | 
| 2678 |  |  |  |  |  |  |  | 
| 2679 |  |  |  |  |  |  | sub verify_superclass { | 
| 2680 | 3 |  |  | 3 | 0 | 6 | my($self, $super, $super_meta) = @_; | 
| 2681 |  |  |  |  |  |  |  | 
| 2682 | 3 | 100 |  |  |  | 6 | if(defined $super_meta) { | 
| 2683 | 1 | 50 |  |  |  | 6 | if(Mousse::Util::is_a_metarole($super_meta)){ | 
| 2684 | 0 |  |  |  |  | 0 | $self->throw_error("You cannot inherit from a Mousse Role ($super)"); | 
| 2685 |  |  |  |  |  |  | } | 
| 2686 |  |  |  |  |  |  | } | 
| 2687 |  |  |  |  |  |  | else { | 
| 2688 |  |  |  |  |  |  | # The metaclass of $super is not initialized. | 
| 2689 |  |  |  |  |  |  | # i.e. it might be Mousse::Object, a mixin package (e.g. Exporter), | 
| 2690 |  |  |  |  |  |  | # or a foreign class including Moose classes. | 
| 2691 |  |  |  |  |  |  | # See also Mousse::Foreign::Meta::Role::Class. | 
| 2692 | 2 |  |  |  |  | 15 | my $mm = $super->can('meta'); | 
| 2693 | 2 | 50 | 33 |  |  | 13 | if(!($mm && $mm == \&Mousse::Util::meta)) { | 
| 2694 | 0 | 0 | 0 |  |  | 0 | if($super->can('new') or $super->can('DESTROY')) { | 
| 2695 | 0 |  |  |  |  | 0 | $self->inherit_from_foreign_class($super); | 
| 2696 |  |  |  |  |  |  | } | 
| 2697 |  |  |  |  |  |  | } | 
| 2698 | 2 |  |  |  |  | 11 | return 1; # always ok | 
| 2699 |  |  |  |  |  |  | } | 
| 2700 |  |  |  |  |  |  |  | 
| 2701 | 1 |  |  |  |  | 14 | return $self->isa(ref $super_meta); # checks metaclass compatibility | 
| 2702 |  |  |  |  |  |  | } | 
| 2703 |  |  |  |  |  |  |  | 
| 2704 |  |  |  |  |  |  | sub inherit_from_foreign_class { | 
| 2705 | 0 |  |  | 0 | 0 | 0 | my($class, $super) = @_; | 
| 2706 | 0 | 0 |  |  |  | 0 | if($ENV{PERL_MOUSE_STRICT}) { | 
| 2707 | 0 |  |  |  |  | 0 | Carp::carp("You inherit from non-Mousse class ($super)," | 
| 2708 |  |  |  |  |  |  | . " but it is unlikely to work correctly." | 
| 2709 |  |  |  |  |  |  | . " Please consider using MousseX::Foreign"); | 
| 2710 |  |  |  |  |  |  | } | 
| 2711 | 0 |  |  |  |  | 0 | return; | 
| 2712 |  |  |  |  |  |  | } | 
| 2713 |  |  |  |  |  |  |  | 
| 2714 |  |  |  |  |  |  | my @MetaClassTypes = ( | 
| 2715 |  |  |  |  |  |  | 'attribute',   # Mousse::Meta::Attribute | 
| 2716 |  |  |  |  |  |  | 'method',      # Mousse::Meta::Method | 
| 2717 |  |  |  |  |  |  | 'constructor', # Mousse::Meta::Method::Constructor | 
| 2718 |  |  |  |  |  |  | 'destructor',  # Mousse::Meta::Method::Destructor | 
| 2719 |  |  |  |  |  |  | ); | 
| 2720 |  |  |  |  |  |  |  | 
| 2721 |  |  |  |  |  |  | sub _reconcile_with_superclass_meta { | 
| 2722 | 0 |  |  | 0 |  | 0 | my($self, $other) = @_; | 
| 2723 |  |  |  |  |  |  |  | 
| 2724 |  |  |  |  |  |  | # find incompatible traits | 
| 2725 | 0 |  |  |  |  | 0 | my %metaroles; | 
| 2726 | 0 |  |  |  |  | 0 | foreach my $metaclass_type(@MetaClassTypes){ | 
| 2727 | 0 |  | 0 |  |  | 0 | my $accessor = $self->can($metaclass_type . '_metaclass') | 
| 2728 |  |  |  |  |  |  | || $self->can($metaclass_type . '_class'); | 
| 2729 |  |  |  |  |  |  |  | 
| 2730 | 0 |  |  |  |  | 0 | my $other_c = $other->$accessor(); | 
| 2731 | 0 |  |  |  |  | 0 | my $self_c  = $self->$accessor(); | 
| 2732 |  |  |  |  |  |  |  | 
| 2733 | 0 | 0 |  |  |  | 0 | if(!$self_c->isa($other_c)){ | 
| 2734 | 0 |  |  |  |  | 0 | $metaroles{$metaclass_type} | 
| 2735 |  |  |  |  |  |  | = [ $self_c->meta->_collect_roles($other_c->meta) ]; | 
| 2736 |  |  |  |  |  |  | } | 
| 2737 |  |  |  |  |  |  | } | 
| 2738 |  |  |  |  |  |  |  | 
| 2739 | 0 |  |  |  |  | 0 | $metaroles{class} = [$self->meta->_collect_roles($other->meta)]; | 
| 2740 |  |  |  |  |  |  |  | 
| 2741 |  |  |  |  |  |  | #use Data::Dumper; print Data::Dumper->new([\%metaroles], ['*metaroles'])->Indent(1)->Dump; | 
| 2742 |  |  |  |  |  |  |  | 
| 2743 | 0 |  |  |  |  | 0 | require Mousse::Util::MetaRole; | 
| 2744 | 0 |  |  |  |  | 0 | $_[0] = Mousse::Util::MetaRole::apply_metaroles( | 
| 2745 |  |  |  |  |  |  | for             => $self, | 
| 2746 |  |  |  |  |  |  | class_metaroles => \%metaroles, | 
| 2747 |  |  |  |  |  |  | ); | 
| 2748 | 0 |  |  |  |  | 0 | return; | 
| 2749 |  |  |  |  |  |  | } | 
| 2750 |  |  |  |  |  |  |  | 
| 2751 |  |  |  |  |  |  | sub _collect_roles { | 
| 2752 | 0 |  |  | 0 |  | 0 | my ($self, $other) = @_; | 
| 2753 |  |  |  |  |  |  |  | 
| 2754 |  |  |  |  |  |  | # find common ancestor | 
| 2755 | 0 |  |  |  |  | 0 | my @self_lin_isa  = $self->linearized_isa; | 
| 2756 | 0 |  |  |  |  | 0 | my @other_lin_isa = $other->linearized_isa; | 
| 2757 |  |  |  |  |  |  |  | 
| 2758 | 0 |  |  |  |  | 0 | my(@self_anon_supers, @other_anon_supers); | 
| 2759 | 0 |  |  |  |  | 0 | push @self_anon_supers,  shift @self_lin_isa  while $self_lin_isa[0]->meta->is_anon_class; | 
| 2760 | 0 |  |  |  |  | 0 | push @other_anon_supers, shift @other_lin_isa while $other_lin_isa[0]->meta->is_anon_class; | 
| 2761 |  |  |  |  |  |  |  | 
| 2762 | 0 |  | 0 |  |  | 0 | my $common_ancestor = $self_lin_isa[0] eq $other_lin_isa[0] && $self_lin_isa[0]; | 
| 2763 |  |  |  |  |  |  |  | 
| 2764 | 0 | 0 |  |  |  | 0 | if(!$common_ancestor){ | 
| 2765 | 0 |  |  |  |  | 0 | $self->throw_error(sprintf '%s cannot have %s as a super class because of their metaclass incompatibility', | 
| 2766 |  |  |  |  |  |  | $self->name, $other->name); | 
| 2767 |  |  |  |  |  |  | } | 
| 2768 |  |  |  |  |  |  |  | 
| 2769 | 0 |  |  |  |  | 0 | my %seen; | 
| 2770 | 0 |  |  |  |  | 0 | return sort grep { !$seen{$_}++ } ## no critic | 
|  | 0 |  |  |  |  | 0 |  | 
| 2771 | 0 |  |  |  |  | 0 | (map{ $_->name } map{ $_->meta->calculate_all_roles } @self_anon_supers), | 
|  | 0 |  |  |  |  | 0 |  | 
| 2772 | 0 |  |  |  |  | 0 | (map{ $_->name } map{ $_->meta->calculate_all_roles } @other_anon_supers), | 
|  | 0 |  |  |  |  | 0 |  | 
| 2773 |  |  |  |  |  |  | ; | 
| 2774 |  |  |  |  |  |  | } | 
| 2775 |  |  |  |  |  |  |  | 
| 2776 |  |  |  |  |  |  |  | 
| 2777 |  |  |  |  |  |  | sub find_method_by_name { | 
| 2778 | 0 |  |  | 0 | 0 | 0 | my($self, $method_name) = @_; | 
| 2779 | 0 | 0 |  |  |  | 0 | defined($method_name) | 
| 2780 |  |  |  |  |  |  | or $self->throw_error('You must define a method name to find'); | 
| 2781 |  |  |  |  |  |  |  | 
| 2782 | 0 |  |  |  |  | 0 | foreach my $class( $self->linearized_isa ){ | 
| 2783 | 0 |  |  |  |  | 0 | my $method = $self->initialize($class)->get_method($method_name); | 
| 2784 | 0 | 0 |  |  |  | 0 | return $method if defined $method; | 
| 2785 |  |  |  |  |  |  | } | 
| 2786 | 0 |  |  |  |  | 0 | return undef; | 
| 2787 |  |  |  |  |  |  | } | 
| 2788 |  |  |  |  |  |  |  | 
| 2789 |  |  |  |  |  |  | sub get_all_methods { | 
| 2790 | 0 |  |  | 0 | 0 | 0 | my($self) = @_; | 
| 2791 | 0 |  |  |  |  | 0 | return map{ $self->find_method_by_name($_) } $self->get_all_method_names; | 
|  | 0 |  |  |  |  | 0 |  | 
| 2792 |  |  |  |  |  |  | } | 
| 2793 |  |  |  |  |  |  |  | 
| 2794 |  |  |  |  |  |  | sub get_all_method_names { | 
| 2795 | 0 |  |  | 0 | 0 | 0 | my $self = shift; | 
| 2796 | 0 |  |  |  |  | 0 | my %uniq; | 
| 2797 | 0 |  |  |  |  | 0 | return grep { $uniq{$_}++ == 0 } | 
|  | 0 |  |  |  |  | 0 |  | 
| 2798 | 0 |  |  |  |  | 0 | map { Mousse::Meta::Class->initialize($_)->get_method_list() } | 
| 2799 |  |  |  |  |  |  | $self->linearized_isa; | 
| 2800 |  |  |  |  |  |  | } | 
| 2801 |  |  |  |  |  |  |  | 
| 2802 |  |  |  |  |  |  | sub find_attribute_by_name { | 
| 2803 | 0 |  |  | 0 | 0 | 0 | my($self, $name) = @_; | 
| 2804 | 0 | 0 |  |  |  | 0 | defined($name) | 
| 2805 |  |  |  |  |  |  | or $self->throw_error('You must define an attribute name to find'); | 
| 2806 | 0 |  |  |  |  | 0 | foreach my $attr($self->get_all_attributes) { | 
| 2807 | 0 | 0 |  |  |  | 0 | return $attr if $attr->name eq $name; | 
| 2808 |  |  |  |  |  |  | } | 
| 2809 | 0 |  |  |  |  | 0 | return undef; | 
| 2810 |  |  |  |  |  |  | } | 
| 2811 |  |  |  |  |  |  |  | 
| 2812 |  |  |  |  |  |  | sub add_attribute { | 
| 2813 | 2 |  |  | 2 | 0 | 4 | my $self = shift; | 
| 2814 |  |  |  |  |  |  |  | 
| 2815 | 2 |  |  |  |  | 3 | my($attr, $name); | 
| 2816 |  |  |  |  |  |  |  | 
| 2817 | 2 | 50 |  |  |  | 9 | if(Scalar::Util::blessed($_[0])){ | 
| 2818 | 0 |  |  |  |  | 0 | $attr = $_[0]; | 
| 2819 |  |  |  |  |  |  |  | 
| 2820 | 0 | 0 |  |  |  | 0 | $attr->isa('Mousse::Meta::Attribute') | 
| 2821 |  |  |  |  |  |  | || $self->throw_error("Your attribute must be an instance of Mousse::Meta::Attribute (or a subclass)"); | 
| 2822 |  |  |  |  |  |  |  | 
| 2823 | 0 |  |  |  |  | 0 | $name = $attr->name; | 
| 2824 |  |  |  |  |  |  | } | 
| 2825 |  |  |  |  |  |  | else{ | 
| 2826 |  |  |  |  |  |  | # _process_attribute | 
| 2827 | 2 |  |  |  |  | 4 | $name = shift; | 
| 2828 |  |  |  |  |  |  |  | 
| 2829 | 2 | 50 |  |  |  | 9 | my %args = (@_ == 1) ? %{$_[0]} : @_; | 
|  | 0 |  |  |  |  | 0 |  | 
| 2830 |  |  |  |  |  |  |  | 
| 2831 | 2 | 50 |  |  |  | 6 | defined($name) | 
| 2832 |  |  |  |  |  |  | or $self->throw_error('You must provide a name for the attribute'); | 
| 2833 |  |  |  |  |  |  |  | 
| 2834 | 2 | 50 |  |  |  | 36 | if ($name =~ s/^\+//) { # inherited attributes | 
| 2835 | 0 | 0 |  |  |  | 0 | my $inherited_attr = $self->find_attribute_by_name($name) | 
| 2836 |  |  |  |  |  |  | or $self->throw_error("Could not find an attribute by the name of '$name' to inherit from in ".$self->name); | 
| 2837 |  |  |  |  |  |  |  | 
| 2838 | 0 |  |  |  |  | 0 | $attr = $inherited_attr->clone_and_inherit_options(%args); | 
| 2839 |  |  |  |  |  |  | } | 
| 2840 |  |  |  |  |  |  | else{ | 
| 2841 | 2 |  |  |  |  | 8 | my($attribute_class, @traits) = $self->attribute_metaclass->interpolate_class(\%args); | 
| 2842 | 2 | 50 |  |  |  | 9 | $args{traits} = \@traits if @traits; | 
| 2843 |  |  |  |  |  |  |  | 
| 2844 | 2 |  |  |  |  | 10 | $attr = $attribute_class->new($name, %args); | 
| 2845 |  |  |  |  |  |  | } | 
| 2846 |  |  |  |  |  |  | } | 
| 2847 |  |  |  |  |  |  |  | 
| 2848 | 2 |  |  |  |  | 14 | Scalar::Util::weaken( $attr->{associated_class} = $self ); | 
| 2849 |  |  |  |  |  |  |  | 
| 2850 |  |  |  |  |  |  | # install accessors first | 
| 2851 | 2 |  |  |  |  | 7 | $attr->install_accessors(); | 
| 2852 |  |  |  |  |  |  |  | 
| 2853 |  |  |  |  |  |  | # then register the attribute to the metaclass | 
| 2854 | 2 |  |  |  |  | 4 | $attr->{insertion_order}   = keys %{ $self->{attributes} }; | 
|  | 2 |  |  |  |  | 9 |  | 
| 2855 | 2 |  |  |  |  | 5 | $self->{attributes}{$name} = $attr; | 
| 2856 | 2 |  |  |  |  | 8 | $self->_invalidate_metaclass_cache(); | 
| 2857 |  |  |  |  |  |  |  | 
| 2858 | 2 | 50 | 0 |  |  | 15 | if(!$attr->{associated_methods} && ($attr->{is} || '') ne 'bare'){ | 
|  |  |  | 33 |  |  |  |  | 
| 2859 | 0 |  |  |  |  | 0 | Carp::carp(qq{Attribute ($name) of class }.$self->name | 
| 2860 |  |  |  |  |  |  | .qq{ has no associated methods (did you mean to provide an "is" argument?)}); | 
| 2861 |  |  |  |  |  |  | } | 
| 2862 | 2 |  |  |  |  | 6 | return $attr; | 
| 2863 |  |  |  |  |  |  | } | 
| 2864 |  |  |  |  |  |  |  | 
| 2865 |  |  |  |  |  |  | sub _calculate_all_attributes { | 
| 2866 | 2 |  |  | 2 |  | 3 | my($self) = @_; | 
| 2867 | 2 |  |  |  |  | 3 | my %seen; | 
| 2868 |  |  |  |  |  |  | my @all_attrs; | 
| 2869 | 2 |  |  |  |  | 7 | foreach my $class($self->linearized_isa) { | 
| 2870 | 5 | 100 |  |  |  | 10 | my $meta  = Mousse::Util::get_metaclass_by_name($class) or next; | 
| 2871 | 3 |  |  |  |  | 4 | my @attrs = grep { !$seen{$_->name}++ } values %{$meta->{attributes}}; | 
|  | 3 |  |  |  |  | 7 |  | 
|  | 3 |  |  |  |  | 9 |  | 
| 2872 | 0 |  |  |  |  | 0 | @attrs = sort { | 
| 2873 | 3 |  |  |  |  | 8 | $b->{insertion_order} <=> $a->{insertion_order} | 
| 2874 |  |  |  |  |  |  | } @attrs; | 
| 2875 | 3 |  |  |  |  | 13 | push @all_attrs, @attrs; | 
| 2876 |  |  |  |  |  |  | } | 
| 2877 | 2 |  |  |  |  | 13 | return [reverse @all_attrs]; | 
| 2878 |  |  |  |  |  |  | } | 
| 2879 |  |  |  |  |  |  |  | 
| 2880 |  |  |  |  |  |  | sub linearized_isa; | 
| 2881 |  |  |  |  |  |  |  | 
| 2882 |  |  |  |  |  |  | sub new_object; | 
| 2883 |  |  |  |  |  |  | sub clone_object; | 
| 2884 |  |  |  |  |  |  |  | 
| 2885 |  |  |  |  |  |  | sub immutable_options { | 
| 2886 | 0 |  |  | 0 | 0 | 0 | my ( $self, @args ) = @_; | 
| 2887 |  |  |  |  |  |  |  | 
| 2888 |  |  |  |  |  |  | return ( | 
| 2889 | 0 |  |  |  |  | 0 | inline_constructor => 1, | 
| 2890 |  |  |  |  |  |  | inline_destructor  => 1, | 
| 2891 |  |  |  |  |  |  | constructor_name   => 'new', | 
| 2892 |  |  |  |  |  |  | @args, | 
| 2893 |  |  |  |  |  |  | ); | 
| 2894 |  |  |  |  |  |  | } | 
| 2895 |  |  |  |  |  |  |  | 
| 2896 |  |  |  |  |  |  | sub make_immutable { | 
| 2897 | 0 |  |  | 0 | 0 | 0 | my $self = shift; | 
| 2898 | 0 |  |  |  |  | 0 | my %args = $self->immutable_options(@_); | 
| 2899 |  |  |  |  |  |  |  | 
| 2900 | 0 |  |  |  |  | 0 | $self->{is_immutable}++; | 
| 2901 |  |  |  |  |  |  |  | 
| 2902 | 0 | 0 |  |  |  | 0 | if ($args{inline_constructor}) { | 
| 2903 | 0 |  |  |  |  | 0 | $self->add_method($args{constructor_name} => | 
| 2904 |  |  |  |  |  |  | Mousse::Util::load_class($self->constructor_class) | 
| 2905 |  |  |  |  |  |  | ->_generate_constructor($self, \%args)); | 
| 2906 |  |  |  |  |  |  | } | 
| 2907 |  |  |  |  |  |  |  | 
| 2908 | 0 | 0 |  |  |  | 0 | if ($args{inline_destructor}) { | 
| 2909 | 0 |  |  |  |  | 0 | $self->add_method(DESTROY => | 
| 2910 |  |  |  |  |  |  | Mousse::Util::load_class($self->destructor_class) | 
| 2911 |  |  |  |  |  |  | ->_generate_destructor($self, \%args)); | 
| 2912 |  |  |  |  |  |  | } | 
| 2913 |  |  |  |  |  |  |  | 
| 2914 |  |  |  |  |  |  | # Moose's make_immutable returns true allowing calling code to skip | 
| 2915 |  |  |  |  |  |  | # setting an explicit true value at the end of a source file. | 
| 2916 | 0 |  |  |  |  | 0 | return 1; | 
| 2917 |  |  |  |  |  |  | } | 
| 2918 |  |  |  |  |  |  |  | 
| 2919 |  |  |  |  |  |  | sub make_mutable { | 
| 2920 | 0 |  |  | 0 | 0 | 0 | my($self) = @_; | 
| 2921 | 0 |  |  |  |  | 0 | $self->{is_immutable} = 0; | 
| 2922 | 0 |  |  |  |  | 0 | return; | 
| 2923 |  |  |  |  |  |  | } | 
| 2924 |  |  |  |  |  |  |  | 
| 2925 |  |  |  |  |  |  | sub is_immutable; | 
| 2926 | 0 |  |  | 0 | 0 | 0 | sub is_mutable   { !$_[0]->is_immutable } | 
| 2927 |  |  |  |  |  |  |  | 
| 2928 |  |  |  |  |  |  | sub _install_modifier { | 
| 2929 | 0 |  |  | 0 |  | 0 | my( $self, $type, $name, $code ) = @_; | 
| 2930 | 0 |  |  |  |  | 0 | my $into = $self->name; | 
| 2931 |  |  |  |  |  |  |  | 
| 2932 | 0 | 0 |  |  |  | 0 | my $original = $into->can($name) | 
| 2933 |  |  |  |  |  |  | or $self->throw_error("The method '$name' was not found in the inheritance hierarchy for $into"); | 
| 2934 |  |  |  |  |  |  |  | 
| 2935 | 0 |  |  |  |  | 0 | my $modifier_table = $self->{modifiers}{$name}; | 
| 2936 |  |  |  |  |  |  |  | 
| 2937 | 0 | 0 |  |  |  | 0 | if(!$modifier_table){ | 
| 2938 | 0 |  |  |  |  | 0 | my(@before, @after, @around); | 
| 2939 | 0 |  |  |  |  | 0 | my $cache = $original; | 
| 2940 |  |  |  |  |  |  | my $modified = sub { | 
| 2941 | 0 | 0 |  | 0 |  | 0 | if(@before) { | 
| 2942 | 0 |  |  |  |  | 0 | for my $c (@before) { $c->(@_) } | 
|  | 0 |  |  |  |  | 0 |  | 
| 2943 |  |  |  |  |  |  | } | 
| 2944 | 0 | 0 |  |  |  | 0 | unless(@after) { | 
| 2945 | 0 |  |  |  |  | 0 | return $cache->(@_); | 
| 2946 |  |  |  |  |  |  | } | 
| 2947 |  |  |  |  |  |  |  | 
| 2948 | 0 | 0 |  |  |  | 0 | if(wantarray){ # list context | 
|  |  | 0 |  |  |  |  |  | 
| 2949 | 0 |  |  |  |  | 0 | my @rval = $cache->(@_); | 
| 2950 |  |  |  |  |  |  |  | 
| 2951 | 0 |  |  |  |  | 0 | for my $c(@after){ $c->(@_) } | 
|  | 0 |  |  |  |  | 0 |  | 
| 2952 | 0 |  |  |  |  | 0 | return @rval; | 
| 2953 |  |  |  |  |  |  | } | 
| 2954 |  |  |  |  |  |  | elsif(defined wantarray){ # scalar context | 
| 2955 | 0 |  |  |  |  | 0 | my $rval = $cache->(@_); | 
| 2956 |  |  |  |  |  |  |  | 
| 2957 | 0 |  |  |  |  | 0 | for my $c(@after){ $c->(@_) } | 
|  | 0 |  |  |  |  | 0 |  | 
| 2958 | 0 |  |  |  |  | 0 | return $rval; | 
| 2959 |  |  |  |  |  |  | } | 
| 2960 |  |  |  |  |  |  | else{ # void context | 
| 2961 | 0 |  |  |  |  | 0 | $cache->(@_); | 
| 2962 |  |  |  |  |  |  |  | 
| 2963 | 0 |  |  |  |  | 0 | for my $c(@after){ $c->(@_) } | 
|  | 0 |  |  |  |  | 0 |  | 
| 2964 | 0 |  |  |  |  | 0 | return; | 
| 2965 |  |  |  |  |  |  | } | 
| 2966 | 0 |  |  |  |  | 0 | }; | 
| 2967 |  |  |  |  |  |  |  | 
| 2968 | 0 |  |  |  |  | 0 | $self->{modifiers}{$name} = $modifier_table = { | 
| 2969 |  |  |  |  |  |  | original => $original, | 
| 2970 |  |  |  |  |  |  |  | 
| 2971 |  |  |  |  |  |  | before   => \@before, | 
| 2972 |  |  |  |  |  |  | after    => \@after, | 
| 2973 |  |  |  |  |  |  | around   => \@around, | 
| 2974 |  |  |  |  |  |  |  | 
| 2975 |  |  |  |  |  |  | cache    => \$cache, # cache for around modifiers | 
| 2976 |  |  |  |  |  |  | }; | 
| 2977 |  |  |  |  |  |  |  | 
| 2978 | 0 |  |  |  |  | 0 | $self->add_method($name => $modified); | 
| 2979 |  |  |  |  |  |  | } | 
| 2980 |  |  |  |  |  |  |  | 
| 2981 | 0 | 0 |  |  |  | 0 | if($type eq 'before'){ | 
|  |  | 0 |  |  |  |  |  | 
| 2982 | 0 |  |  |  |  | 0 | unshift @{$modifier_table->{before}}, $code; | 
|  | 0 |  |  |  |  | 0 |  | 
| 2983 |  |  |  |  |  |  | } | 
| 2984 |  |  |  |  |  |  | elsif($type eq 'after'){ | 
| 2985 | 0 |  |  |  |  | 0 | push @{$modifier_table->{after}}, $code; | 
|  | 0 |  |  |  |  | 0 |  | 
| 2986 |  |  |  |  |  |  | } | 
| 2987 |  |  |  |  |  |  | else{ # around | 
| 2988 | 0 |  |  |  |  | 0 | push @{$modifier_table->{around}}, $code; | 
|  | 0 |  |  |  |  | 0 |  | 
| 2989 |  |  |  |  |  |  |  | 
| 2990 | 0 |  |  |  |  | 0 | my $next = ${ $modifier_table->{cache} }; | 
|  | 0 |  |  |  |  | 0 |  | 
| 2991 | 0 |  |  | 0 |  | 0 | ${ $modifier_table->{cache} } = sub{ $code->($next, @_) }; | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 2992 |  |  |  |  |  |  | } | 
| 2993 |  |  |  |  |  |  |  | 
| 2994 | 0 |  |  |  |  | 0 | return; | 
| 2995 |  |  |  |  |  |  | } | 
| 2996 |  |  |  |  |  |  |  | 
| 2997 |  |  |  |  |  |  | sub add_before_method_modifier { | 
| 2998 | 0 |  |  | 0 | 0 | 0 | my ( $self, $name, $code ) = @_; | 
| 2999 | 0 |  |  |  |  | 0 | $self->_install_modifier( 'before', $name, $code ); | 
| 3000 |  |  |  |  |  |  | } | 
| 3001 |  |  |  |  |  |  |  | 
| 3002 |  |  |  |  |  |  | sub add_around_method_modifier { | 
| 3003 | 0 |  |  | 0 | 0 | 0 | my ( $self, $name, $code ) = @_; | 
| 3004 | 0 |  |  |  |  | 0 | $self->_install_modifier( 'around', $name, $code ); | 
| 3005 |  |  |  |  |  |  | } | 
| 3006 |  |  |  |  |  |  |  | 
| 3007 |  |  |  |  |  |  | sub add_after_method_modifier { | 
| 3008 | 0 |  |  | 0 | 0 | 0 | my ( $self, $name, $code ) = @_; | 
| 3009 | 0 |  |  |  |  | 0 | $self->_install_modifier( 'after', $name, $code ); | 
| 3010 |  |  |  |  |  |  | } | 
| 3011 |  |  |  |  |  |  |  | 
| 3012 |  |  |  |  |  |  | sub add_override_method_modifier { | 
| 3013 | 0 |  |  | 0 | 0 | 0 | my ($self, $name, $code) = @_; | 
| 3014 |  |  |  |  |  |  |  | 
| 3015 | 0 | 0 |  |  |  | 0 | if($self->has_method($name)){ | 
| 3016 | 0 |  |  |  |  | 0 | $self->throw_error("Cannot add an override method if a local method is already present"); | 
| 3017 |  |  |  |  |  |  | } | 
| 3018 |  |  |  |  |  |  |  | 
| 3019 | 0 |  |  |  |  | 0 | my $package = $self->name; | 
| 3020 |  |  |  |  |  |  |  | 
| 3021 | 0 | 0 |  |  |  | 0 | my $super_body = $package->can($name) | 
| 3022 |  |  |  |  |  |  | or $self->throw_error("You cannot override '$name' because it has no super method"); | 
| 3023 |  |  |  |  |  |  |  | 
| 3024 |  |  |  |  |  |  | $self->add_method($name => sub { | 
| 3025 | 0 |  |  | 0 |  | 0 | local $Mousse::SUPER_PACKAGE = $package; | 
| 3026 | 0 |  |  |  |  | 0 | local $Mousse::SUPER_BODY    = $super_body; | 
| 3027 | 0 |  |  |  |  | 0 | local @Mousse::SUPER_ARGS    = @_; | 
| 3028 | 0 |  |  |  |  | 0 | &{$code}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 3029 | 0 |  |  |  |  | 0 | }); | 
| 3030 | 0 |  |  |  |  | 0 | return; | 
| 3031 |  |  |  |  |  |  | } | 
| 3032 |  |  |  |  |  |  |  | 
| 3033 |  |  |  |  |  |  | sub add_augment_method_modifier { | 
| 3034 | 0 |  |  | 0 | 0 | 0 | my ($self, $name, $code) = @_; | 
| 3035 | 0 | 0 |  |  |  | 0 | if($self->has_method($name)){ | 
| 3036 | 0 |  |  |  |  | 0 | $self->throw_error("Cannot add an augment method if a local method is already present"); | 
| 3037 |  |  |  |  |  |  | } | 
| 3038 |  |  |  |  |  |  |  | 
| 3039 | 0 | 0 |  |  |  | 0 | my $super = $self->find_method_by_name($name) | 
| 3040 |  |  |  |  |  |  | or $self->throw_error("You cannot augment '$name' because it has no super method"); | 
| 3041 |  |  |  |  |  |  |  | 
| 3042 | 0 |  |  |  |  | 0 | my $super_package = $super->package_name; | 
| 3043 | 0 |  |  |  |  | 0 | my $super_body    = $super->body; | 
| 3044 |  |  |  |  |  |  |  | 
| 3045 |  |  |  |  |  |  | $self->add_method($name => sub { | 
| 3046 | 0 |  |  | 0 |  | 0 | local $Mousse::INNER_BODY{$super_package} = $code; | 
| 3047 | 0 |  |  |  |  | 0 | local $Mousse::INNER_ARGS{$super_package} = [@_]; | 
| 3048 | 0 |  |  |  |  | 0 | &{$super_body}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 3049 | 0 |  |  |  |  | 0 | }); | 
| 3050 | 0 |  |  |  |  | 0 | return; | 
| 3051 |  |  |  |  |  |  | } | 
| 3052 |  |  |  |  |  |  |  | 
| 3053 |  |  |  |  |  |  | sub does_role { | 
| 3054 | 0 |  |  | 0 | 0 | 0 | my ($self, $role_name) = @_; | 
| 3055 |  |  |  |  |  |  |  | 
| 3056 | 0 | 0 |  |  |  | 0 | (defined $role_name) | 
| 3057 |  |  |  |  |  |  | || $self->throw_error("You must supply a role name to look for"); | 
| 3058 |  |  |  |  |  |  |  | 
| 3059 | 0 | 0 |  |  |  | 0 | $role_name = $role_name->name if ref $role_name; | 
| 3060 |  |  |  |  |  |  |  | 
| 3061 | 0 |  |  |  |  | 0 | for my $class ($self->linearized_isa) { | 
| 3062 | 0 | 0 |  |  |  | 0 | my $meta = Mousse::Util::get_metaclass_by_name($class) | 
| 3063 |  |  |  |  |  |  | or next; | 
| 3064 |  |  |  |  |  |  |  | 
| 3065 | 0 |  |  |  |  | 0 | for my $role (@{ $meta->roles }) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 3066 |  |  |  |  |  |  |  | 
| 3067 | 0 | 0 |  |  |  | 0 | return 1 if $role->does_role($role_name); | 
| 3068 |  |  |  |  |  |  | } | 
| 3069 |  |  |  |  |  |  | } | 
| 3070 |  |  |  |  |  |  |  | 
| 3071 | 0 |  |  |  |  | 0 | return 0; | 
| 3072 |  |  |  |  |  |  | } | 
| 3073 |  |  |  |  |  |  |  | 
| 3074 |  |  |  |  |  |  | # Contents of Mouse::Meta::Method | 
| 3075 |  |  |  |  |  |  | package Mousse::Meta::Method; | 
| 3076 | 1 |  |  | 1 |  | 7 | use Mousse::Util qw(:meta); # enables strict and warnings | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 4 |  | 
| 3077 | 1 |  |  | 1 |  | 4 | use Scalar::Util (); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 55 |  | 
| 3078 |  |  |  |  |  |  |  | 
| 3079 |  |  |  |  |  |  | use overload | 
| 3080 |  |  |  |  |  |  | '=='  => '_equal', | 
| 3081 |  |  |  |  |  |  | 'eq'  => '_equal', | 
| 3082 | 0 |  |  | 0 |  | 0 | '&{}' => sub{ $_[0]->body }, | 
| 3083 | 1 |  |  |  |  | 11 | fallback => 1, | 
| 3084 | 1 |  |  | 1 |  | 4 | ; | 
|  | 1 |  |  |  |  | 1 |  | 
| 3085 |  |  |  |  |  |  |  | 
| 3086 |  |  |  |  |  |  | sub wrap { | 
| 3087 | 0 |  |  | 0 | 0 | 0 | my $class = shift; | 
| 3088 | 0 | 0 |  |  |  | 0 | unshift @_, 'body' if @_ % 2 != 0; | 
| 3089 | 0 |  |  |  |  | 0 | return $class->_new(@_); | 
| 3090 |  |  |  |  |  |  | } | 
| 3091 |  |  |  |  |  |  |  | 
| 3092 |  |  |  |  |  |  | sub _new{ | 
| 3093 | 0 |  |  | 0 |  | 0 | my($class, %args) = @_; | 
| 3094 | 0 |  |  |  |  | 0 | my $self = bless \%args, $class; | 
| 3095 |  |  |  |  |  |  |  | 
| 3096 | 0 | 0 |  |  |  | 0 | if($class ne __PACKAGE__){ | 
| 3097 | 0 |  |  |  |  | 0 | $self->meta->_initialize_object($self, \%args); | 
| 3098 |  |  |  |  |  |  | } | 
| 3099 | 0 |  |  |  |  | 0 | return $self; | 
| 3100 |  |  |  |  |  |  | } | 
| 3101 |  |  |  |  |  |  |  | 
| 3102 | 0 |  |  | 0 | 0 | 0 | sub body                 { $_[0]->{body}    } | 
| 3103 | 0 |  |  | 0 | 0 | 0 | sub name                 { $_[0]->{name}    } | 
| 3104 | 0 |  |  | 0 | 0 | 0 | sub package_name         { $_[0]->{package} } | 
| 3105 | 0 |  |  | 0 | 0 | 0 | sub associated_metaclass { $_[0]->{associated_metaclass} } | 
| 3106 |  |  |  |  |  |  |  | 
| 3107 |  |  |  |  |  |  | sub fully_qualified_name { | 
| 3108 | 0 |  |  | 0 | 0 | 0 | my($self) = @_; | 
| 3109 | 0 |  |  |  |  | 0 | return $self->package_name . '::' . $self->name; | 
| 3110 |  |  |  |  |  |  | } | 
| 3111 |  |  |  |  |  |  |  | 
| 3112 |  |  |  |  |  |  | # for Moose compat | 
| 3113 |  |  |  |  |  |  | sub _equal { | 
| 3114 | 0 |  |  | 0 |  | 0 | my($l, $r) = @_; | 
| 3115 |  |  |  |  |  |  |  | 
| 3116 | 0 |  | 0 |  |  | 0 | return Scalar::Util::blessed($r) | 
| 3117 |  |  |  |  |  |  | && $l->body         == $r->body | 
| 3118 |  |  |  |  |  |  | && $l->name         eq $r->name | 
| 3119 |  |  |  |  |  |  | && $l->package_name eq $r->package_name; | 
| 3120 |  |  |  |  |  |  | } | 
| 3121 |  |  |  |  |  |  |  | 
| 3122 |  |  |  |  |  |  | # Contents of Mouse::Meta::Method::Accessor | 
| 3123 |  |  |  |  |  |  | package Mousse::Meta::Method::Accessor; | 
| 3124 | 1 |  |  | 1 |  | 642 | use Mousse::Util qw(:meta); # enables strict and warnings | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 7 |  | 
| 3125 |  |  |  |  |  |  |  | 
| 3126 | 1 | 50 |  | 1 |  | 6 | use constant _MOUSE_DEBUG => $ENV{MOUSE_DEBUG} ? 1 : 0; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 1674 |  | 
| 3127 |  |  |  |  |  |  |  | 
| 3128 |  |  |  |  |  |  | sub _inline_slot{ | 
| 3129 | 2 |  |  | 2 |  | 4 | my(undef, $self_var, $attr_name) = @_; | 
| 3130 | 2 |  |  |  |  | 10 | return sprintf '%s->{q{%s}}', $self_var, $attr_name; | 
| 3131 |  |  |  |  |  |  | } | 
| 3132 |  |  |  |  |  |  |  | 
| 3133 |  |  |  |  |  |  | sub _generate_accessor_any{ | 
| 3134 | 2 |  |  | 2 |  | 5 | my($method_class, $type, $attribute, $class) = @_; | 
| 3135 |  |  |  |  |  |  |  | 
| 3136 | 2 |  |  |  |  | 5 | my $name          = $attribute->name; | 
| 3137 | 2 |  |  |  |  | 7 | my $default       = $attribute->default; | 
| 3138 | 2 |  |  |  |  | 6 | my $constraint    = $attribute->type_constraint; | 
| 3139 | 2 |  |  |  |  | 6 | my $builder       = $attribute->builder; | 
| 3140 | 2 |  |  |  |  | 15 | my $trigger       = $attribute->trigger; | 
| 3141 | 2 |  |  |  |  | 6 | my $is_weak       = $attribute->is_weak_ref; | 
| 3142 | 2 |  |  |  |  | 6 | my $should_deref  = $attribute->should_auto_deref; | 
| 3143 | 2 |  | 33 |  |  | 8 | my $should_coerce = (defined($constraint) | 
| 3144 |  |  |  |  |  |  | && $constraint->has_coercion | 
| 3145 |  |  |  |  |  |  | && $attribute->should_coerce); | 
| 3146 |  |  |  |  |  |  |  | 
| 3147 | 2 | 50 |  |  |  | 5 | my $compiled_type_constraint = defined($constraint) | 
| 3148 |  |  |  |  |  |  | ? $constraint->_compiled_type_constraint | 
| 3149 |  |  |  |  |  |  | : undef; | 
| 3150 |  |  |  |  |  |  |  | 
| 3151 | 2 |  |  |  |  | 4 | my $self  = '$_[0]'; | 
| 3152 | 2 |  |  |  |  | 7 | my $slot  = $method_class->_inline_slot($self, $name);; | 
| 3153 |  |  |  |  |  |  |  | 
| 3154 | 2 |  |  |  |  | 9 | my $accessor = sprintf(qq{package %s;\n#line 1 "%s-accessor for %s (%s)"\n}, $class->name, $type, $name, __FILE__) | 
| 3155 |  |  |  |  |  |  | . "sub {\n"; | 
| 3156 |  |  |  |  |  |  |  | 
| 3157 | 2 | 50 | 33 |  |  | 11 | if ($type eq 'rw' || $type eq 'wo') { | 
|  |  | 0 |  |  |  |  |  | 
| 3158 | 2 | 50 |  |  |  | 12 | if($type eq 'rw'){ | 
| 3159 | 2 |  |  |  |  | 5 | $accessor .= | 
| 3160 |  |  |  |  |  |  | 'if (scalar(@_) >= 2) {' . "\n"; | 
| 3161 |  |  |  |  |  |  | } | 
| 3162 |  |  |  |  |  |  | else{ # writer | 
| 3163 | 0 |  |  |  |  | 0 | $accessor .= | 
| 3164 |  |  |  |  |  |  | 'if(@_ < 2){ Carp::confess("Not enough arguments for the writer of $name") }'. | 
| 3165 |  |  |  |  |  |  | '{' . "\n"; | 
| 3166 |  |  |  |  |  |  | } | 
| 3167 |  |  |  |  |  |  |  | 
| 3168 | 2 |  |  |  |  | 3 | my $value = '$_[1]'; | 
| 3169 |  |  |  |  |  |  |  | 
| 3170 | 2 | 50 |  |  |  | 6 | if (defined $constraint) { | 
| 3171 | 0 | 0 |  |  |  | 0 | if ($should_coerce) { | 
| 3172 | 0 |  |  |  |  | 0 | $accessor .= | 
| 3173 |  |  |  |  |  |  | "\n". | 
| 3174 |  |  |  |  |  |  | 'my $val = $constraint->coerce('.$value.');'; | 
| 3175 | 0 |  |  |  |  | 0 | $value = '$val'; | 
| 3176 |  |  |  |  |  |  | } | 
| 3177 |  |  |  |  |  |  | $accessor .= | 
| 3178 | 0 |  |  |  |  | 0 | "\n". | 
| 3179 |  |  |  |  |  |  | '$compiled_type_constraint->('.$value.') or | 
| 3180 |  |  |  |  |  |  | $attribute->_throw_type_constraint_error('.$value.', $constraint);' . "\n"; | 
| 3181 |  |  |  |  |  |  | } | 
| 3182 |  |  |  |  |  |  |  | 
| 3183 |  |  |  |  |  |  | # if there's nothing left to do for the attribute we can return during | 
| 3184 |  |  |  |  |  |  | # this setter | 
| 3185 | 2 | 50 | 33 |  |  | 20 | $accessor .= 'return ' if !$is_weak && !$trigger && !$should_deref; | 
|  |  |  | 33 |  |  |  |  | 
| 3186 |  |  |  |  |  |  |  | 
| 3187 | 2 |  |  |  |  | 5 | $accessor .= "$slot = $value;\n"; | 
| 3188 |  |  |  |  |  |  |  | 
| 3189 | 2 | 50 |  |  |  | 12 | if ($is_weak) { | 
| 3190 | 0 |  |  |  |  | 0 | $accessor .= "Scalar::Util::weaken($slot) if ref $slot;\n"; | 
| 3191 |  |  |  |  |  |  | } | 
| 3192 |  |  |  |  |  |  |  | 
| 3193 | 2 | 50 |  |  |  | 6 | if ($trigger) { | 
| 3194 | 0 |  |  |  |  | 0 | $accessor .= '$trigger->('.$self.', '.$value.');' . "\n"; | 
| 3195 |  |  |  |  |  |  | } | 
| 3196 |  |  |  |  |  |  |  | 
| 3197 | 2 |  |  |  |  | 4 | $accessor .= "}\n"; | 
| 3198 |  |  |  |  |  |  | } | 
| 3199 |  |  |  |  |  |  | elsif($type eq 'ro') { | 
| 3200 | 0 |  |  |  |  | 0 | $accessor .= 'Carp::confess("Cannot assign a value to a read-only accessor of $name") if scalar(@_) >= 2;' . "\n"; | 
| 3201 |  |  |  |  |  |  | } | 
| 3202 |  |  |  |  |  |  | else{ | 
| 3203 | 0 |  |  |  |  | 0 | $class->throw_error("Unknown accessor type '$type'"); | 
| 3204 |  |  |  |  |  |  | } | 
| 3205 |  |  |  |  |  |  |  | 
| 3206 | 2 | 50 | 33 |  |  | 6 | if ($attribute->is_lazy and $type ne 'wo') { | 
| 3207 | 0 |  |  |  |  | 0 | my $value; | 
| 3208 |  |  |  |  |  |  |  | 
| 3209 | 0 | 0 |  |  |  | 0 | if (defined $builder){ | 
|  |  | 0 |  |  |  |  |  | 
| 3210 | 0 |  |  |  |  | 0 | $value = "$self->\$builder()"; | 
| 3211 |  |  |  |  |  |  | } | 
| 3212 |  |  |  |  |  |  | elsif (ref($default) eq 'CODE'){ | 
| 3213 | 0 |  |  |  |  | 0 | $value = "$self->\$default()"; | 
| 3214 |  |  |  |  |  |  | } | 
| 3215 |  |  |  |  |  |  | else{ | 
| 3216 | 0 |  |  |  |  | 0 | $value = '$default'; | 
| 3217 |  |  |  |  |  |  | } | 
| 3218 |  |  |  |  |  |  |  | 
| 3219 | 0 | 0 |  |  |  | 0 | $accessor .= "els" if $type eq 'rw'; | 
| 3220 | 0 |  |  |  |  | 0 | $accessor .= "if(!exists $slot){\n"; | 
| 3221 | 0 | 0 |  |  |  | 0 | if($should_coerce){ | 
|  |  | 0 |  |  |  |  |  | 
| 3222 | 0 |  |  |  |  | 0 | $accessor .= "$slot = \$constraint->coerce($value)"; | 
| 3223 |  |  |  |  |  |  | } | 
| 3224 |  |  |  |  |  |  | elsif(defined $constraint){ | 
| 3225 | 0 |  |  |  |  | 0 | $accessor .= "my \$tmp = $value;\n"; | 
| 3226 | 0 |  |  |  |  | 0 | $accessor .= "\$compiled_type_constraint->(\$tmp)"; | 
| 3227 | 0 |  |  |  |  | 0 | $accessor .= " || \$attribute->_throw_type_constraint_error(\$tmp, \$constraint);\n"; | 
| 3228 | 0 |  |  |  |  | 0 | $accessor .= "$slot = \$tmp;\n"; | 
| 3229 |  |  |  |  |  |  | } | 
| 3230 |  |  |  |  |  |  | else{ | 
| 3231 | 0 |  |  |  |  | 0 | $accessor .= "$slot = $value;\n"; | 
| 3232 |  |  |  |  |  |  | } | 
| 3233 | 0 | 0 |  |  |  | 0 | if ($is_weak) { | 
| 3234 | 0 |  |  |  |  | 0 | $accessor .= "Scalar::Util::weaken($slot) if ref $slot;\n"; | 
| 3235 |  |  |  |  |  |  | } | 
| 3236 | 0 |  |  |  |  | 0 | $accessor .= "}\n"; | 
| 3237 |  |  |  |  |  |  | } | 
| 3238 |  |  |  |  |  |  |  | 
| 3239 | 2 | 50 |  |  |  | 5 | if ($should_deref) { | 
| 3240 | 0 | 0 |  |  |  | 0 | if ($constraint->is_a_type_of('ArrayRef')) { | 
|  |  | 0 |  |  |  |  |  | 
| 3241 | 0 |  |  |  |  | 0 | $accessor .= "return \@{ $slot || [] } if wantarray;\n"; | 
| 3242 |  |  |  |  |  |  | } | 
| 3243 |  |  |  |  |  |  | elsif($constraint->is_a_type_of('HashRef')){ | 
| 3244 | 0 |  |  |  |  | 0 | $accessor .= "return \%{ $slot || {} } if wantarray;\n"; | 
| 3245 |  |  |  |  |  |  | } | 
| 3246 |  |  |  |  |  |  | else{ | 
| 3247 | 0 |  |  |  |  | 0 | $class->throw_error("Can not auto de-reference the type constraint " . $constraint->name); | 
| 3248 |  |  |  |  |  |  | } | 
| 3249 |  |  |  |  |  |  | } | 
| 3250 |  |  |  |  |  |  |  | 
| 3251 | 2 |  |  |  |  | 6 | $accessor .= "return $slot;\n}\n"; | 
| 3252 |  |  |  |  |  |  |  | 
| 3253 | 2 |  |  |  |  | 3 | warn $accessor if _MOUSE_DEBUG; | 
| 3254 | 2 |  |  |  |  | 3 | my $code; | 
| 3255 | 2 |  |  |  |  | 3 | my $e = do{ | 
| 3256 | 2 |  |  |  |  | 3 | local $@; | 
| 3257 | 2 |  |  |  |  | 582 | $code = eval $accessor; | 
| 3258 | 2 |  |  |  |  | 26 | $@; | 
| 3259 |  |  |  |  |  |  | }; | 
| 3260 | 2 | 50 |  |  |  | 8 | die $e if $e; | 
| 3261 |  |  |  |  |  |  |  | 
| 3262 | 2 |  |  |  |  | 8 | return $code; | 
| 3263 |  |  |  |  |  |  | } | 
| 3264 |  |  |  |  |  |  |  | 
| 3265 |  |  |  |  |  |  | sub _generate_accessor{ | 
| 3266 |  |  |  |  |  |  | #my($self, $attribute, $metaclass) = @_; | 
| 3267 | 2 |  |  | 2 |  | 5 | my $self = shift; | 
| 3268 | 2 |  |  |  |  | 8 | return $self->_generate_accessor_any(rw => @_); | 
| 3269 |  |  |  |  |  |  | } | 
| 3270 |  |  |  |  |  |  |  | 
| 3271 |  |  |  |  |  |  | sub _generate_reader { | 
| 3272 |  |  |  |  |  |  | #my($self, $attribute, $metaclass) = @_; | 
| 3273 | 0 |  |  | 0 |  | 0 | my $self = shift; | 
| 3274 | 0 |  |  |  |  | 0 | return $self->_generate_accessor_any(ro => @_); | 
| 3275 |  |  |  |  |  |  | } | 
| 3276 |  |  |  |  |  |  |  | 
| 3277 |  |  |  |  |  |  | sub _generate_writer { | 
| 3278 |  |  |  |  |  |  | #my($self, $attribute, $metaclass) = @_; | 
| 3279 | 0 |  |  | 0 |  | 0 | my $self = shift; | 
| 3280 | 0 |  |  |  |  | 0 | return $self->_generate_accessor_any(wo => @_); | 
| 3281 |  |  |  |  |  |  | } | 
| 3282 |  |  |  |  |  |  |  | 
| 3283 |  |  |  |  |  |  | sub _generate_predicate { | 
| 3284 |  |  |  |  |  |  | #my($self, $attribute, $metaclass) = @_; | 
| 3285 | 0 |  |  | 0 |  | 0 | my(undef, $attribute) = @_; | 
| 3286 |  |  |  |  |  |  |  | 
| 3287 | 0 |  |  |  |  | 0 | my $slot = $attribute->name; | 
| 3288 |  |  |  |  |  |  | return sub{ | 
| 3289 | 0 |  |  | 0 |  | 0 | return exists $_[0]->{$slot}; | 
| 3290 | 0 |  |  |  |  | 0 | }; | 
| 3291 |  |  |  |  |  |  | } | 
| 3292 |  |  |  |  |  |  |  | 
| 3293 |  |  |  |  |  |  | sub _generate_clearer { | 
| 3294 |  |  |  |  |  |  | #my($self, $attribute, $metaclass) = @_; | 
| 3295 | 0 |  |  | 0 |  | 0 | my(undef, $attribute) = @_; | 
| 3296 |  |  |  |  |  |  |  | 
| 3297 | 0 |  |  |  |  | 0 | my $slot = $attribute->name; | 
| 3298 |  |  |  |  |  |  | return sub{ | 
| 3299 | 0 |  |  | 0 |  | 0 | delete $_[0]->{$slot}; | 
| 3300 | 0 |  |  |  |  | 0 | }; | 
| 3301 |  |  |  |  |  |  | } | 
| 3302 |  |  |  |  |  |  |  | 
| 3303 |  |  |  |  |  |  | # Contents of Mouse::Meta::Method::Constructor | 
| 3304 |  |  |  |  |  |  | package Mousse::Meta::Method::Constructor; | 
| 3305 | 1 |  |  | 1 |  | 8 | use Mousse::Util qw(:meta); # enables strict and warnings | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 10 |  | 
| 3306 |  |  |  |  |  |  |  | 
| 3307 | 1 | 50 |  | 1 |  | 6 | use constant _MOUSE_DEBUG => $ENV{MOUSE_DEBUG} ? 1 : 0; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 3467 |  | 
| 3308 |  |  |  |  |  |  |  | 
| 3309 |  |  |  |  |  |  | sub _inline_slot{ | 
| 3310 | 3 |  |  | 3 |  | 11 | my(undef, $self_var, $attr_name) = @_; | 
| 3311 | 3 |  |  |  |  | 9 | return sprintf '%s->{q{%s}}', $self_var, $attr_name; | 
| 3312 |  |  |  |  |  |  | } | 
| 3313 |  |  |  |  |  |  |  | 
| 3314 |  |  |  |  |  |  | sub _generate_constructor { | 
| 3315 | 0 |  |  | 0 |  | 0 | my ($class, $metaclass, $args) = @_; | 
| 3316 |  |  |  |  |  |  |  | 
| 3317 | 0 |  |  |  |  | 0 | my $associated_metaclass_name = $metaclass->name; | 
| 3318 |  |  |  |  |  |  |  | 
| 3319 | 0 |  |  |  |  | 0 | my $buildall      = $class->_generate_BUILDALL($metaclass); | 
| 3320 | 0 |  |  |  |  | 0 | my $buildargs     = $class->_generate_BUILDARGS($metaclass); | 
| 3321 | 0 |  | 0 |  |  | 0 | my $initializer   = $metaclass->{_mouse_cache}{_initialize_object} ||= | 
| 3322 |  |  |  |  |  |  | $class->_generate_initialize_object($metaclass); | 
| 3323 | 0 |  |  |  |  | 0 | my $source = sprintf(<<'EOT', __FILE__, $metaclass->name, $buildargs, $buildall); | 
| 3324 |  |  |  |  |  |  | #line 1 "%s" | 
| 3325 |  |  |  |  |  |  | package %s; | 
| 3326 |  |  |  |  |  |  | sub { | 
| 3327 |  |  |  |  |  |  | my $class = shift; | 
| 3328 |  |  |  |  |  |  | return $class->Mousse::Object::new(@_) | 
| 3329 |  |  |  |  |  |  | if $class ne __PACKAGE__; | 
| 3330 |  |  |  |  |  |  | # BUILDARGS | 
| 3331 |  |  |  |  |  |  | %s; | 
| 3332 |  |  |  |  |  |  | my $instance = bless {}, $class; | 
| 3333 |  |  |  |  |  |  | $metaclass->$initializer($instance, $args, 0); | 
| 3334 |  |  |  |  |  |  | # BUILDALL | 
| 3335 |  |  |  |  |  |  | %s; | 
| 3336 |  |  |  |  |  |  | return $instance; | 
| 3337 |  |  |  |  |  |  | } | 
| 3338 |  |  |  |  |  |  | EOT | 
| 3339 | 0 |  |  |  |  | 0 | warn $source if _MOUSE_DEBUG; | 
| 3340 | 0 |  |  |  |  | 0 | my $body; | 
| 3341 | 0 |  |  |  |  | 0 | my $e = do{ | 
| 3342 | 0 |  |  |  |  | 0 | local $@; | 
| 3343 | 0 |  |  |  |  | 0 | $body = eval $source; | 
| 3344 | 0 |  |  |  |  | 0 | $@; | 
| 3345 |  |  |  |  |  |  | }; | 
| 3346 | 0 | 0 |  |  |  | 0 | die $e if $e; | 
| 3347 | 0 |  |  |  |  | 0 | return $body; | 
| 3348 |  |  |  |  |  |  | } | 
| 3349 |  |  |  |  |  |  |  | 
| 3350 |  |  |  |  |  |  | sub _generate_initialize_object { | 
| 3351 | 2 |  |  | 2 |  | 4 | my ($method_class, $metaclass) = @_; | 
| 3352 | 2 |  |  |  |  | 6 | my @attrs  = $metaclass->get_all_attributes; | 
| 3353 |  |  |  |  |  |  |  | 
| 3354 | 3 | 50 |  |  |  | 11 | my @checks = map { $_ && $_->_compiled_type_constraint } | 
|  | 3 |  |  |  |  | 6 |  | 
| 3355 | 2 |  |  |  |  | 6 | map { $_->type_constraint } @attrs; | 
| 3356 |  |  |  |  |  |  |  | 
| 3357 | 2 |  |  |  |  | 3 | my @res; | 
| 3358 |  |  |  |  |  |  |  | 
| 3359 |  |  |  |  |  |  | my $has_triggers; | 
| 3360 | 2 |  |  |  |  | 6 | my $strict = $metaclass->strict_constructor; | 
| 3361 |  |  |  |  |  |  |  | 
| 3362 | 2 | 50 |  |  |  | 6 | if($strict){ | 
| 3363 | 0 |  |  |  |  | 0 | push @res, 'my $used = 0;'; | 
| 3364 |  |  |  |  |  |  | } | 
| 3365 |  |  |  |  |  |  |  | 
| 3366 | 2 |  |  |  |  | 6 | for my $index (0 .. @attrs - 1) { | 
| 3367 | 3 |  |  |  |  | 4 | my $code = ''; | 
| 3368 |  |  |  |  |  |  |  | 
| 3369 | 3 |  |  |  |  | 5 | my $attr = $attrs[$index]; | 
| 3370 | 3 |  |  |  |  | 6 | my $key  = $attr->name; | 
| 3371 |  |  |  |  |  |  |  | 
| 3372 | 3 |  |  |  |  | 7 | my $init_arg        = $attr->init_arg; | 
| 3373 | 3 |  |  |  |  | 8 | my $type_constraint = $attr->type_constraint; | 
| 3374 | 3 |  |  |  |  | 7 | my $is_weak_ref     = $attr->is_weak_ref; | 
| 3375 | 3 |  |  |  |  | 4 | my $need_coercion; | 
| 3376 |  |  |  |  |  |  |  | 
| 3377 | 3 |  |  |  |  | 9 | my $instance_slot  = $method_class->_inline_slot('$instance', $key); | 
| 3378 | 3 |  |  |  |  | 8 | my $attr_var       = "\$attrs[$index]"; | 
| 3379 | 3 |  |  |  |  | 3 | my $constraint_var; | 
| 3380 |  |  |  |  |  |  |  | 
| 3381 | 3 | 50 |  |  |  | 9 | if(defined $type_constraint){ | 
| 3382 | 0 |  |  |  |  | 0 | $constraint_var = "$attr_var\->{type_constraint}"; | 
| 3383 | 0 |  | 0 |  |  | 0 | $need_coercion  = ($attr->should_coerce && $type_constraint->has_coercion); | 
| 3384 |  |  |  |  |  |  | } | 
| 3385 |  |  |  |  |  |  |  | 
| 3386 | 3 |  |  |  |  | 6 | $code .= "# initialize $key\n"; | 
| 3387 |  |  |  |  |  |  |  | 
| 3388 | 3 |  |  |  |  | 5 | my $post_process = ''; | 
| 3389 | 3 | 50 |  |  |  | 7 | if(defined $type_constraint){ | 
| 3390 | 0 |  |  |  |  | 0 | $post_process .= "\$checks[$index]->($instance_slot)\n"; | 
| 3391 | 0 |  |  |  |  | 0 | $post_process .= "  or $attr_var->_throw_type_constraint_error($instance_slot, $constraint_var);\n"; | 
| 3392 |  |  |  |  |  |  | } | 
| 3393 |  |  |  |  |  |  |  | 
| 3394 |  |  |  |  |  |  | # build cde for an attribute | 
| 3395 | 3 | 50 |  |  |  | 8 | if (defined $init_arg) { | 
| 3396 | 3 |  |  |  |  | 5 | my $value = "\$args->{q{$init_arg}}"; | 
| 3397 |  |  |  |  |  |  |  | 
| 3398 | 3 |  |  |  |  | 8 | $code .= "if (exists $value) {\n"; | 
| 3399 |  |  |  |  |  |  |  | 
| 3400 | 3 | 50 |  |  |  | 8 | if($need_coercion){ | 
| 3401 | 0 |  |  |  |  | 0 | $value = "$constraint_var->coerce($value)"; | 
| 3402 |  |  |  |  |  |  | } | 
| 3403 |  |  |  |  |  |  |  | 
| 3404 | 3 |  |  |  |  | 6 | $code .= "$instance_slot = $value;\n"; | 
| 3405 | 3 |  |  |  |  | 4 | $code .= $post_process; | 
| 3406 |  |  |  |  |  |  |  | 
| 3407 | 3 | 50 |  |  |  | 10 | if ($attr->has_trigger) { | 
| 3408 | 0 |  |  |  |  | 0 | $has_triggers++; | 
| 3409 | 0 |  |  |  |  | 0 | $code .= "push \@triggers, [$attr_var\->{trigger}, $instance_slot];\n"; | 
| 3410 |  |  |  |  |  |  | } | 
| 3411 |  |  |  |  |  |  |  | 
| 3412 | 3 | 50 |  |  |  | 7 | if ($strict){ | 
| 3413 | 0 |  |  |  |  | 0 | $code .= '++$used;' . "\n"; | 
| 3414 |  |  |  |  |  |  | } | 
| 3415 |  |  |  |  |  |  |  | 
| 3416 | 3 |  |  |  |  | 5 | $code .= "\n} else {\n"; # $value exists | 
| 3417 |  |  |  |  |  |  | } | 
| 3418 |  |  |  |  |  |  |  | 
| 3419 | 3 | 50 | 33 |  |  | 9 | if ($attr->has_default || $attr->has_builder) { | 
|  |  | 50 |  |  |  |  |  | 
| 3420 | 0 | 0 |  |  |  | 0 | unless ($attr->is_lazy) { | 
| 3421 | 0 |  |  |  |  | 0 | my $default = $attr->default; | 
| 3422 | 0 |  |  |  |  | 0 | my $builder = $attr->builder; | 
| 3423 |  |  |  |  |  |  |  | 
| 3424 | 0 |  |  |  |  | 0 | my $value; | 
| 3425 | 0 | 0 |  |  |  | 0 | if (defined($builder)) { | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 3426 | 0 |  |  |  |  | 0 | $value = "\$instance->$builder()"; | 
| 3427 |  |  |  |  |  |  | } | 
| 3428 |  |  |  |  |  |  | elsif (ref($default) eq 'CODE') { | 
| 3429 | 0 |  |  |  |  | 0 | $value = "$attr_var\->{default}->(\$instance)"; | 
| 3430 |  |  |  |  |  |  | } | 
| 3431 |  |  |  |  |  |  | elsif (defined($default)) { | 
| 3432 | 0 |  |  |  |  | 0 | $value = "$attr_var\->{default}"; | 
| 3433 |  |  |  |  |  |  | } | 
| 3434 |  |  |  |  |  |  | else { | 
| 3435 | 0 |  |  |  |  | 0 | $value = 'undef'; | 
| 3436 |  |  |  |  |  |  | } | 
| 3437 |  |  |  |  |  |  |  | 
| 3438 | 0 | 0 |  |  |  | 0 | if($need_coercion){ | 
| 3439 | 0 |  |  |  |  | 0 | $value = "$constraint_var->coerce($value)"; | 
| 3440 |  |  |  |  |  |  | } | 
| 3441 |  |  |  |  |  |  |  | 
| 3442 | 0 |  |  |  |  | 0 | $code .= "$instance_slot = $value;\n"; | 
| 3443 | 0 |  |  |  |  | 0 | $code .= $post_process; | 
| 3444 |  |  |  |  |  |  | } | 
| 3445 |  |  |  |  |  |  | } | 
| 3446 |  |  |  |  |  |  | elsif ($attr->is_required) { | 
| 3447 | 0 |  |  |  |  | 0 | $code .= "\$meta->throw_error('Attribute ($key) is required')"; | 
| 3448 | 0 |  |  |  |  | 0 | $code .= "    unless \$is_cloning;\n"; | 
| 3449 |  |  |  |  |  |  | } | 
| 3450 |  |  |  |  |  |  |  | 
| 3451 | 3 | 50 |  |  |  | 8 | $code .= "}\n" if defined $init_arg; | 
| 3452 |  |  |  |  |  |  |  | 
| 3453 | 3 | 50 |  |  |  | 6 | if($is_weak_ref){ | 
| 3454 | 0 |  |  |  |  | 0 | $code .= "Scalar::Util::weaken($instance_slot) " | 
| 3455 |  |  |  |  |  |  | . "if ref $instance_slot;\n"; | 
| 3456 |  |  |  |  |  |  | } | 
| 3457 |  |  |  |  |  |  |  | 
| 3458 | 3 |  |  |  |  | 10 | push @res, $code; | 
| 3459 |  |  |  |  |  |  | } | 
| 3460 |  |  |  |  |  |  |  | 
| 3461 | 2 | 50 |  |  |  | 7 | if($strict){ | 
| 3462 | 0 |  |  |  |  | 0 | push @res, q{if($used < keys %{$args})} | 
| 3463 |  |  |  |  |  |  | . q{{ $meta->_report_unknown_args(\@attrs, $args) }}; | 
| 3464 |  |  |  |  |  |  | } | 
| 3465 |  |  |  |  |  |  |  | 
| 3466 | 2 | 50 |  |  |  | 6 | if($metaclass->is_anon_class){ | 
| 3467 | 0 |  |  |  |  | 0 | push @res, q{$instance->{__METACLASS__} = $meta;}; | 
| 3468 |  |  |  |  |  |  | } | 
| 3469 |  |  |  |  |  |  |  | 
| 3470 | 2 | 50 |  |  |  | 6 | if($has_triggers){ | 
| 3471 | 0 |  |  |  |  | 0 | unshift @res, q{my @triggers;}; | 
| 3472 | 0 |  |  |  |  | 0 | push    @res, q{$_->[0]->($instance, $_->[1]) for @triggers;}; | 
| 3473 |  |  |  |  |  |  | } | 
| 3474 |  |  |  |  |  |  |  | 
| 3475 | 2 |  |  |  |  | 12 | my $source = sprintf <<'EOT', __FILE__, $metaclass->name, join "\n", @res; | 
| 3476 |  |  |  |  |  |  | #line 1 "%s" | 
| 3477 |  |  |  |  |  |  | package %s; | 
| 3478 |  |  |  |  |  |  | sub { | 
| 3479 |  |  |  |  |  |  | my($meta, $instance, $args, $is_cloning) = @_; | 
| 3480 |  |  |  |  |  |  | %s; | 
| 3481 |  |  |  |  |  |  | return $instance; | 
| 3482 |  |  |  |  |  |  | } | 
| 3483 |  |  |  |  |  |  | EOT | 
| 3484 | 2 |  |  |  |  | 3 | warn $source if _MOUSE_DEBUG; | 
| 3485 | 2 |  |  |  |  | 4 | my $body; | 
| 3486 | 2 |  |  |  |  | 2 | my $e = do { | 
| 3487 | 2 |  |  |  |  | 3 | local $@; | 
| 3488 | 2 |  |  |  |  | 280 | $body = eval $source; | 
| 3489 | 2 |  |  |  |  | 7 | $@; | 
| 3490 |  |  |  |  |  |  | }; | 
| 3491 | 2 | 50 |  |  |  | 6 | die $e if $e; | 
| 3492 | 2 |  |  |  |  | 12 | return $body; | 
| 3493 |  |  |  |  |  |  | } | 
| 3494 |  |  |  |  |  |  |  | 
| 3495 |  |  |  |  |  |  | sub _generate_BUILDARGS { | 
| 3496 | 0 |  |  | 0 |  | 0 | my(undef, $metaclass) = @_; | 
| 3497 |  |  |  |  |  |  |  | 
| 3498 | 0 |  |  |  |  | 0 | my $class = $metaclass->name; | 
| 3499 | 0 | 0 | 0 |  |  | 0 | if ( $class->can('BUILDARGS') && $class->can('BUILDARGS') != \&Mousse::Object::BUILDARGS ) { | 
| 3500 | 0 |  |  |  |  | 0 | return 'my $args = $class->BUILDARGS(@_)'; | 
| 3501 |  |  |  |  |  |  | } | 
| 3502 |  |  |  |  |  |  |  | 
| 3503 | 0 |  |  |  |  | 0 | return <<'...'; | 
| 3504 |  |  |  |  |  |  | my $args; | 
| 3505 |  |  |  |  |  |  | if ( scalar @_ == 1 ) { | 
| 3506 |  |  |  |  |  |  | ( ref( $_[0] ) eq 'HASH' ) | 
| 3507 |  |  |  |  |  |  | || Carp::confess "Single parameters to new() must be a HASH ref"; | 
| 3508 |  |  |  |  |  |  | $args = +{ %{ $_[0] } }; | 
| 3509 |  |  |  |  |  |  | } | 
| 3510 |  |  |  |  |  |  | else { | 
| 3511 |  |  |  |  |  |  | $args = +{@_}; | 
| 3512 |  |  |  |  |  |  | } | 
| 3513 |  |  |  |  |  |  | ... | 
| 3514 |  |  |  |  |  |  | } | 
| 3515 |  |  |  |  |  |  |  | 
| 3516 |  |  |  |  |  |  | sub _generate_BUILDALL { | 
| 3517 | 0 |  |  | 0 |  | 0 | my (undef, $metaclass) = @_; | 
| 3518 |  |  |  |  |  |  |  | 
| 3519 | 0 | 0 |  |  |  | 0 | return '' unless $metaclass->name->can('BUILD'); | 
| 3520 |  |  |  |  |  |  |  | 
| 3521 | 0 |  |  |  |  | 0 | my @code; | 
| 3522 | 0 |  |  |  |  | 0 | for my $class ($metaclass->linearized_isa) { | 
| 3523 | 0 | 0 |  |  |  | 0 | if (Mousse::Util::get_code_ref($class, 'BUILD')) { | 
| 3524 | 0 |  |  |  |  | 0 | unshift  @code, qq{${class}::BUILD(\$instance, \$args);}; | 
| 3525 |  |  |  |  |  |  | } | 
| 3526 |  |  |  |  |  |  | } | 
| 3527 | 0 |  |  |  |  | 0 | return join "\n", @code; | 
| 3528 |  |  |  |  |  |  | } | 
| 3529 |  |  |  |  |  |  |  | 
| 3530 |  |  |  |  |  |  | # Contents of Mouse::Meta::Method::Delegation | 
| 3531 |  |  |  |  |  |  | package Mousse::Meta::Method::Delegation; | 
| 3532 | 1 |  |  | 1 |  | 6 | use Mousse::Util qw(:meta); # enables strict and warnings | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 5 |  | 
| 3533 | 1 |  |  | 1 |  | 5 | use Scalar::Util; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 505 |  | 
| 3534 |  |  |  |  |  |  |  | 
| 3535 |  |  |  |  |  |  | sub _generate_delegation{ | 
| 3536 | 0 |  |  | 0 |  | 0 | my (undef, $attr, $handle_name, $method_to_call) = @_; | 
| 3537 |  |  |  |  |  |  |  | 
| 3538 | 0 |  |  |  |  | 0 | my @curried_args; | 
| 3539 | 0 | 0 |  |  |  | 0 | if(ref($method_to_call) eq 'ARRAY'){ | 
| 3540 | 0 |  |  |  |  | 0 | ($method_to_call, @curried_args) = @{$method_to_call}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 3541 |  |  |  |  |  |  | } | 
| 3542 |  |  |  |  |  |  |  | 
| 3543 |  |  |  |  |  |  | # If it has a reader, we must use it to make method modifiers work | 
| 3544 | 0 |  | 0 |  |  | 0 | my $reader = $attr->get_read_method() || $attr->get_read_method_ref(); | 
| 3545 |  |  |  |  |  |  |  | 
| 3546 | 0 |  |  |  |  | 0 | my $can_be_optimized = $attr->{_mouse_cache_method_delegation_can_be_optimized}; | 
| 3547 |  |  |  |  |  |  |  | 
| 3548 | 0 | 0 |  |  |  | 0 | if(!defined $can_be_optimized){ | 
| 3549 | 0 |  |  |  |  | 0 | my $tc = $attr->type_constraint; | 
| 3550 | 0 |  | 0 |  |  | 0 | $attr->{_mouse_cache_method_delegation_can_be_optimized} = | 
| 3551 |  |  |  |  |  |  | (defined($tc) && $tc->is_a_type_of('Object')) | 
| 3552 |  |  |  |  |  |  | && ($attr->is_required || $attr->has_default || $attr->has_builder) | 
| 3553 |  |  |  |  |  |  | && ($attr->is_lazy || !$attr->has_clearer); | 
| 3554 |  |  |  |  |  |  | } | 
| 3555 |  |  |  |  |  |  |  | 
| 3556 | 0 | 0 |  |  |  | 0 | if($can_be_optimized){ | 
| 3557 |  |  |  |  |  |  | # need not check the attribute value | 
| 3558 |  |  |  |  |  |  | return sub { | 
| 3559 | 0 |  |  | 0 |  | 0 | return shift()->$reader()->$method_to_call(@curried_args, @_); | 
| 3560 | 0 |  |  |  |  | 0 | }; | 
| 3561 |  |  |  |  |  |  | } | 
| 3562 |  |  |  |  |  |  | else { | 
| 3563 |  |  |  |  |  |  | # need to check the attribute value | 
| 3564 |  |  |  |  |  |  | return sub { | 
| 3565 | 0 |  |  | 0 |  | 0 | my $instance = shift; | 
| 3566 | 0 |  |  |  |  | 0 | my $proxy    = $instance->$reader(); | 
| 3567 |  |  |  |  |  |  |  | 
| 3568 | 0 | 0 | 0 |  |  | 0 | my $error = !defined($proxy)                              ? ' is not defined' | 
|  |  | 0 |  |  |  |  |  | 
| 3569 |  |  |  |  |  |  | : ref($proxy) && !Scalar::Util::blessed($proxy) ? qq{ is not an object (got '$proxy')} | 
| 3570 |  |  |  |  |  |  | : undef; | 
| 3571 | 0 | 0 |  |  |  | 0 | if ($error) { | 
| 3572 | 0 |  |  |  |  | 0 | $instance->meta->throw_error( | 
| 3573 |  |  |  |  |  |  | "Cannot delegate $handle_name to $method_to_call because " | 
| 3574 |  |  |  |  |  |  | . "the value of " | 
| 3575 |  |  |  |  |  |  | . $attr->name | 
| 3576 |  |  |  |  |  |  | . $error | 
| 3577 |  |  |  |  |  |  | ); | 
| 3578 |  |  |  |  |  |  | } | 
| 3579 | 0 |  |  |  |  | 0 | $proxy->$method_to_call(@curried_args, @_); | 
| 3580 | 0 |  |  |  |  | 0 | }; | 
| 3581 |  |  |  |  |  |  | } | 
| 3582 |  |  |  |  |  |  | } | 
| 3583 |  |  |  |  |  |  |  | 
| 3584 |  |  |  |  |  |  |  | 
| 3585 |  |  |  |  |  |  | # Contents of Mouse::Meta::Method::Destructor | 
| 3586 |  |  |  |  |  |  | package Mousse::Meta::Method::Destructor; | 
| 3587 | 1 |  |  | 1 |  | 9 | use Mousse::Util qw(:meta); # enables strict and warnings | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 3 |  | 
| 3588 |  |  |  |  |  |  |  | 
| 3589 | 1 | 50 |  | 1 |  | 5 | use constant _MOUSE_DEBUG => $ENV{MOUSE_DEBUG} ? 1 : 0; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 283 |  | 
| 3590 |  |  |  |  |  |  |  | 
| 3591 |  |  |  |  |  |  | sub _generate_destructor{ | 
| 3592 | 0 |  |  | 0 |  | 0 | my (undef, $metaclass) = @_; | 
| 3593 |  |  |  |  |  |  |  | 
| 3594 | 0 |  |  |  |  | 0 | my $demolishall = ''; | 
| 3595 | 0 |  |  |  |  | 0 | for my $class ($metaclass->linearized_isa) { | 
| 3596 | 0 | 0 |  |  |  | 0 | if (Mousse::Util::get_code_ref($class, 'DEMOLISH')) { | 
| 3597 | 0 |  |  |  |  | 0 | $demolishall .= '                ' . $class | 
| 3598 |  |  |  |  |  |  | . '::DEMOLISH($self, $Mousse::Util::in_global_destruction);' | 
| 3599 |  |  |  |  |  |  | . "\n", | 
| 3600 |  |  |  |  |  |  | } | 
| 3601 |  |  |  |  |  |  | } | 
| 3602 |  |  |  |  |  |  |  | 
| 3603 | 0 | 0 |  |  |  | 0 | if($demolishall) { | 
| 3604 | 0 |  |  |  |  | 0 | $demolishall = sprintf <<'EOT', $demolishall; | 
| 3605 |  |  |  |  |  |  | my $e = do{ | 
| 3606 |  |  |  |  |  |  | local $?; | 
| 3607 |  |  |  |  |  |  | local $@; | 
| 3608 |  |  |  |  |  |  | eval{ | 
| 3609 |  |  |  |  |  |  | %s; | 
| 3610 |  |  |  |  |  |  | }; | 
| 3611 |  |  |  |  |  |  | $@; | 
| 3612 |  |  |  |  |  |  | }; | 
| 3613 |  |  |  |  |  |  | no warnings 'misc'; | 
| 3614 |  |  |  |  |  |  | die $e if $e; # rethrow | 
| 3615 |  |  |  |  |  |  | EOT | 
| 3616 |  |  |  |  |  |  | } | 
| 3617 |  |  |  |  |  |  |  | 
| 3618 | 0 |  |  |  |  | 0 | my $name   = $metaclass->name; | 
| 3619 | 0 |  |  |  |  | 0 | my $source = sprintf(<<'EOT', __FILE__, $name, $demolishall); | 
| 3620 |  |  |  |  |  |  | #line 1 "%s" | 
| 3621 |  |  |  |  |  |  | package %s; | 
| 3622 |  |  |  |  |  |  | sub { | 
| 3623 |  |  |  |  |  |  | my($self) = @_; | 
| 3624 |  |  |  |  |  |  | return $self->Mousse::Object::DESTROY() | 
| 3625 |  |  |  |  |  |  | if ref($self) ne __PACKAGE__; | 
| 3626 |  |  |  |  |  |  | # DEMOLISHALL | 
| 3627 |  |  |  |  |  |  | %s; | 
| 3628 |  |  |  |  |  |  | return; | 
| 3629 |  |  |  |  |  |  | } | 
| 3630 |  |  |  |  |  |  | EOT | 
| 3631 |  |  |  |  |  |  |  | 
| 3632 | 0 |  |  |  |  | 0 | warn $source if _MOUSE_DEBUG; | 
| 3633 |  |  |  |  |  |  |  | 
| 3634 | 0 |  |  |  |  | 0 | my $code; | 
| 3635 | 0 |  |  |  |  | 0 | my $e = do{ | 
| 3636 | 0 |  |  |  |  | 0 | local $@; | 
| 3637 | 0 |  |  |  |  | 0 | $code = eval $source; | 
| 3638 | 0 |  |  |  |  | 0 | $@; | 
| 3639 |  |  |  |  |  |  | }; | 
| 3640 | 0 | 0 |  |  |  | 0 | die $e if $e; | 
| 3641 | 0 |  |  |  |  | 0 | return $code; | 
| 3642 |  |  |  |  |  |  | } | 
| 3643 |  |  |  |  |  |  |  | 
| 3644 |  |  |  |  |  |  | # Contents of Mouse::Meta::Module | 
| 3645 |  |  |  |  |  |  | package Mousse::Meta::Module; | 
| 3646 | 1 |  |  | 1 |  | 5 | use Mousse::Util qw/:meta/; # enables strict and warnings | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 3 |  | 
| 3647 | 1 |  |  | 1 |  | 5 | no warnings 'once'; | 
|  | 1 |  |  |  |  | 8 |  | 
|  | 1 |  |  |  |  | 40 |  | 
| 3648 |  |  |  |  |  |  |  | 
| 3649 | 1 |  |  | 1 |  | 4 | use Carp         (); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 20 |  | 
| 3650 | 1 |  |  | 1 |  | 4 | use Scalar::Util (); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 1625 |  | 
| 3651 |  |  |  |  |  |  |  | 
| 3652 |  |  |  |  |  |  | my %METAS; | 
| 3653 |  |  |  |  |  |  |  | 
| 3654 |  |  |  |  |  |  | if(Mousse::Util::MOUSE_XS){ | 
| 3655 |  |  |  |  |  |  | # register meta storage for performance | 
| 3656 |  |  |  |  |  |  | Mousse::Util::__register_metaclass_storage(\%METAS, 0); | 
| 3657 |  |  |  |  |  |  |  | 
| 3658 |  |  |  |  |  |  | # ensure thread safety | 
| 3659 |  |  |  |  |  |  | *CLONE = sub { Mousse::Util::__register_metaclass_storage(\%METAS, 1) }; | 
| 3660 |  |  |  |  |  |  | } | 
| 3661 |  |  |  |  |  |  |  | 
| 3662 |  |  |  |  |  |  | sub initialize { | 
| 3663 | 7 |  |  | 7 | 0 | 14 | my($class, $package_name, @args) = @_; | 
| 3664 |  |  |  |  |  |  |  | 
| 3665 | 7 | 50 | 33 |  |  | 44 | ($package_name && !ref($package_name)) | 
| 3666 |  |  |  |  |  |  | || $class->throw_error("You must pass a package name and it cannot be blessed"); | 
| 3667 |  |  |  |  |  |  |  | 
| 3668 | 7 |  | 66 |  |  | 47 | return $METAS{$package_name} | 
| 3669 |  |  |  |  |  |  | ||= $class->_construct_meta(package => $package_name, @args); | 
| 3670 |  |  |  |  |  |  | } | 
| 3671 |  |  |  |  |  |  |  | 
| 3672 |  |  |  |  |  |  | sub reinitialize { | 
| 3673 | 0 |  |  | 0 | 0 | 0 | my($class, $package_name, @args) = @_; | 
| 3674 |  |  |  |  |  |  |  | 
| 3675 | 0 | 0 |  |  |  | 0 | $package_name = $package_name->name if ref $package_name; | 
| 3676 |  |  |  |  |  |  |  | 
| 3677 | 0 | 0 | 0 |  |  | 0 | ($package_name && !ref($package_name)) | 
| 3678 |  |  |  |  |  |  | || $class->throw_error("You must pass a package name and it cannot be blessed"); | 
| 3679 |  |  |  |  |  |  |  | 
| 3680 | 0 | 0 |  |  |  | 0 | if(exists $METAS{$package_name}) { | 
| 3681 | 0 |  |  |  |  | 0 | unshift @args, %{ $METAS{$package_name} }; | 
|  | 0 |  |  |  |  | 0 |  | 
| 3682 |  |  |  |  |  |  | } | 
| 3683 | 0 |  |  |  |  | 0 | delete $METAS{$package_name}; | 
| 3684 | 0 |  |  |  |  | 0 | return $class->initialize($package_name, @args); | 
| 3685 |  |  |  |  |  |  | } | 
| 3686 |  |  |  |  |  |  |  | 
| 3687 |  |  |  |  |  |  | sub _class_of{ | 
| 3688 | 0 |  |  | 0 |  | 0 | my($class_or_instance) = @_; | 
| 3689 | 0 | 0 |  |  |  | 0 | return undef unless defined $class_or_instance; | 
| 3690 | 0 |  | 0 |  |  | 0 | return $METAS{ ref($class_or_instance) || $class_or_instance }; | 
| 3691 |  |  |  |  |  |  | } | 
| 3692 |  |  |  |  |  |  |  | 
| 3693 |  |  |  |  |  |  | # Means of accessing all the metaclasses that have | 
| 3694 |  |  |  |  |  |  | # been initialized thus far. | 
| 3695 |  |  |  |  |  |  | # The public versions are aliased into Mousse::Util::*. | 
| 3696 |  |  |  |  |  |  | #sub _get_all_metaclasses         {        %METAS         } | 
| 3697 | 0 |  |  | 0 |  | 0 | sub _get_all_metaclass_instances { values %METAS         } | 
| 3698 | 0 |  |  | 0 |  | 0 | sub _get_all_metaclass_names     { keys   %METAS         } | 
| 3699 | 13 |  |  | 13 |  | 51 | sub _get_metaclass_by_name       { $METAS{$_[0]}         } | 
| 3700 |  |  |  |  |  |  | #sub _store_metaclass_by_name     { $METAS{$_[0]} = $_[1] } | 
| 3701 |  |  |  |  |  |  | #sub _weaken_metaclass            { weaken($METAS{$_[0]}) } | 
| 3702 |  |  |  |  |  |  | #sub _does_metaclass_exist        { defined $METAS{$_[0]} } | 
| 3703 |  |  |  |  |  |  | #sub _remove_metaclass_by_name    { delete $METAS{$_[0]}  } | 
| 3704 |  |  |  |  |  |  |  | 
| 3705 |  |  |  |  |  |  | sub name; | 
| 3706 |  |  |  |  |  |  |  | 
| 3707 |  |  |  |  |  |  | sub namespace; | 
| 3708 |  |  |  |  |  |  |  | 
| 3709 |  |  |  |  |  |  | # add_attribute is an abstract method | 
| 3710 |  |  |  |  |  |  |  | 
| 3711 |  |  |  |  |  |  | sub get_attribute_map { # DEPRECATED | 
| 3712 | 0 |  |  | 0 | 0 |  | Carp::cluck('get_attribute_map() has been deprecated. Use get_attribute_list() and get_attribute() instead'); | 
| 3713 | 0 |  |  |  |  |  | return $_[0]->{attributes}; | 
| 3714 |  |  |  |  |  |  | } | 
| 3715 |  |  |  |  |  |  |  | 
| 3716 | 0 |  |  | 0 | 0 |  | sub has_attribute     { exists $_[0]->{attributes}->{$_[1]} } | 
| 3717 | 0 |  |  | 0 | 0 |  | sub get_attribute     {        $_[0]->{attributes}->{$_[1]} } | 
| 3718 | 0 |  |  | 0 | 0 |  | sub remove_attribute  { delete $_[0]->{attributes}->{$_[1]} } | 
| 3719 |  |  |  |  |  |  |  | 
| 3720 | 0 |  |  | 0 | 0 |  | sub get_attribute_list{ keys   %{$_[0]->{attributes}} } | 
|  | 0 |  |  |  |  |  |  | 
| 3721 |  |  |  |  |  |  |  | 
| 3722 |  |  |  |  |  |  | # XXX: not completely compatible with Moose | 
| 3723 |  |  |  |  |  |  | my %foreign = map{ $_ => undef } qw( | 
| 3724 |  |  |  |  |  |  | Mousse Mousse::Role Mousse::Util Mousse::Util::TypeConstraints | 
| 3725 |  |  |  |  |  |  | Carp Scalar::Util List::Util | 
| 3726 |  |  |  |  |  |  | ); | 
| 3727 |  |  |  |  |  |  | sub _get_method_body { | 
| 3728 | 0 |  |  | 0 |  |  | my($self, $method_name) = @_; | 
| 3729 | 0 |  |  |  |  |  | my $code = Mousse::Util::get_code_ref($self->{package}, $method_name); | 
| 3730 | 0 | 0 | 0 |  |  |  | return $code && !exists $foreign{ Mousse::Util::get_code_package($code) } | 
| 3731 |  |  |  |  |  |  | ? $code | 
| 3732 |  |  |  |  |  |  | : undef; | 
| 3733 |  |  |  |  |  |  | } | 
| 3734 |  |  |  |  |  |  |  | 
| 3735 |  |  |  |  |  |  | sub add_method; | 
| 3736 |  |  |  |  |  |  |  | 
| 3737 |  |  |  |  |  |  | sub has_method { | 
| 3738 | 0 |  |  | 0 | 0 |  | my($self, $method_name) = @_; | 
| 3739 | 0 | 0 |  |  |  |  | defined($method_name) | 
| 3740 |  |  |  |  |  |  | or $self->throw_error('You must define a method name'); | 
| 3741 |  |  |  |  |  |  |  | 
| 3742 | 0 |  | 0 |  |  |  | return defined( $self->{methods}{$method_name} ) | 
| 3743 |  |  |  |  |  |  | || defined( $self->_get_method_body($method_name) ); | 
| 3744 |  |  |  |  |  |  | } | 
| 3745 |  |  |  |  |  |  |  | 
| 3746 |  |  |  |  |  |  | sub get_method_body { | 
| 3747 | 0 |  |  | 0 | 0 |  | my($self, $method_name) = @_; | 
| 3748 | 0 | 0 |  |  |  |  | defined($method_name) | 
| 3749 |  |  |  |  |  |  | or $self->throw_error('You must define a method name'); | 
| 3750 |  |  |  |  |  |  |  | 
| 3751 | 0 |  | 0 |  |  |  | return $self->{methods}{$method_name} | 
| 3752 |  |  |  |  |  |  | ||= $self->_get_method_body($method_name); | 
| 3753 |  |  |  |  |  |  | } | 
| 3754 |  |  |  |  |  |  |  | 
| 3755 |  |  |  |  |  |  | sub get_method { | 
| 3756 | 0 |  |  | 0 | 0 |  | my($self, $method_name) = @_; | 
| 3757 |  |  |  |  |  |  |  | 
| 3758 | 0 | 0 |  |  |  |  | if(my $code = $self->get_method_body($method_name)){ | 
| 3759 | 0 |  |  |  |  |  | return Mousse::Util::load_class($self->method_metaclass)->wrap( | 
| 3760 |  |  |  |  |  |  | body                 => $code, | 
| 3761 |  |  |  |  |  |  | name                 => $method_name, | 
| 3762 |  |  |  |  |  |  | package              => $self->name, | 
| 3763 |  |  |  |  |  |  | associated_metaclass => $self, | 
| 3764 |  |  |  |  |  |  | ); | 
| 3765 |  |  |  |  |  |  | } | 
| 3766 |  |  |  |  |  |  |  | 
| 3767 | 0 |  |  |  |  |  | return undef; | 
| 3768 |  |  |  |  |  |  | } | 
| 3769 |  |  |  |  |  |  |  | 
| 3770 |  |  |  |  |  |  | sub get_method_list { | 
| 3771 | 0 |  |  | 0 | 0 |  | my($self) = @_; | 
| 3772 |  |  |  |  |  |  |  | 
| 3773 | 0 |  |  |  |  |  | return grep { $self->has_method($_) } keys %{ $self->namespace }; | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 3774 |  |  |  |  |  |  | } | 
| 3775 |  |  |  |  |  |  |  | 
| 3776 |  |  |  |  |  |  | sub _collect_methods { # Mousse specific, used for method modifiers | 
| 3777 | 0 |  |  | 0 |  |  | my($meta, @args) = @_; | 
| 3778 |  |  |  |  |  |  |  | 
| 3779 | 0 |  |  |  |  |  | my @methods; | 
| 3780 | 0 |  |  |  |  |  | foreach my $arg(@args){ | 
| 3781 | 0 | 0 |  |  |  |  | if(my $type = ref $arg){ | 
| 3782 | 0 | 0 |  |  |  |  | if($type eq 'Regexp'){ | 
|  |  | 0 |  |  |  |  |  | 
| 3783 | 0 |  |  |  |  |  | push @methods, grep { $_ =~ $arg } $meta->get_all_method_names; | 
|  | 0 |  |  |  |  |  |  | 
| 3784 |  |  |  |  |  |  | } | 
| 3785 |  |  |  |  |  |  | elsif($type eq 'ARRAY'){ | 
| 3786 | 0 |  |  |  |  |  | push @methods, @{$arg}; | 
|  | 0 |  |  |  |  |  |  | 
| 3787 |  |  |  |  |  |  | } | 
| 3788 |  |  |  |  |  |  | else{ | 
| 3789 | 0 |  |  |  |  |  | my $subname = ( caller(1) )[3]; | 
| 3790 | 0 |  |  |  |  |  | $meta->throw_error( | 
| 3791 |  |  |  |  |  |  | sprintf( | 
| 3792 |  |  |  |  |  |  | 'Methods passed to %s must be provided as a list,' | 
| 3793 |  |  |  |  |  |  | . ' ArrayRef or regular expression, not %s', | 
| 3794 |  |  |  |  |  |  | $subname, | 
| 3795 |  |  |  |  |  |  | $type, | 
| 3796 |  |  |  |  |  |  | ) | 
| 3797 |  |  |  |  |  |  | ); | 
| 3798 |  |  |  |  |  |  | } | 
| 3799 |  |  |  |  |  |  | } | 
| 3800 |  |  |  |  |  |  | else{ | 
| 3801 | 0 |  |  |  |  |  | push @methods, $arg; | 
| 3802 |  |  |  |  |  |  | } | 
| 3803 |  |  |  |  |  |  | } | 
| 3804 | 0 |  |  |  |  |  | return @methods; | 
| 3805 |  |  |  |  |  |  | } | 
| 3806 |  |  |  |  |  |  |  | 
| 3807 |  |  |  |  |  |  | my $ANON_SERIAL = 0;  # anonymous class/role id | 
| 3808 |  |  |  |  |  |  | my %IMMORTALS;        # immortal anonymous classes | 
| 3809 |  |  |  |  |  |  |  | 
| 3810 |  |  |  |  |  |  | sub create { | 
| 3811 | 0 |  |  | 0 | 0 |  | my($self, $package_name, %options) = @_; | 
| 3812 |  |  |  |  |  |  |  | 
| 3813 | 0 |  | 0 |  |  |  | my $class = ref($self) || $self; | 
| 3814 | 0 | 0 |  |  |  |  | $self->throw_error('You must pass a package name') if @_ < 2; | 
| 3815 |  |  |  |  |  |  |  | 
| 3816 | 0 |  |  |  |  |  | my $superclasses; | 
| 3817 | 0 | 0 |  |  |  |  | if(exists $options{superclasses}){ | 
| 3818 | 0 | 0 |  |  |  |  | if(Mousse::Util::is_a_metarole($self)){ | 
| 3819 | 0 |  |  |  |  |  | delete $options{superclasses}; | 
| 3820 |  |  |  |  |  |  | } | 
| 3821 |  |  |  |  |  |  | else{ | 
| 3822 | 0 |  |  |  |  |  | $superclasses = delete $options{superclasses}; | 
| 3823 | 0 | 0 |  |  |  |  | (ref $superclasses eq 'ARRAY') | 
| 3824 |  |  |  |  |  |  | || $self->throw_error("You must pass an ARRAY ref of superclasses"); | 
| 3825 |  |  |  |  |  |  | } | 
| 3826 |  |  |  |  |  |  | } | 
| 3827 |  |  |  |  |  |  |  | 
| 3828 | 0 |  |  |  |  |  | my $attributes = delete $options{attributes}; | 
| 3829 | 0 | 0 |  |  |  |  | if(defined $attributes){ | 
| 3830 | 0 | 0 | 0 |  |  |  | (ref $attributes eq 'ARRAY' || ref $attributes eq 'HASH') | 
| 3831 |  |  |  |  |  |  | || $self->throw_error("You must pass an ARRAY ref of attributes"); | 
| 3832 |  |  |  |  |  |  | } | 
| 3833 | 0 |  |  |  |  |  | my $methods = delete $options{methods}; | 
| 3834 | 0 | 0 |  |  |  |  | if(defined $methods){ | 
| 3835 | 0 | 0 |  |  |  |  | (ref $methods eq 'HASH') | 
| 3836 |  |  |  |  |  |  | || $self->throw_error("You must pass a HASH ref of methods"); | 
| 3837 |  |  |  |  |  |  | } | 
| 3838 | 0 |  |  |  |  |  | my $roles = delete $options{roles}; | 
| 3839 | 0 | 0 |  |  |  |  | if(defined $roles){ | 
| 3840 | 0 | 0 |  |  |  |  | (ref $roles eq 'ARRAY') | 
| 3841 |  |  |  |  |  |  | || $self->throw_error("You must pass an ARRAY ref of roles"); | 
| 3842 |  |  |  |  |  |  | } | 
| 3843 | 0 |  |  |  |  |  | my $mortal; | 
| 3844 |  |  |  |  |  |  | my $cache_key; | 
| 3845 |  |  |  |  |  |  |  | 
| 3846 | 0 | 0 |  |  |  |  | if(!defined $package_name){ # anonymous | 
| 3847 | 0 |  |  |  |  |  | $mortal = !$options{cache}; | 
| 3848 |  |  |  |  |  |  |  | 
| 3849 |  |  |  |  |  |  | # anonymous but immortal | 
| 3850 | 0 | 0 |  |  |  |  | if(!$mortal){ | 
| 3851 |  |  |  |  |  |  | # something like Super::Class|Super::Class::2=Role|Role::1 | 
| 3852 | 0 | 0 |  |  |  |  | $cache_key = join '=' => ( | 
| 3853 | 0 | 0 |  |  |  |  | join('|',      @{$superclasses || []}), | 
| 3854 | 0 |  |  |  |  |  | join('|', sort @{$roles        || []}), | 
| 3855 |  |  |  |  |  |  | ); | 
| 3856 | 0 | 0 |  |  |  |  | return $IMMORTALS{$cache_key} if exists $IMMORTALS{$cache_key}; | 
| 3857 |  |  |  |  |  |  | } | 
| 3858 | 0 |  |  |  |  |  | $options{anon_serial_id} = ++$ANON_SERIAL; | 
| 3859 | 0 |  |  |  |  |  | $package_name = $class . '::__ANON__::' . $ANON_SERIAL; | 
| 3860 |  |  |  |  |  |  | } | 
| 3861 |  |  |  |  |  |  |  | 
| 3862 |  |  |  |  |  |  |  | 
| 3863 |  |  |  |  |  |  | # instantiate a module | 
| 3864 |  |  |  |  |  |  | { | 
| 3865 | 1 |  |  | 1 |  | 6 | no strict 'refs'; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 590 |  | 
|  | 0 |  |  |  |  |  |  | 
| 3866 | 0 | 0 |  |  |  |  | ${ $package_name . '::VERSION'   } = delete $options{version}   if exists $options{version}; | 
|  | 0 |  |  |  |  |  |  | 
| 3867 | 0 | 0 |  |  |  |  | ${ $package_name . '::AUTHORITY' } = delete $options{authority} if exists $options{authority}; | 
|  | 0 |  |  |  |  |  |  | 
| 3868 |  |  |  |  |  |  | } | 
| 3869 |  |  |  |  |  |  |  | 
| 3870 | 0 |  |  |  |  |  | my $meta = $self->initialize( $package_name, %options); | 
| 3871 |  |  |  |  |  |  |  | 
| 3872 | 0 | 0 |  |  |  |  | Scalar::Util::weaken($METAS{$package_name}) | 
| 3873 |  |  |  |  |  |  | if $mortal; | 
| 3874 |  |  |  |  |  |  |  | 
| 3875 |  |  |  |  |  |  | $meta->add_method(meta => sub { | 
| 3876 | 0 |  | 0 | 0 |  |  | $self->initialize(ref($_[0]) || $_[0]); | 
| 3877 | 0 |  |  |  |  |  | }); | 
| 3878 |  |  |  |  |  |  |  | 
| 3879 | 0 | 0 |  |  |  |  | $meta->superclasses(@{$superclasses}) | 
|  | 0 |  |  |  |  |  |  | 
| 3880 |  |  |  |  |  |  | if defined $superclasses; | 
| 3881 |  |  |  |  |  |  |  | 
| 3882 |  |  |  |  |  |  | # NOTE: | 
| 3883 |  |  |  |  |  |  | # process attributes first, so that they can | 
| 3884 |  |  |  |  |  |  | # install accessors, but locally defined methods | 
| 3885 |  |  |  |  |  |  | # can then overwrite them. It is maybe a little odd, but | 
| 3886 |  |  |  |  |  |  | # I think this should be the order of things. | 
| 3887 | 0 | 0 |  |  |  |  | if (defined $attributes) { | 
| 3888 | 0 | 0 |  |  |  |  | if(ref($attributes) eq 'ARRAY'){ | 
| 3889 |  |  |  |  |  |  | # array of Mousse::Meta::Attribute | 
| 3890 | 0 |  |  |  |  |  | foreach my $attr (@{$attributes}) { | 
|  | 0 |  |  |  |  |  |  | 
| 3891 | 0 |  |  |  |  |  | $meta->add_attribute($attr); | 
| 3892 |  |  |  |  |  |  | } | 
| 3893 |  |  |  |  |  |  | } | 
| 3894 |  |  |  |  |  |  | else{ | 
| 3895 |  |  |  |  |  |  | # hash map of name and attribute spec pairs | 
| 3896 | 0 |  |  |  |  |  | while(my($name, $attr) = each %{$attributes}){ | 
|  | 0 |  |  |  |  |  |  | 
| 3897 | 0 |  |  |  |  |  | $meta->add_attribute($name => $attr); | 
| 3898 |  |  |  |  |  |  | } | 
| 3899 |  |  |  |  |  |  | } | 
| 3900 |  |  |  |  |  |  | } | 
| 3901 | 0 | 0 |  |  |  |  | if (defined $methods) { | 
| 3902 | 0 |  |  |  |  |  | while(my($method_name, $method_body) = each %{$methods}){ | 
|  | 0 |  |  |  |  |  |  | 
| 3903 | 0 |  |  |  |  |  | $meta->add_method($method_name, $method_body); | 
| 3904 |  |  |  |  |  |  | } | 
| 3905 |  |  |  |  |  |  | } | 
| 3906 | 0 | 0 | 0 |  |  |  | if (defined $roles and !$options{in_application_to_instance}){ | 
| 3907 | 0 |  |  |  |  |  | Mousse::Util::apply_all_roles($package_name, @{$roles}); | 
|  | 0 |  |  |  |  |  |  | 
| 3908 |  |  |  |  |  |  | } | 
| 3909 |  |  |  |  |  |  |  | 
| 3910 | 0 | 0 |  |  |  |  | if($cache_key){ | 
| 3911 | 0 |  |  |  |  |  | $IMMORTALS{$cache_key} = $meta; | 
| 3912 |  |  |  |  |  |  | } | 
| 3913 |  |  |  |  |  |  |  | 
| 3914 | 0 |  |  |  |  |  | return $meta; | 
| 3915 |  |  |  |  |  |  | } | 
| 3916 |  |  |  |  |  |  |  | 
| 3917 |  |  |  |  |  |  | sub DESTROY{ | 
| 3918 | 0 |  |  | 0 |  |  | my($self) = @_; | 
| 3919 |  |  |  |  |  |  |  | 
| 3920 | 0 | 0 |  |  |  |  | return if $Mousse::Util::in_global_destruction; | 
| 3921 |  |  |  |  |  |  |  | 
| 3922 | 0 |  |  |  |  |  | my $serial_id = $self->{anon_serial_id}; | 
| 3923 | 0 | 0 |  |  |  |  | return if !$serial_id; | 
| 3924 |  |  |  |  |  |  |  | 
| 3925 |  |  |  |  |  |  | # XXX: cleaning stash with threads causes panic/SEGV on legacy perls. | 
| 3926 | 0 | 0 |  |  |  |  | if(exists $INC{'threads.pm'}) { | 
| 3927 |  |  |  |  |  |  | # (caller)[2] indicates the caller's line number, | 
| 3928 |  |  |  |  |  |  | # which is zero when the current thread is joining (destroying). | 
| 3929 | 0 | 0 |  |  |  |  | return if( (caller)[2] == 0); | 
| 3930 |  |  |  |  |  |  | } | 
| 3931 |  |  |  |  |  |  |  | 
| 3932 |  |  |  |  |  |  | # clean up mortal anonymous class stuff | 
| 3933 |  |  |  |  |  |  |  | 
| 3934 |  |  |  |  |  |  | # @ISA is a magical variable, so we must clear it manually. | 
| 3935 | 0 | 0 |  |  |  |  | @{$self->{superclasses}} = () if exists $self->{superclasses}; | 
|  | 0 |  |  |  |  |  |  | 
| 3936 |  |  |  |  |  |  |  | 
| 3937 |  |  |  |  |  |  | # Then, clear the symbol table hash | 
| 3938 | 0 |  |  |  |  |  | %{$self->namespace} = (); | 
|  | 0 |  |  |  |  |  |  | 
| 3939 |  |  |  |  |  |  |  | 
| 3940 | 0 |  |  |  |  |  | my $name = $self->name; | 
| 3941 | 0 |  |  |  |  |  | delete $METAS{$name}; | 
| 3942 |  |  |  |  |  |  |  | 
| 3943 | 0 |  |  |  |  |  | $name =~ s/ $serial_id \z//xms; | 
| 3944 | 1 |  |  | 1 |  | 5 | no strict 'refs'; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 73 |  | 
| 3945 | 0 |  |  |  |  |  | delete ${$name}{ $serial_id . '::' }; | 
|  | 0 |  |  |  |  |  |  | 
| 3946 | 0 |  |  |  |  |  | return; | 
| 3947 |  |  |  |  |  |  | } | 
| 3948 |  |  |  |  |  |  |  | 
| 3949 |  |  |  |  |  |  |  | 
| 3950 |  |  |  |  |  |  | # Contents of Mouse::Meta::Role | 
| 3951 |  |  |  |  |  |  | package Mousse::Meta::Role; | 
| 3952 | 1 |  |  | 1 |  | 10 | use Mousse::Util qw(:meta); # enables strict and warnings | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 3 |  | 
| 3953 |  |  |  |  |  |  |  | 
| 3954 | 1 |  |  | 1 |  | 5 | use Mousse::Meta::Module; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 1038 |  | 
| 3955 |  |  |  |  |  |  | our @ISA = qw(Mousse::Meta::Module); | 
| 3956 |  |  |  |  |  |  |  | 
| 3957 |  |  |  |  |  |  | sub method_metaclass; | 
| 3958 |  |  |  |  |  |  |  | 
| 3959 |  |  |  |  |  |  | sub _construct_meta { | 
| 3960 | 0 |  |  | 0 |  |  | my $class = shift; | 
| 3961 |  |  |  |  |  |  |  | 
| 3962 | 0 |  |  |  |  |  | my %args  = @_; | 
| 3963 |  |  |  |  |  |  |  | 
| 3964 | 0 |  |  |  |  |  | $args{methods}          = {}; | 
| 3965 | 0 |  |  |  |  |  | $args{attributes}       = {}; | 
| 3966 | 0 |  |  |  |  |  | $args{required_methods} = []; | 
| 3967 | 0 |  |  |  |  |  | $args{roles}            = []; | 
| 3968 |  |  |  |  |  |  |  | 
| 3969 | 0 |  | 0 |  |  |  | my $self = bless \%args, ref($class) || $class; | 
| 3970 | 0 | 0 |  |  |  |  | if($class ne __PACKAGE__){ | 
| 3971 | 0 |  |  |  |  |  | $self->meta->_initialize_object($self, \%args); | 
| 3972 |  |  |  |  |  |  | } | 
| 3973 | 0 |  |  |  |  |  | return $self; | 
| 3974 |  |  |  |  |  |  | } | 
| 3975 |  |  |  |  |  |  |  | 
| 3976 |  |  |  |  |  |  | sub create_anon_role{ | 
| 3977 | 0 |  |  | 0 | 0 |  | my $self = shift; | 
| 3978 | 0 |  |  |  |  |  | return $self->create(undef, @_); | 
| 3979 |  |  |  |  |  |  | } | 
| 3980 |  |  |  |  |  |  |  | 
| 3981 |  |  |  |  |  |  | sub is_anon_role; | 
| 3982 |  |  |  |  |  |  |  | 
| 3983 |  |  |  |  |  |  | sub get_roles; | 
| 3984 |  |  |  |  |  |  |  | 
| 3985 |  |  |  |  |  |  | sub calculate_all_roles { | 
| 3986 | 0 |  |  | 0 | 0 |  | my $self = shift; | 
| 3987 | 0 |  |  |  |  |  | my %seen; | 
| 3988 | 0 |  |  |  |  |  | return grep { !$seen{ $_->name }++ } | 
|  | 0 |  |  |  |  |  |  | 
| 3989 | 0 |  |  |  |  |  | ($self, map  { $_->calculate_all_roles } @{ $self->get_roles }); | 
|  | 0 |  |  |  |  |  |  | 
| 3990 |  |  |  |  |  |  | } | 
| 3991 |  |  |  |  |  |  |  | 
| 3992 |  |  |  |  |  |  | sub get_required_method_list{ | 
| 3993 | 0 |  |  | 0 | 0 |  | return @{ $_[0]->{required_methods} }; | 
|  | 0 |  |  |  |  |  |  | 
| 3994 |  |  |  |  |  |  | } | 
| 3995 |  |  |  |  |  |  |  | 
| 3996 |  |  |  |  |  |  | sub add_required_methods { | 
| 3997 | 0 |  |  | 0 | 0 |  | my($self, @methods) = @_; | 
| 3998 | 0 |  |  |  |  |  | my %required = map{ $_ => 1 } @{$self->{required_methods}}; | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 3999 | 0 |  | 0 |  |  |  | push @{$self->{required_methods}}, grep{ !$required{$_}++ && !$self->has_method($_) } @methods; | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 4000 | 0 |  |  |  |  |  | return; | 
| 4001 |  |  |  |  |  |  | } | 
| 4002 |  |  |  |  |  |  |  | 
| 4003 |  |  |  |  |  |  | sub requires_method { | 
| 4004 | 0 |  |  | 0 | 0 |  | my($self, $name) = @_; | 
| 4005 | 0 |  |  |  |  |  | return scalar( grep{ $_ eq $name } @{ $self->{required_methods} } ) != 0; | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 4006 |  |  |  |  |  |  | } | 
| 4007 |  |  |  |  |  |  |  | 
| 4008 |  |  |  |  |  |  | sub add_attribute { | 
| 4009 | 0 |  |  | 0 | 0 |  | my $self = shift; | 
| 4010 | 0 |  |  |  |  |  | my $name = shift; | 
| 4011 |  |  |  |  |  |  |  | 
| 4012 | 0 | 0 |  |  |  |  | $self->{attributes}->{$name} = (@_ == 1) ? $_[0] : { @_ }; | 
| 4013 | 0 |  |  |  |  |  | return; | 
| 4014 |  |  |  |  |  |  | } | 
| 4015 |  |  |  |  |  |  |  | 
| 4016 |  |  |  |  |  |  | sub apply { | 
| 4017 | 0 |  |  | 0 | 0 |  | my $self     = shift; | 
| 4018 | 0 |  |  |  |  |  | my $consumer = shift; | 
| 4019 |  |  |  |  |  |  |  | 
| 4020 | 0 |  |  |  |  |  | require 'Mousse/Meta/Role/Application.pm'; | 
| 4021 | 0 |  |  |  |  |  | return Mousse::Meta::Role::Application->new(@_)->apply($self, $consumer); | 
| 4022 |  |  |  |  |  |  | } | 
| 4023 |  |  |  |  |  |  |  | 
| 4024 |  |  |  |  |  |  | sub combine { | 
| 4025 | 0 |  |  | 0 | 0 |  | my($self, @role_specs) = @_; | 
| 4026 |  |  |  |  |  |  |  | 
| 4027 | 0 |  |  |  |  |  | require 'Mousse/Meta/Role/Composite.pm'; | 
| 4028 | 0 |  |  |  |  |  | return Mousse::Meta::Role::Composite->new(roles => \@role_specs); | 
| 4029 |  |  |  |  |  |  | } | 
| 4030 |  |  |  |  |  |  |  | 
| 4031 |  |  |  |  |  |  | sub add_before_method_modifier; | 
| 4032 |  |  |  |  |  |  | sub add_around_method_modifier; | 
| 4033 |  |  |  |  |  |  | sub add_after_method_modifier; | 
| 4034 |  |  |  |  |  |  |  | 
| 4035 |  |  |  |  |  |  | sub get_before_method_modifiers; | 
| 4036 |  |  |  |  |  |  | sub get_around_method_modifiers; | 
| 4037 |  |  |  |  |  |  | sub get_after_method_modifiers; | 
| 4038 |  |  |  |  |  |  |  | 
| 4039 |  |  |  |  |  |  | sub add_override_method_modifier{ | 
| 4040 | 0 |  |  | 0 | 0 |  | my($self, $method_name, $method) = @_; | 
| 4041 |  |  |  |  |  |  |  | 
| 4042 | 0 | 0 |  |  |  |  | if($self->has_method($method_name)){ | 
| 4043 |  |  |  |  |  |  | # This error happens in the override keyword or during role composition, | 
| 4044 |  |  |  |  |  |  | # so I added a message, "A local method of ...", only for compatibility (gfx) | 
| 4045 | 0 |  |  |  |  |  | $self->throw_error("Cannot add an override of method '$method_name' " | 
| 4046 |  |  |  |  |  |  | . "because there is a local version of '$method_name'" | 
| 4047 |  |  |  |  |  |  | . "(A local method of the same name as been found)"); | 
| 4048 |  |  |  |  |  |  | } | 
| 4049 |  |  |  |  |  |  |  | 
| 4050 | 0 |  |  |  |  |  | $self->{override_method_modifiers}->{$method_name} = $method; | 
| 4051 |  |  |  |  |  |  | } | 
| 4052 |  |  |  |  |  |  |  | 
| 4053 |  |  |  |  |  |  | sub get_override_method_modifier { | 
| 4054 | 0 |  |  | 0 | 0 |  | my ($self, $method_name) = @_; | 
| 4055 | 0 |  |  |  |  |  | return $self->{override_method_modifiers}->{$method_name}; | 
| 4056 |  |  |  |  |  |  | } | 
| 4057 |  |  |  |  |  |  |  | 
| 4058 |  |  |  |  |  |  | sub does_role { | 
| 4059 | 0 |  |  | 0 | 0 |  | my ($self, $role_name) = @_; | 
| 4060 |  |  |  |  |  |  |  | 
| 4061 | 0 | 0 |  |  |  |  | (defined $role_name) | 
| 4062 |  |  |  |  |  |  | || $self->throw_error("You must supply a role name to look for"); | 
| 4063 |  |  |  |  |  |  |  | 
| 4064 | 0 | 0 |  |  |  |  | $role_name = $role_name->name if ref $role_name; | 
| 4065 |  |  |  |  |  |  |  | 
| 4066 |  |  |  |  |  |  | # if we are it,.. then return true | 
| 4067 | 0 | 0 |  |  |  |  | return 1 if $role_name eq $self->name; | 
| 4068 |  |  |  |  |  |  | # otherwise.. check our children | 
| 4069 | 0 |  |  |  |  |  | for my $role (@{ $self->get_roles }) { | 
|  | 0 |  |  |  |  |  |  | 
| 4070 | 0 | 0 |  |  |  |  | return 1 if $role->does_role($role_name); | 
| 4071 |  |  |  |  |  |  | } | 
| 4072 | 0 |  |  |  |  |  | return 0; | 
| 4073 |  |  |  |  |  |  | } | 
| 4074 |  |  |  |  |  |  |  | 
| 4075 |  |  |  |  |  |  | # Contents of Mouse::Meta::Role::Application | 
| 4076 |  |  |  |  |  |  | package Mousse::Meta::Role::Application; | 
| 4077 | 1 |  |  | 1 |  | 5 | use Mousse::Util qw(:meta); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 3 |  | 
| 4078 |  |  |  |  |  |  |  | 
| 4079 |  |  |  |  |  |  | sub new { | 
| 4080 | 0 |  |  | 0 | 0 |  | my $class = shift; | 
| 4081 | 0 |  |  |  |  |  | my $args = $class->Mousse::Object::BUILDARGS(@_); | 
| 4082 |  |  |  |  |  |  |  | 
| 4083 | 0 | 0 | 0 |  |  |  | if(exists $args->{exclude} or exists $args->{alias}) { | 
| 4084 | 0 |  |  |  |  |  | warnings::warnif(deprecated => | 
| 4085 |  |  |  |  |  |  | 'The alias and excludes options for role application have been' | 
| 4086 |  |  |  |  |  |  | . ' renamed -alias and -exclude'); | 
| 4087 |  |  |  |  |  |  |  | 
| 4088 | 0 | 0 | 0 |  |  |  | if($args->{alias} && !exists $args->{-alias}){ | 
| 4089 | 0 |  |  |  |  |  | $args->{-alias} = $args->{alias}; | 
| 4090 |  |  |  |  |  |  | } | 
| 4091 | 0 | 0 | 0 |  |  |  | if($args->{excludes} && !exists $args->{-excludes}){ | 
| 4092 | 0 |  |  |  |  |  | $args->{-excludes} = $args->{excludes}; | 
| 4093 |  |  |  |  |  |  | } | 
| 4094 |  |  |  |  |  |  | } | 
| 4095 |  |  |  |  |  |  |  | 
| 4096 | 0 |  |  |  |  |  | $args->{aliased_methods} = {}; | 
| 4097 | 0 | 0 |  |  |  |  | if(my $alias = $args->{-alias}){ | 
| 4098 | 0 |  |  |  |  |  | @{$args->{aliased_methods}}{ values %{$alias} } = (); | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 4099 |  |  |  |  |  |  | } | 
| 4100 |  |  |  |  |  |  |  | 
| 4101 | 0 | 0 |  |  |  |  | if(my $excludes = $args->{-excludes}){ | 
| 4102 | 0 |  |  |  |  |  | $args->{-excludes} = {}; # replace with a hash ref | 
| 4103 | 0 | 0 |  |  |  |  | if(ref $excludes){ | 
| 4104 | 0 |  |  |  |  |  | %{$args->{-excludes}} = (map{ $_ => undef } @{$excludes}); | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 4105 |  |  |  |  |  |  | } | 
| 4106 |  |  |  |  |  |  | else{ | 
| 4107 | 0 |  |  |  |  |  | $args->{-excludes}{$excludes} = undef; | 
| 4108 |  |  |  |  |  |  | } | 
| 4109 |  |  |  |  |  |  | } | 
| 4110 | 0 |  |  |  |  |  | my $self = bless $args, $class; | 
| 4111 | 0 | 0 |  |  |  |  | if($class ne __PACKAGE__){ | 
| 4112 | 0 |  |  |  |  |  | $self->meta->_initialize_object($self, $args); | 
| 4113 |  |  |  |  |  |  | } | 
| 4114 | 0 |  |  |  |  |  | return $self; | 
| 4115 |  |  |  |  |  |  | } | 
| 4116 |  |  |  |  |  |  |  | 
| 4117 |  |  |  |  |  |  | sub apply { | 
| 4118 | 0 |  |  | 0 | 0 |  | my($self, $role, $consumer, @extra) = @_; | 
| 4119 | 0 |  |  |  |  |  | my $instance; | 
| 4120 |  |  |  |  |  |  |  | 
| 4121 | 0 | 0 |  |  |  |  | if(Mousse::Util::is_a_metaclass($consumer)) {   # Application::ToClass | 
|  |  | 0 |  |  |  |  |  | 
| 4122 | 0 |  |  |  |  |  | $self->{_to} = 'class'; | 
| 4123 |  |  |  |  |  |  | } | 
| 4124 |  |  |  |  |  |  | elsif(Mousse::Util::is_a_metarole($consumer)) { # Application::ToRole | 
| 4125 | 0 |  |  |  |  |  | $self->{_to} = 'role'; | 
| 4126 |  |  |  |  |  |  | } | 
| 4127 |  |  |  |  |  |  | else {                                         # Appplication::ToInstance | 
| 4128 | 0 |  |  |  |  |  | $self->{_to} = 'instance'; | 
| 4129 | 0 |  |  |  |  |  | $instance  = $consumer; | 
| 4130 |  |  |  |  |  |  |  | 
| 4131 | 0 |  | 0 |  |  |  | $consumer = (Mousse::Util::class_of($instance) || 'Mousse::Meta::Class') | 
| 4132 |  |  |  |  |  |  | ->create_anon_class( | 
| 4133 |  |  |  |  |  |  | superclasses => [ref $instance], | 
| 4134 |  |  |  |  |  |  | roles        => [$role], | 
| 4135 |  |  |  |  |  |  | cache        => 1, | 
| 4136 |  |  |  |  |  |  |  | 
| 4137 |  |  |  |  |  |  | in_application_to_instance => 1, # suppress to apply roles | 
| 4138 |  |  |  |  |  |  | ); | 
| 4139 |  |  |  |  |  |  | } | 
| 4140 |  |  |  |  |  |  |  | 
| 4141 |  |  |  |  |  |  | #$self->check_role_exclusions($role, $consumer, @extra); | 
| 4142 | 0 |  |  |  |  |  | $self->check_required_methods($role, $consumer, @extra); | 
| 4143 |  |  |  |  |  |  | #$self->check_required_attributes($role, $consumer, @extra); | 
| 4144 |  |  |  |  |  |  |  | 
| 4145 | 0 |  |  |  |  |  | $self->apply_attributes($role, $consumer, @extra); | 
| 4146 | 0 |  |  |  |  |  | $self->apply_methods($role, $consumer, @extra); | 
| 4147 |  |  |  |  |  |  | #$self->apply_override_method_modifiers($role, $consumer, @extra); | 
| 4148 |  |  |  |  |  |  | #$self->apply_before_method_modifiers($role, $consumer, @extra); | 
| 4149 |  |  |  |  |  |  | #$self->apply_around_method_modifiers($role, $consumer, @extra); | 
| 4150 |  |  |  |  |  |  | #$self->apply_after_method_modifiers($role, $consumer, @extra); | 
| 4151 | 0 |  |  |  |  |  | $self->apply_modifiers($role, $consumer, @extra); | 
| 4152 |  |  |  |  |  |  |  | 
| 4153 | 0 |  |  |  |  |  | $self->_append_roles($role, $consumer); | 
| 4154 |  |  |  |  |  |  |  | 
| 4155 | 0 | 0 |  |  |  |  | if(defined $instance){ # Application::ToInstance | 
| 4156 |  |  |  |  |  |  | # rebless instance | 
| 4157 | 0 |  |  |  |  |  | bless $instance, $consumer->name; | 
| 4158 | 0 |  |  |  |  |  | $consumer->_initialize_object($instance, $instance, 1); | 
| 4159 |  |  |  |  |  |  | } | 
| 4160 |  |  |  |  |  |  |  | 
| 4161 | 0 |  |  |  |  |  | return; | 
| 4162 |  |  |  |  |  |  | } | 
| 4163 |  |  |  |  |  |  |  | 
| 4164 |  |  |  |  |  |  | sub check_required_methods { | 
| 4165 | 0 |  |  | 0 | 0 |  | my($self, $role, $consumer) = @_; | 
| 4166 |  |  |  |  |  |  |  | 
| 4167 | 0 | 0 |  |  |  |  | if($self->{_to} eq 'role'){ | 
| 4168 | 0 |  |  |  |  |  | $consumer->add_required_methods($role->get_required_method_list); | 
| 4169 |  |  |  |  |  |  | } | 
| 4170 |  |  |  |  |  |  | else{ # to class or instance | 
| 4171 | 0 |  |  |  |  |  | my $consumer_class_name = $consumer->name; | 
| 4172 |  |  |  |  |  |  |  | 
| 4173 | 0 |  |  |  |  |  | my @missing; | 
| 4174 | 0 |  |  |  |  |  | foreach my $method_name(@{$role->{required_methods}}){ | 
|  | 0 |  |  |  |  |  |  | 
| 4175 | 0 | 0 |  |  |  |  | next if exists $self->{aliased_methods}{$method_name}; | 
| 4176 | 0 | 0 |  |  |  |  | next if exists $role->{methods}{$method_name}; | 
| 4177 | 0 | 0 |  |  |  |  | next if $consumer_class_name->can($method_name); | 
| 4178 |  |  |  |  |  |  |  | 
| 4179 | 0 |  |  |  |  |  | push @missing, $method_name; | 
| 4180 |  |  |  |  |  |  | } | 
| 4181 | 0 | 0 |  |  |  |  | if(@missing){ | 
| 4182 | 0 | 0 |  |  |  |  | $role->throw_error(sprintf "'%s' requires the method%s %s to be implemented by '%s'", | 
| 4183 |  |  |  |  |  |  | $role->name, | 
| 4184 |  |  |  |  |  |  | (@missing == 1 ? '' : 's'), # method or methods | 
| 4185 |  |  |  |  |  |  | Mousse::Util::quoted_english_list(@missing), | 
| 4186 |  |  |  |  |  |  | $consumer_class_name); | 
| 4187 |  |  |  |  |  |  | } | 
| 4188 |  |  |  |  |  |  | } | 
| 4189 |  |  |  |  |  |  |  | 
| 4190 | 0 |  |  |  |  |  | return; | 
| 4191 |  |  |  |  |  |  | } | 
| 4192 |  |  |  |  |  |  |  | 
| 4193 |  |  |  |  |  |  | sub apply_methods { | 
| 4194 | 0 |  |  | 0 | 0 |  | my($self, $role, $consumer) = @_; | 
| 4195 |  |  |  |  |  |  |  | 
| 4196 | 0 |  |  |  |  |  | my $alias    = $self->{-alias}; | 
| 4197 | 0 |  |  |  |  |  | my $excludes = $self->{-excludes}; | 
| 4198 |  |  |  |  |  |  |  | 
| 4199 | 0 |  |  |  |  |  | foreach my $method_name($role->get_method_list){ | 
| 4200 | 0 | 0 |  |  |  |  | next if $method_name eq 'meta'; | 
| 4201 |  |  |  |  |  |  |  | 
| 4202 | 0 |  |  |  |  |  | my $code = $role->get_method_body($method_name); | 
| 4203 |  |  |  |  |  |  |  | 
| 4204 | 0 | 0 |  |  |  |  | if(!exists $excludes->{$method_name}){ | 
| 4205 | 0 | 0 |  |  |  |  | if(!$consumer->has_method($method_name)){ | 
| 4206 |  |  |  |  |  |  | # The third argument $role is used in Role::Composite | 
| 4207 | 0 |  |  |  |  |  | $consumer->add_method($method_name => $code, $role); | 
| 4208 |  |  |  |  |  |  | } | 
| 4209 |  |  |  |  |  |  | } | 
| 4210 |  |  |  |  |  |  |  | 
| 4211 | 0 | 0 |  |  |  |  | if(exists $alias->{$method_name}){ | 
| 4212 | 0 |  |  |  |  |  | my $dstname = $alias->{$method_name}; | 
| 4213 |  |  |  |  |  |  |  | 
| 4214 | 0 |  |  |  |  |  | my $dstcode = $consumer->get_method_body($dstname); | 
| 4215 |  |  |  |  |  |  |  | 
| 4216 | 0 | 0 | 0 |  |  |  | if(defined($dstcode) && $dstcode != $code){ | 
| 4217 | 0 |  |  |  |  |  | $role->throw_error("Cannot create a method alias if a local method of the same name exists"); | 
| 4218 |  |  |  |  |  |  | } | 
| 4219 |  |  |  |  |  |  | else{ | 
| 4220 | 0 |  |  |  |  |  | $consumer->add_method($dstname => $code, $role); | 
| 4221 |  |  |  |  |  |  | } | 
| 4222 |  |  |  |  |  |  | } | 
| 4223 |  |  |  |  |  |  | } | 
| 4224 |  |  |  |  |  |  |  | 
| 4225 | 0 |  |  |  |  |  | return; | 
| 4226 |  |  |  |  |  |  | } | 
| 4227 |  |  |  |  |  |  |  | 
| 4228 |  |  |  |  |  |  | sub apply_attributes { | 
| 4229 | 0 |  |  | 0 | 0 |  | my($self, $role, $consumer) = @_; | 
| 4230 |  |  |  |  |  |  |  | 
| 4231 | 0 |  |  |  |  |  | for my $attr_name ($role->get_attribute_list) { | 
| 4232 | 0 | 0 |  |  |  |  | next if $consumer->has_attribute($attr_name); | 
| 4233 |  |  |  |  |  |  |  | 
| 4234 | 0 |  |  |  |  |  | $consumer->add_attribute($attr_name | 
| 4235 |  |  |  |  |  |  | => $role->get_attribute($attr_name)); | 
| 4236 |  |  |  |  |  |  | } | 
| 4237 | 0 |  |  |  |  |  | return; | 
| 4238 |  |  |  |  |  |  | } | 
| 4239 |  |  |  |  |  |  |  | 
| 4240 |  |  |  |  |  |  | sub apply_modifiers { | 
| 4241 | 0 |  |  | 0 | 0 |  | my($self, $role, $consumer) = @_; | 
| 4242 |  |  |  |  |  |  |  | 
| 4243 | 0 | 0 |  |  |  |  | if(my $modifiers = $role->{override_method_modifiers}){ | 
| 4244 | 0 |  |  |  |  |  | foreach my $method_name (keys %{$modifiers}){ | 
|  | 0 |  |  |  |  |  |  | 
| 4245 | 0 |  |  |  |  |  | $consumer->add_override_method_modifier( | 
| 4246 |  |  |  |  |  |  | $method_name => $modifiers->{$method_name}); | 
| 4247 |  |  |  |  |  |  | } | 
| 4248 |  |  |  |  |  |  | } | 
| 4249 |  |  |  |  |  |  |  | 
| 4250 | 0 |  |  |  |  |  | for my $modifier_type (qw/before around after/) { | 
| 4251 | 0 | 0 |  |  |  |  | my $table = $role->{"${modifier_type}_method_modifiers"} | 
| 4252 |  |  |  |  |  |  | or next; | 
| 4253 |  |  |  |  |  |  |  | 
| 4254 | 0 |  |  |  |  |  | my $add_modifier = "add_${modifier_type}_method_modifier"; | 
| 4255 |  |  |  |  |  |  |  | 
| 4256 | 0 |  |  |  |  |  | while(my($method_name, $modifiers) = each %{$table}){ | 
|  | 0 |  |  |  |  |  |  | 
| 4257 | 0 |  |  |  |  |  | foreach my $code(@{ $modifiers }) { | 
|  | 0 |  |  |  |  |  |  | 
| 4258 |  |  |  |  |  |  | # skip if the modifier is already applied | 
| 4259 | 0 | 0 |  |  |  |  | next if $consumer->{"_applied_$modifier_type"}{$method_name, $code}++; | 
| 4260 | 0 |  |  |  |  |  | $consumer->$add_modifier($method_name => $code); | 
| 4261 |  |  |  |  |  |  | } | 
| 4262 |  |  |  |  |  |  | } | 
| 4263 |  |  |  |  |  |  | } | 
| 4264 | 0 |  |  |  |  |  | return; | 
| 4265 |  |  |  |  |  |  | } | 
| 4266 |  |  |  |  |  |  |  | 
| 4267 |  |  |  |  |  |  | sub _append_roles { | 
| 4268 | 0 |  |  | 0 |  |  | my($self, $role, $metaclass_or_role) = @_; | 
| 4269 |  |  |  |  |  |  |  | 
| 4270 | 0 |  |  |  |  |  | my $roles = $metaclass_or_role->{roles}; | 
| 4271 | 0 |  |  |  |  |  | foreach my $r($role, @{$role->get_roles}){ | 
|  | 0 |  |  |  |  |  |  | 
| 4272 | 0 | 0 |  |  |  |  | if(!$metaclass_or_role->does_role($r)){ | 
| 4273 | 0 |  |  |  |  |  | push @{$roles}, $r; | 
|  | 0 |  |  |  |  |  |  | 
| 4274 |  |  |  |  |  |  | } | 
| 4275 |  |  |  |  |  |  | } | 
| 4276 | 0 |  |  |  |  |  | return; | 
| 4277 |  |  |  |  |  |  | } | 
| 4278 |  |  |  |  |  |  | # Contents of Mouse::Meta::Role::Composite | 
| 4279 |  |  |  |  |  |  | package Mousse::Meta::Role::Composite; | 
| 4280 | 1 |  |  | 1 |  | 5 | use Mousse::Util; # enables strict and warnings | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 4 |  | 
| 4281 | 1 |  |  | 1 |  | 5 | use Mousse::Meta::Role; | 
|  | 1 |  |  |  |  | 7 |  | 
|  | 1 |  |  |  |  | 20 |  | 
| 4282 | 1 |  |  | 1 |  | 5 | use Mousse::Meta::Role::Application; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 1231 |  | 
| 4283 |  |  |  |  |  |  | our @ISA = qw(Mousse::Meta::Role); | 
| 4284 |  |  |  |  |  |  |  | 
| 4285 |  |  |  |  |  |  | # FIXME: Mousse::Meta::Role::Composite does things in different way from Moose's | 
| 4286 |  |  |  |  |  |  | # Moose: creates a new class for the consumer, and applies roles to it. | 
| 4287 |  |  |  |  |  |  | # Mousse: creates a coposite role and apply roles to the role, | 
| 4288 |  |  |  |  |  |  | #        and then applies it to the consumer. | 
| 4289 |  |  |  |  |  |  |  | 
| 4290 |  |  |  |  |  |  | sub new { | 
| 4291 | 0 |  |  | 0 | 0 |  | my $class = shift; | 
| 4292 | 0 |  |  |  |  |  | my $args  = $class->Mousse::Object::BUILDARGS(@_); | 
| 4293 | 0 |  |  |  |  |  | my $roles = delete $args->{roles}; | 
| 4294 | 0 |  |  |  |  |  | my $self  = $class->create_anon_role(%{$args}); | 
|  | 0 |  |  |  |  |  |  | 
| 4295 | 0 |  |  |  |  |  | foreach my $role_spec(@{$roles}) { | 
|  | 0 |  |  |  |  |  |  | 
| 4296 | 0 |  |  |  |  |  | my($role, $args) = ref($role_spec) eq 'ARRAY' | 
| 4297 | 0 | 0 |  |  |  |  | ? @{$role_spec} | 
| 4298 |  |  |  |  |  |  | : ($role_spec, {}); | 
| 4299 | 0 |  |  |  |  |  | $role->apply($self, %{$args}); | 
|  | 0 |  |  |  |  |  |  | 
| 4300 |  |  |  |  |  |  | } | 
| 4301 | 0 |  |  |  |  |  | return $self; | 
| 4302 |  |  |  |  |  |  | } | 
| 4303 |  |  |  |  |  |  |  | 
| 4304 |  |  |  |  |  |  | sub get_method_list { | 
| 4305 | 0 |  |  | 0 | 0 |  | my($self) = @_; | 
| 4306 | 0 |  |  |  |  |  | return keys %{ $self->{methods} }; | 
|  | 0 |  |  |  |  |  |  | 
| 4307 |  |  |  |  |  |  | } | 
| 4308 |  |  |  |  |  |  |  | 
| 4309 |  |  |  |  |  |  | sub add_method { | 
| 4310 | 0 |  |  | 0 | 0 |  | my($self, $method_name, $code, $role) = @_; | 
| 4311 |  |  |  |  |  |  |  | 
| 4312 | 0 | 0 | 0 |  |  |  | if( ($self->{methods}{$method_name} || 0) == $code){ | 
| 4313 |  |  |  |  |  |  | # This role already has the same method. | 
| 4314 | 0 |  |  |  |  |  | return; | 
| 4315 |  |  |  |  |  |  | } | 
| 4316 |  |  |  |  |  |  |  | 
| 4317 | 0 | 0 |  |  |  |  | if($method_name eq 'meta'){ | 
| 4318 | 0 |  |  |  |  |  | $self->SUPER::add_method($method_name => $code); | 
| 4319 |  |  |  |  |  |  | } | 
| 4320 |  |  |  |  |  |  | else{ | 
| 4321 |  |  |  |  |  |  | # no need to add a subroutine to the stash | 
| 4322 | 0 |  | 0 |  |  |  | my $roles = $self->{composed_roles_by_method}{$method_name} ||= []; | 
| 4323 | 0 |  |  |  |  |  | push @{$roles}, $role; | 
|  | 0 |  |  |  |  |  |  | 
| 4324 | 0 | 0 |  |  |  |  | if(@{$roles} > 1){ | 
|  | 0 |  |  |  |  |  |  | 
| 4325 | 0 |  |  |  |  |  | $self->{conflicting_methods}{$method_name}++; | 
| 4326 |  |  |  |  |  |  | } | 
| 4327 | 0 |  |  |  |  |  | $self->{methods}{$method_name} = $code; | 
| 4328 |  |  |  |  |  |  | } | 
| 4329 | 0 |  |  |  |  |  | return; | 
| 4330 |  |  |  |  |  |  | } | 
| 4331 |  |  |  |  |  |  |  | 
| 4332 |  |  |  |  |  |  | sub get_method_body { | 
| 4333 | 0 |  |  | 0 | 0 |  | my($self, $method_name) = @_; | 
| 4334 | 0 |  |  |  |  |  | return $self->{methods}{$method_name}; | 
| 4335 |  |  |  |  |  |  | } | 
| 4336 |  |  |  |  |  |  |  | 
| 4337 |  |  |  |  |  |  | sub has_method { | 
| 4338 |  |  |  |  |  |  | # my($self, $method_name) = @_; | 
| 4339 | 0 |  |  | 0 | 0 |  | return 0; # to fool apply_methods() in combine() | 
| 4340 |  |  |  |  |  |  | } | 
| 4341 |  |  |  |  |  |  |  | 
| 4342 |  |  |  |  |  |  | sub has_attribute { | 
| 4343 |  |  |  |  |  |  | # my($self, $method_name) = @_; | 
| 4344 | 0 |  |  | 0 | 0 |  | return 0; # to fool appply_attributes() in combine() | 
| 4345 |  |  |  |  |  |  | } | 
| 4346 |  |  |  |  |  |  |  | 
| 4347 |  |  |  |  |  |  | sub has_override_method_modifier { | 
| 4348 |  |  |  |  |  |  | # my($self, $method_name) = @_; | 
| 4349 | 0 |  |  | 0 | 0 |  | return 0; # to fool apply_modifiers() in combine() | 
| 4350 |  |  |  |  |  |  | } | 
| 4351 |  |  |  |  |  |  |  | 
| 4352 |  |  |  |  |  |  | sub add_attribute { | 
| 4353 | 0 |  |  | 0 | 0 |  | my $self      = shift; | 
| 4354 | 0 |  |  |  |  |  | my $attr_name = shift; | 
| 4355 | 0 | 0 |  |  |  |  | my $spec      = (@_ == 1 ? $_[0] : {@_}); | 
| 4356 |  |  |  |  |  |  |  | 
| 4357 | 0 |  |  |  |  |  | my $existing = $self->{attributes}{$attr_name}; | 
| 4358 | 0 | 0 | 0 |  |  |  | if($existing && $existing != $spec){ | 
| 4359 | 0 |  |  |  |  |  | $self->throw_error("We have encountered an attribute conflict with '$attr_name' " | 
| 4360 |  |  |  |  |  |  | . "during composition. This is fatal error and cannot be disambiguated."); | 
| 4361 |  |  |  |  |  |  | } | 
| 4362 | 0 |  |  |  |  |  | $self->SUPER::add_attribute($attr_name, $spec); | 
| 4363 | 0 |  |  |  |  |  | return; | 
| 4364 |  |  |  |  |  |  | } | 
| 4365 |  |  |  |  |  |  |  | 
| 4366 |  |  |  |  |  |  | sub add_override_method_modifier { | 
| 4367 | 0 |  |  | 0 | 0 |  | my($self, $method_name, $code) = @_; | 
| 4368 |  |  |  |  |  |  |  | 
| 4369 | 0 |  |  |  |  |  | my $existing = $self->{override_method_modifiers}{$method_name}; | 
| 4370 | 0 | 0 | 0 |  |  |  | if($existing && $existing != $code){ | 
| 4371 | 0 |  |  |  |  |  | $self->throw_error( "We have encountered an 'override' method conflict with '$method_name' during " | 
| 4372 |  |  |  |  |  |  | . "composition (Two 'override' methods of the same name encountered). " | 
| 4373 |  |  |  |  |  |  | . "This is fatal error.") | 
| 4374 |  |  |  |  |  |  | } | 
| 4375 | 0 |  |  |  |  |  | $self->SUPER::add_override_method_modifier($method_name, $code); | 
| 4376 | 0 |  |  |  |  |  | return; | 
| 4377 |  |  |  |  |  |  | } | 
| 4378 |  |  |  |  |  |  |  | 
| 4379 |  |  |  |  |  |  | sub apply { | 
| 4380 | 0 |  |  | 0 | 0 |  | my $self     = shift; | 
| 4381 | 0 |  |  |  |  |  | my $consumer = shift; | 
| 4382 |  |  |  |  |  |  |  | 
| 4383 | 0 |  |  |  |  |  | Mousse::Meta::Role::Application::RoleSummation->new(@_)->apply($self, $consumer); | 
| 4384 | 0 |  |  |  |  |  | return; | 
| 4385 |  |  |  |  |  |  | } | 
| 4386 |  |  |  |  |  |  |  | 
| 4387 |  |  |  |  |  |  | package Mousse::Meta::Role::Application::RoleSummation; | 
| 4388 |  |  |  |  |  |  | our @ISA = qw(Mousse::Meta::Role::Application); | 
| 4389 |  |  |  |  |  |  |  | 
| 4390 |  |  |  |  |  |  | sub apply_methods { | 
| 4391 | 0 |  |  | 0 |  |  | my($self, $role, $consumer, @extra) = @_; | 
| 4392 |  |  |  |  |  |  |  | 
| 4393 | 0 | 0 |  |  |  |  | if(exists $role->{conflicting_methods}){ | 
| 4394 | 0 |  |  |  |  |  | my $consumer_class_name = $consumer->name; | 
| 4395 |  |  |  |  |  |  |  | 
| 4396 | 0 |  |  |  |  |  | my @conflicting = grep{ !$consumer_class_name->can($_) } | 
|  | 0 |  |  |  |  |  |  | 
| 4397 | 0 |  |  |  |  |  | keys %{ $role->{conflicting_methods} }; | 
| 4398 |  |  |  |  |  |  |  | 
| 4399 | 0 | 0 |  |  |  |  | if(@conflicting) { | 
| 4400 | 0 | 0 |  |  |  |  | my $method_name_conflict = (@conflicting == 1 | 
| 4401 |  |  |  |  |  |  | ? 'a method name conflict' | 
| 4402 |  |  |  |  |  |  | : 'method name conflicts'); | 
| 4403 |  |  |  |  |  |  |  | 
| 4404 | 0 |  |  |  |  |  | my %seen; | 
| 4405 | 0 |  |  |  |  |  | my $roles = Mousse::Util::quoted_english_list( | 
| 4406 | 0 |  |  |  |  |  | grep{ !$seen{$_}++ } # uniq | 
| 4407 | 0 |  |  |  |  |  | map { $_->name } | 
| 4408 | 0 |  |  |  |  |  | map { @{$_} } | 
|  | 0 |  |  |  |  |  |  | 
| 4409 | 0 |  |  |  |  |  | @{ $role->{composed_roles_by_method} }{@conflicting} | 
| 4410 |  |  |  |  |  |  | ); | 
| 4411 |  |  |  |  |  |  |  | 
| 4412 | 0 | 0 |  |  |  |  | $self->throw_error(sprintf | 
| 4413 |  |  |  |  |  |  | q{Due to %s in roles %s,} | 
| 4414 |  |  |  |  |  |  | . q{ the method%s %s must be implemented or excluded by '%s'}, | 
| 4415 |  |  |  |  |  |  | $method_name_conflict, | 
| 4416 |  |  |  |  |  |  | $roles, | 
| 4417 |  |  |  |  |  |  | (@conflicting > 1 ? 's' : ''), | 
| 4418 |  |  |  |  |  |  | Mousse::Util::quoted_english_list(@conflicting), | 
| 4419 |  |  |  |  |  |  | $consumer_class_name); | 
| 4420 |  |  |  |  |  |  | } | 
| 4421 |  |  |  |  |  |  | } | 
| 4422 |  |  |  |  |  |  |  | 
| 4423 | 0 |  |  |  |  |  | $self->SUPER::apply_methods($role, $consumer, @extra); | 
| 4424 | 0 |  |  |  |  |  | return; | 
| 4425 |  |  |  |  |  |  | } | 
| 4426 |  |  |  |  |  |  |  | 
| 4427 |  |  |  |  |  |  | package Mousse::Meta::Role::Composite; | 
| 4428 |  |  |  |  |  |  | # Contents of Mouse::Meta::Role::Method | 
| 4429 |  |  |  |  |  |  | package Mousse::Meta::Role::Method; | 
| 4430 | 1 |  |  | 1 |  | 14 | use Mousse::Util; # enables strict and warnings | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 7 |  | 
| 4431 |  |  |  |  |  |  |  | 
| 4432 | 1 |  |  | 1 |  | 5 | use Mousse::Meta::Method; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 121 |  | 
| 4433 |  |  |  |  |  |  | our @ISA = qw(Mousse::Meta::Method); | 
| 4434 |  |  |  |  |  |  |  | 
| 4435 |  |  |  |  |  |  | sub _new{ | 
| 4436 | 0 |  |  | 0 |  |  | my($class, %args) = @_; | 
| 4437 | 0 |  |  |  |  |  | my $self = bless \%args, $class; | 
| 4438 |  |  |  |  |  |  |  | 
| 4439 | 0 | 0 |  |  |  |  | if($class ne __PACKAGE__){ | 
| 4440 | 0 |  |  |  |  |  | $self->meta->_initialize_object($self, \%args); | 
| 4441 |  |  |  |  |  |  | } | 
| 4442 | 0 |  |  |  |  |  | return $self; | 
| 4443 |  |  |  |  |  |  | } | 
| 4444 |  |  |  |  |  |  |  | 
| 4445 |  |  |  |  |  |  | # Contents of Mouse::Object | 
| 4446 |  |  |  |  |  |  | package Mousse::Object; | 
| 4447 | 1 |  |  | 1 |  | 4 | use Mousse::Util qw(does dump meta); # enables strict and warnings | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 11 |  | 
| 4448 |  |  |  |  |  |  | # all the stuff are defined in XS or PP | 
| 4449 |  |  |  |  |  |  |  | 
| 4450 |  |  |  |  |  |  | sub DOES { | 
| 4451 | 0 |  |  | 0 | 0 |  | my($self, $class_or_role_name) = @_; | 
| 4452 | 0 |  | 0 |  |  |  | return $self->isa($class_or_role_name) || $self->does($class_or_role_name); | 
| 4453 |  |  |  |  |  |  | } | 
| 4454 |  |  |  |  |  |  |  | 
| 4455 |  |  |  |  |  |  | # Contents of Mouse::Role | 
| 4456 |  |  |  |  |  |  | package Mousse::Role; | 
| 4457 | 1 |  |  | 1 |  | 5 | use Mousse::Exporter; # enables strict and warnings | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 6 |  | 
| 4458 |  |  |  |  |  |  |  | 
| 4459 |  |  |  |  |  |  | our $VERSION = '0.93'; | 
| 4460 |  |  |  |  |  |  |  | 
| 4461 | 1 |  |  | 1 |  | 4 | use Carp         (); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 15 |  | 
| 4462 | 1 |  |  | 1 |  | 4 | use Scalar::Util (); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 20 |  | 
| 4463 |  |  |  |  |  |  |  | 
| 4464 | 1 |  |  | 1 |  | 11 | use Mousse (); | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 972 |  | 
| 4465 |  |  |  |  |  |  |  | 
| 4466 |  |  |  |  |  |  | Mousse::Exporter->setup_import_methods( | 
| 4467 |  |  |  |  |  |  | as_is => [qw( | 
| 4468 |  |  |  |  |  |  | extends with | 
| 4469 |  |  |  |  |  |  | has | 
| 4470 |  |  |  |  |  |  | before after around | 
| 4471 |  |  |  |  |  |  | override super | 
| 4472 |  |  |  |  |  |  | augment  inner | 
| 4473 |  |  |  |  |  |  |  | 
| 4474 |  |  |  |  |  |  | requires excludes | 
| 4475 |  |  |  |  |  |  | ), | 
| 4476 |  |  |  |  |  |  | \&Scalar::Util::blessed, | 
| 4477 |  |  |  |  |  |  | \&Carp::confess, | 
| 4478 |  |  |  |  |  |  | ], | 
| 4479 |  |  |  |  |  |  | ); | 
| 4480 |  |  |  |  |  |  |  | 
| 4481 |  |  |  |  |  |  |  | 
| 4482 |  |  |  |  |  |  | sub extends  { | 
| 4483 | 0 |  |  | 0 | 0 |  | Carp::croak "Roles do not support 'extends'"; | 
| 4484 |  |  |  |  |  |  | } | 
| 4485 |  |  |  |  |  |  |  | 
| 4486 |  |  |  |  |  |  | sub with { | 
| 4487 | 0 |  |  | 0 | 0 |  | Mousse::Util::apply_all_roles(scalar(caller), @_); | 
| 4488 | 0 |  |  |  |  |  | return; | 
| 4489 |  |  |  |  |  |  | } | 
| 4490 |  |  |  |  |  |  |  | 
| 4491 |  |  |  |  |  |  | sub has { | 
| 4492 | 0 |  |  | 0 | 0 |  | my $meta = Mousse::Meta::Role->initialize(scalar caller); | 
| 4493 | 0 |  |  |  |  |  | my $name = shift; | 
| 4494 |  |  |  |  |  |  |  | 
| 4495 | 0 | 0 |  |  |  |  | $meta->throw_error(q{Usage: has 'name' => ( key => value, ... )}) | 
| 4496 |  |  |  |  |  |  | if @_ % 2; # odd number of arguments | 
| 4497 |  |  |  |  |  |  |  | 
| 4498 | 0 | 0 |  |  |  |  | for my $n(ref($name) ? @{$name} : $name){ | 
|  | 0 |  |  |  |  |  |  | 
| 4499 | 0 |  |  |  |  |  | $meta->add_attribute($n => @_); | 
| 4500 |  |  |  |  |  |  | } | 
| 4501 | 0 |  |  |  |  |  | return; | 
| 4502 |  |  |  |  |  |  | } | 
| 4503 |  |  |  |  |  |  |  | 
| 4504 |  |  |  |  |  |  | sub before { | 
| 4505 | 0 |  |  | 0 | 0 |  | my $meta = Mousse::Meta::Role->initialize(scalar caller); | 
| 4506 | 0 |  |  |  |  |  | my $code = pop; | 
| 4507 | 0 |  |  |  |  |  | for my $name($meta->_collect_methods(@_)) { | 
| 4508 | 0 |  |  |  |  |  | $meta->add_before_method_modifier($name => $code); | 
| 4509 |  |  |  |  |  |  | } | 
| 4510 | 0 |  |  |  |  |  | return; | 
| 4511 |  |  |  |  |  |  | } | 
| 4512 |  |  |  |  |  |  |  | 
| 4513 |  |  |  |  |  |  | sub after { | 
| 4514 | 0 |  |  | 0 | 0 |  | my $meta = Mousse::Meta::Role->initialize(scalar caller); | 
| 4515 | 0 |  |  |  |  |  | my $code = pop; | 
| 4516 | 0 |  |  |  |  |  | for my $name($meta->_collect_methods(@_)) { | 
| 4517 | 0 |  |  |  |  |  | $meta->add_after_method_modifier($name => $code); | 
| 4518 |  |  |  |  |  |  | } | 
| 4519 | 0 |  |  |  |  |  | return; | 
| 4520 |  |  |  |  |  |  | } | 
| 4521 |  |  |  |  |  |  |  | 
| 4522 |  |  |  |  |  |  | sub around { | 
| 4523 | 0 |  |  | 0 | 0 |  | my $meta = Mousse::Meta::Role->initialize(scalar caller); | 
| 4524 | 0 |  |  |  |  |  | my $code = pop; | 
| 4525 | 0 |  |  |  |  |  | for my $name($meta->_collect_methods(@_)) { | 
| 4526 | 0 |  |  |  |  |  | $meta->add_around_method_modifier($name => $code); | 
| 4527 |  |  |  |  |  |  | } | 
| 4528 | 0 |  |  |  |  |  | return; | 
| 4529 |  |  |  |  |  |  | } | 
| 4530 |  |  |  |  |  |  |  | 
| 4531 |  |  |  |  |  |  |  | 
| 4532 |  |  |  |  |  |  | sub super { | 
| 4533 | 0 | 0 |  | 0 | 0 |  | return if !defined $Mousse::SUPER_BODY; | 
| 4534 | 0 |  |  |  |  |  | $Mousse::SUPER_BODY->(@Mousse::SUPER_ARGS); | 
| 4535 |  |  |  |  |  |  | } | 
| 4536 |  |  |  |  |  |  |  | 
| 4537 |  |  |  |  |  |  | sub override { | 
| 4538 |  |  |  |  |  |  | # my($name, $code) = @_; | 
| 4539 | 0 |  |  | 0 | 0 |  | Mousse::Meta::Role->initialize(scalar caller)->add_override_method_modifier(@_); | 
| 4540 | 0 |  |  |  |  |  | return; | 
| 4541 |  |  |  |  |  |  | } | 
| 4542 |  |  |  |  |  |  |  | 
| 4543 |  |  |  |  |  |  | # We keep the same errors messages as Moose::Role emits, here. | 
| 4544 |  |  |  |  |  |  | sub inner { | 
| 4545 | 0 |  |  | 0 | 0 |  | Carp::croak "Roles cannot support 'inner'"; | 
| 4546 |  |  |  |  |  |  | } | 
| 4547 |  |  |  |  |  |  |  | 
| 4548 |  |  |  |  |  |  | sub augment { | 
| 4549 | 0 |  |  | 0 | 0 |  | Carp::croak "Roles cannot support 'augment'"; | 
| 4550 |  |  |  |  |  |  | } | 
| 4551 |  |  |  |  |  |  |  | 
| 4552 |  |  |  |  |  |  | sub requires { | 
| 4553 | 0 |  |  | 0 | 0 |  | my $meta = Mousse::Meta::Role->initialize(scalar caller); | 
| 4554 | 0 | 0 |  |  |  |  | $meta->throw_error("Must specify at least one method") unless @_; | 
| 4555 | 0 |  |  |  |  |  | $meta->add_required_methods(@_); | 
| 4556 | 0 |  |  |  |  |  | return; | 
| 4557 |  |  |  |  |  |  | } | 
| 4558 |  |  |  |  |  |  |  | 
| 4559 |  |  |  |  |  |  | sub excludes { | 
| 4560 | 0 |  |  | 0 | 0 |  | Mousse::Util::not_supported(); | 
| 4561 |  |  |  |  |  |  | } | 
| 4562 |  |  |  |  |  |  |  | 
| 4563 |  |  |  |  |  |  | sub init_meta{ | 
| 4564 | 0 |  |  | 0 | 0 |  | shift; | 
| 4565 | 0 |  |  |  |  |  | my %args = @_; | 
| 4566 |  |  |  |  |  |  |  | 
| 4567 | 0 | 0 |  |  |  |  | my $class = $args{for_class} | 
| 4568 |  |  |  |  |  |  | or Carp::confess("Cannot call init_meta without specifying a for_class"); | 
| 4569 |  |  |  |  |  |  |  | 
| 4570 | 0 |  | 0 |  |  |  | my $metaclass  = $args{metaclass}  || 'Mousse::Meta::Role'; | 
| 4571 |  |  |  |  |  |  |  | 
| 4572 | 0 |  |  |  |  |  | my $meta = $metaclass->initialize($class); | 
| 4573 |  |  |  |  |  |  |  | 
| 4574 |  |  |  |  |  |  | $meta->add_method(meta => sub{ | 
| 4575 | 0 |  | 0 | 0 |  |  | $metaclass->initialize(ref($_[0]) || $_[0]); | 
| 4576 | 0 |  |  |  |  |  | }); | 
| 4577 |  |  |  |  |  |  |  | 
| 4578 |  |  |  |  |  |  | # make a role type for each Mousse role | 
| 4579 | 0 | 0 |  |  |  |  | Mousse::Util::TypeConstraints::role_type($class) | 
| 4580 |  |  |  |  |  |  | unless Mousse::Util::TypeConstraints::find_type_constraint($class); | 
| 4581 |  |  |  |  |  |  |  | 
| 4582 | 0 |  |  |  |  |  | return $meta; | 
| 4583 |  |  |  |  |  |  | } | 
| 4584 |  |  |  |  |  |  |  | 
| 4585 |  |  |  |  |  |  | # Contents of Mouse::Util::MetaRole | 
| 4586 |  |  |  |  |  |  | package Mousse::Util::MetaRole; | 
| 4587 | 1 |  |  | 1 |  | 13 | use Mousse::Util; # enables strict and warnings | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 3 |  | 
| 4588 | 1 |  |  | 1 |  | 92 | use Scalar::Util (); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 1208 |  | 
| 4589 |  |  |  |  |  |  |  | 
| 4590 |  |  |  |  |  |  | sub apply_metaclass_roles { | 
| 4591 | 0 |  |  | 0 | 0 |  | my %args = @_; | 
| 4592 | 0 |  |  |  |  |  | _fixup_old_style_args(\%args); | 
| 4593 |  |  |  |  |  |  |  | 
| 4594 | 0 |  |  |  |  |  | return apply_metaroles(%args); | 
| 4595 |  |  |  |  |  |  | } | 
| 4596 |  |  |  |  |  |  |  | 
| 4597 |  |  |  |  |  |  | sub apply_metaroles { | 
| 4598 | 0 |  |  | 0 | 0 |  | my %args = @_; | 
| 4599 |  |  |  |  |  |  |  | 
| 4600 | 0 | 0 |  |  |  |  | my $for = Scalar::Util::blessed($args{for}) | 
| 4601 |  |  |  |  |  |  | ?                                     $args{for} | 
| 4602 |  |  |  |  |  |  | : Mousse::Util::get_metaclass_by_name( $args{for} ); | 
| 4603 |  |  |  |  |  |  |  | 
| 4604 | 0 | 0 |  |  |  |  | if(!$for){ | 
| 4605 | 0 |  |  |  |  |  | Carp::confess("You must pass an initialized class, but '$args{for}' has no metaclass"); | 
| 4606 |  |  |  |  |  |  | } | 
| 4607 |  |  |  |  |  |  |  | 
| 4608 | 0 | 0 |  |  |  |  | if ( Mousse::Util::is_a_metarole($for) ) { | 
| 4609 | 0 |  |  |  |  |  | return _make_new_metaclass( $for, $args{role_metaroles}, 'role' ); | 
| 4610 |  |  |  |  |  |  | } | 
| 4611 |  |  |  |  |  |  | else { | 
| 4612 | 0 |  |  |  |  |  | return _make_new_metaclass( $for, $args{class_metaroles}, 'class' ); | 
| 4613 |  |  |  |  |  |  | } | 
| 4614 |  |  |  |  |  |  | } | 
| 4615 |  |  |  |  |  |  |  | 
| 4616 |  |  |  |  |  |  | sub _make_new_metaclass { | 
| 4617 | 0 |  |  | 0 |  |  | my($for, $roles, $primary) = @_; | 
| 4618 |  |  |  |  |  |  |  | 
| 4619 | 0 | 0 |  |  |  |  | return $for unless keys %{$roles}; | 
|  | 0 |  |  |  |  |  |  | 
| 4620 |  |  |  |  |  |  |  | 
| 4621 | 0 | 0 |  |  |  |  | my $new_metaclass = exists($roles->{$primary}) | 
| 4622 |  |  |  |  |  |  | ? _make_new_class( ref $for, $roles->{$primary} ) # new class with traits | 
| 4623 |  |  |  |  |  |  | :                  ref $for; | 
| 4624 |  |  |  |  |  |  |  | 
| 4625 | 0 |  |  |  |  |  | my %classes; | 
| 4626 |  |  |  |  |  |  |  | 
| 4627 | 0 |  |  |  |  |  | for my $key ( grep { $_ ne $primary } keys %{$roles} ) { | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 4628 | 0 |  |  |  |  |  | my $metaclass; | 
| 4629 | 0 |  | 0 |  |  |  | my $attr = $for->can($metaclass = ($key . '_metaclass')) | 
| 4630 |  |  |  |  |  |  | || $for->can($metaclass = ($key . '_class')) | 
| 4631 |  |  |  |  |  |  | || $for->throw_error("Unknown metaclass '$key'"); | 
| 4632 |  |  |  |  |  |  |  | 
| 4633 | 0 |  |  |  |  |  | $classes{ $metaclass } | 
| 4634 |  |  |  |  |  |  | = _make_new_class( $for->$attr(), $roles->{$key} ); | 
| 4635 |  |  |  |  |  |  | } | 
| 4636 |  |  |  |  |  |  |  | 
| 4637 | 0 |  |  |  |  |  | return $new_metaclass->reinitialize( $for, %classes ); | 
| 4638 |  |  |  |  |  |  | } | 
| 4639 |  |  |  |  |  |  |  | 
| 4640 |  |  |  |  |  |  |  | 
| 4641 |  |  |  |  |  |  | sub _fixup_old_style_args { | 
| 4642 | 0 |  |  | 0 |  |  | my $args = shift; | 
| 4643 |  |  |  |  |  |  |  | 
| 4644 | 0 | 0 | 0 |  |  |  | return if $args->{class_metaroles} || $args->{roles_metaroles}; | 
| 4645 |  |  |  |  |  |  |  | 
| 4646 | 0 | 0 |  |  |  |  | $args->{for} = delete $args->{for_class} | 
| 4647 |  |  |  |  |  |  | if exists $args->{for_class}; | 
| 4648 |  |  |  |  |  |  |  | 
| 4649 | 0 |  |  |  |  |  | my @old_keys = qw( | 
| 4650 |  |  |  |  |  |  | attribute_metaclass_roles | 
| 4651 |  |  |  |  |  |  | method_metaclass_roles | 
| 4652 |  |  |  |  |  |  | wrapped_method_metaclass_roles | 
| 4653 |  |  |  |  |  |  | instance_metaclass_roles | 
| 4654 |  |  |  |  |  |  | constructor_class_roles | 
| 4655 |  |  |  |  |  |  | destructor_class_roles | 
| 4656 |  |  |  |  |  |  | error_class_roles | 
| 4657 |  |  |  |  |  |  |  | 
| 4658 |  |  |  |  |  |  | application_to_class_class_roles | 
| 4659 |  |  |  |  |  |  | application_to_role_class_roles | 
| 4660 |  |  |  |  |  |  | application_to_instance_class_roles | 
| 4661 |  |  |  |  |  |  | application_role_summation_class_roles | 
| 4662 |  |  |  |  |  |  | ); | 
| 4663 |  |  |  |  |  |  |  | 
| 4664 | 0 | 0 |  |  |  |  | my $for = Scalar::Util::blessed($args->{for}) | 
| 4665 |  |  |  |  |  |  | ?                                     $args->{for} | 
| 4666 |  |  |  |  |  |  | : Mousse::Util::get_metaclass_by_name( $args->{for} ); | 
| 4667 |  |  |  |  |  |  |  | 
| 4668 | 0 |  |  |  |  |  | my $top_key; | 
| 4669 | 0 | 0 |  |  |  |  | if( Mousse::Util::is_a_metaclass($for) ){ | 
| 4670 | 0 |  |  |  |  |  | $top_key = 'class_metaroles'; | 
| 4671 |  |  |  |  |  |  |  | 
| 4672 | 0 | 0 |  |  |  |  | $args->{class_metaroles}{class} = delete $args->{metaclass_roles} | 
| 4673 |  |  |  |  |  |  | if exists $args->{metaclass_roles}; | 
| 4674 |  |  |  |  |  |  | } | 
| 4675 |  |  |  |  |  |  | else { | 
| 4676 | 0 |  |  |  |  |  | $top_key = 'role_metaroles'; | 
| 4677 |  |  |  |  |  |  |  | 
| 4678 | 0 | 0 |  |  |  |  | $args->{role_metaroles}{role} = delete $args->{metaclass_roles} | 
| 4679 |  |  |  |  |  |  | if exists $args->{metaclass_roles}; | 
| 4680 |  |  |  |  |  |  | } | 
| 4681 |  |  |  |  |  |  |  | 
| 4682 | 0 |  |  |  |  |  | for my $old_key (@old_keys) { | 
| 4683 | 0 |  |  |  |  |  | my ($new_key) = $old_key =~ /^(.+)_(?:class|metaclass)_roles$/; | 
| 4684 |  |  |  |  |  |  |  | 
| 4685 | 0 | 0 |  |  |  |  | $args->{$top_key}{$new_key} = delete $args->{$old_key} | 
| 4686 |  |  |  |  |  |  | if exists $args->{$old_key}; | 
| 4687 |  |  |  |  |  |  | } | 
| 4688 |  |  |  |  |  |  |  | 
| 4689 | 0 |  |  |  |  |  | return; | 
| 4690 |  |  |  |  |  |  | } | 
| 4691 |  |  |  |  |  |  |  | 
| 4692 |  |  |  |  |  |  |  | 
| 4693 |  |  |  |  |  |  | sub apply_base_class_roles { | 
| 4694 | 0 |  |  | 0 | 0 |  | my %options = @_; | 
| 4695 |  |  |  |  |  |  |  | 
| 4696 | 0 |  |  |  |  |  | my $for = $options{for_class}; | 
| 4697 |  |  |  |  |  |  |  | 
| 4698 | 0 |  |  |  |  |  | my $meta = Mousse::Util::class_of($for); | 
| 4699 |  |  |  |  |  |  |  | 
| 4700 | 0 |  |  |  |  |  | my $new_base = _make_new_class( | 
| 4701 |  |  |  |  |  |  | $for, | 
| 4702 |  |  |  |  |  |  | $options{roles}, | 
| 4703 |  |  |  |  |  |  | [ $meta->superclasses() ], | 
| 4704 |  |  |  |  |  |  | ); | 
| 4705 |  |  |  |  |  |  |  | 
| 4706 | 0 | 0 |  |  |  |  | $meta->superclasses($new_base) | 
| 4707 |  |  |  |  |  |  | if $new_base ne $meta->name(); | 
| 4708 | 0 |  |  |  |  |  | return; | 
| 4709 |  |  |  |  |  |  | } | 
| 4710 |  |  |  |  |  |  |  | 
| 4711 |  |  |  |  |  |  | sub _make_new_class { | 
| 4712 | 0 |  |  | 0 |  |  | my($existing_class, $roles, $superclasses) = @_; | 
| 4713 |  |  |  |  |  |  |  | 
| 4714 | 0 | 0 |  |  |  |  | if(!$superclasses){ | 
| 4715 | 0 | 0 |  |  |  |  | return $existing_class if !$roles; | 
| 4716 |  |  |  |  |  |  |  | 
| 4717 | 0 |  |  |  |  |  | my $meta = Mousse::Meta::Class->initialize($existing_class); | 
| 4718 |  |  |  |  |  |  |  | 
| 4719 | 0 |  | 0 |  |  |  | return $existing_class | 
| 4720 | 0 | 0 |  |  |  |  | if !grep { !ref($_) && !$meta->does_role($_) } @{$roles}; | 
|  | 0 |  |  |  |  |  |  | 
| 4721 |  |  |  |  |  |  | } | 
| 4722 |  |  |  |  |  |  |  | 
| 4723 | 0 | 0 |  |  |  |  | return Mousse::Meta::Class->create_anon_class( | 
| 4724 |  |  |  |  |  |  | superclasses => $superclasses ? $superclasses : [$existing_class], | 
| 4725 |  |  |  |  |  |  | roles        => $roles, | 
| 4726 |  |  |  |  |  |  | cache        => 1, | 
| 4727 |  |  |  |  |  |  | )->name(); | 
| 4728 |  |  |  |  |  |  | } | 
| 4729 |  |  |  |  |  |  |  | 
| 4730 |  |  |  |  |  |  | ; | 
| 4731 |  |  |  |  |  |  |  | 
| 4732 |  |  |  |  |  |  | package Mousse; | 
| 4733 |  |  |  |  |  |  |  | 
| 4734 |  |  |  |  |  |  | our $VERSION = '0.13'; | 
| 4735 |  |  |  |  |  |  |  | 
| 4736 |  |  |  |  |  |  | Mousse::Exporter->setup_import_methods(also => 'Mousse::TOP'); | 
| 4737 |  |  |  |  |  |  |  | 
| 4738 |  |  |  |  |  |  | 1; |