File Coverage

lib/Mousse.pm
Criterion Covered Total %
statement 786 2256 34.8
branch 177 928 19.0
condition 46 393 11.7
subroutine 161 436 36.9
pod 0 239 0.0
total 1170 4252 27.5


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;