# This file was generated by tool/generate-mouse-tiny.pl from Mouse 0.43.
#
# ANY CHANGES MADE HERE WILL BE LOST!

# if regular Mouse is loaded, bail out
unless ($INC{'Mouse.pm'}) {
    # tell Perl we already have all of the Mouse files loaded:
$INC{'Mouse.pm'}                              = __FILE__;
$INC{'Mouse/Util.pm'}                         = __FILE__;
$INC{'Mouse/Exporter.pm'}                     = __FILE__;
$INC{'Mouse/Object.pm'}                       = __FILE__;
$INC{'Mouse/PurePerl.pm'}                     = __FILE__;
$INC{'Mouse/Role.pm'}                         = __FILE__;
$INC{'Mouse/Meta/Module.pm'}                  = __FILE__;
$INC{'Mouse/Meta/Method.pm'}                  = __FILE__;
$INC{'Mouse/Meta/Role.pm'}                    = __FILE__;
$INC{'Mouse/Meta/Class.pm'}                   = __FILE__;
$INC{'Mouse/Meta/TypeConstraint.pm'}          = __FILE__;
$INC{'Mouse/Meta/Attribute.pm'}               = __FILE__;
$INC{'Mouse/Meta/Role/Method.pm'}             = __FILE__;
$INC{'Mouse/Meta/Role/Composite.pm'}          = __FILE__;
$INC{'Mouse/Meta/Method/Destructor.pm'}       = __FILE__;
$INC{'Mouse/Meta/Method/Delegation.pm'}       = __FILE__;
$INC{'Mouse/Meta/Method/Constructor.pm'}      = __FILE__;
$INC{'Mouse/Meta/Method/Accessor.pm'}         = __FILE__;
$INC{'Mouse/Util/MetaRole.pm'}                = __FILE__;
$INC{'Mouse/Util/TypeConstraints.pm'}         = __FILE__;
eval sprintf("#line %d %s\n", __LINE__, __FILE__) . <<'END_OF_TINY';

# and now their contents

BEGIN{ # lib/Mouse/PurePerl.pm
package Mouse::PurePerl;

require Mouse::Util;

package
    Mouse::Util;

use strict;
use warnings;

use warnings FATAL => 'redefine'; # to avoid to load Mouse::PurePerl

use B ();

sub is_class_loaded {
    my $class = shift;

    return 0 if ref($class) || !defined($class) || !length($class);

    # walk the symbol table tree to avoid autovififying
    # \*{${main::}{"Foo::"}{"Bar::"}} == \*main::Foo::Bar::

    my $pack = \%::;
    foreach my $part (split('::', $class)) {
        $part .= '::';
        return 0 if !exists $pack->{$part};

        my $entry = \$pack->{$part};
        return 0 if ref($entry) ne 'GLOB';
        $pack = *{$entry}{HASH};
    }

    return 0 if !%{$pack};

    # check for $VERSION or @ISA
    return 1 if exists $pack->{VERSION}
             && defined *{$pack->{VERSION}}{SCALAR} && defined ${ $pack->{VERSION} };
    return 1 if exists $pack->{ISA}
             && defined *{$pack->{ISA}}{ARRAY} && @{ $pack->{ISA} } != 0;

    # check for any method
    foreach my $name( keys %{$pack} ) {
        my $entry = \$pack->{$name};
        return 1 if ref($entry) ne 'GLOB' || defined *{$entry}{CODE};
    }

    # fail
    return 0;
}


# taken from Sub::Identify
sub get_code_info {
    my ($coderef) = @_;
    ref($coderef) or return;

    my $cv = B::svref_2object($coderef);
    $cv->isa('B::CV') or return;

    my $gv = $cv->GV;
    $gv->isa('B::GV') or return;

    return ($gv->STASH->NAME, $gv->NAME);
}

sub get_code_package{
    my($coderef) = @_;

    my $cv = B::svref_2object($coderef);
    $cv->isa('B::CV') or return '';

    my $gv = $cv->GV;
    $gv->isa('B::GV') or return '';

    return $gv->STASH->NAME;
}

sub get_code_ref{
    my($package, $name) = @_;
    no strict 'refs';
    no warnings 'once';
    use warnings FATAL => 'uninitialized';
    return *{$package . '::' . $name}{CODE};
}

sub generate_isa_predicate_for {
    my($for_class, $name) = @_;

    my $predicate = sub{ Scalar::Util::blessed($_[0]) && $_[0]->isa($for_class) };

    if(defined $name){
        no strict 'refs';
        *{ caller() . '::' . $name } = $predicate;
        return;
    }

    return $predicate;
}


package
    Mouse::Util::TypeConstraints;

use Scalar::Util qw(blessed looks_like_number openhandle);

sub Any        { 1 }
sub Item       { 1 }

sub Bool       { $_[0] ? $_[0] eq '1' : 1 }
sub Undef      { !defined($_[0]) }
sub Defined    {  defined($_[0])  }
sub Value      {  defined($_[0]) && !ref($_[0]) }
sub Num        { !ref($_[0]) && looks_like_number($_[0]) }
sub Int        {  defined($_[0]) && !ref($_[0]) && $_[0] =~ /^-?[0-9]+$/ }
sub Str        {  defined($_[0]) && !ref($_[0]) }

sub Ref        { ref($_[0]) }
sub ScalarRef  { ref($_[0]) eq 'SCALAR' }
sub ArrayRef   { ref($_[0]) eq 'ARRAY'  }
sub HashRef    { ref($_[0]) eq 'HASH'   }
sub CodeRef    { ref($_[0]) eq 'CODE'   }
sub RegexpRef  { ref($_[0]) eq 'Regexp' }
sub GlobRef    { ref($_[0]) eq 'GLOB'   }

sub FileHandle {
    openhandle($_[0])  || (blessed($_[0]) && $_[0]->isa("IO::Handle"))
}

sub Object     { blessed($_[0]) && blessed($_[0]) ne 'Regexp' }

sub ClassName  { Mouse::Util::is_class_loaded($_[0]) }
sub RoleName   { (Mouse::Util::class_of($_[0]) || return 0)->isa('Mouse::Meta::Role') }

sub _parameterize_ArrayRef_for {
    my($type_parameter) = @_;
    my $check = $type_parameter->_compiled_type_constraint;

    return sub {
        foreach my $value (@{$_}) {
            return undef unless $check->($value);
        }
        return 1;
    }
}

sub _parameterize_HashRef_for {
    my($type_parameter) = @_;
    my $check = $type_parameter->_compiled_type_constraint;

    return sub {
        foreach my $value(values %{$_}){
            return undef unless $check->($value);
        }
        return 1;
    };
}

# 'Maybe' type accepts 'Any', so it requires parameters
sub _parameterize_Maybe_for {
    my($type_parameter) = @_;
    my $check = $type_parameter->_compiled_type_constraint;

    return sub{
        return !defined($_) || $check->($_);
    };
};



package
    Mouse::Meta::Module;

sub name          { $_[0]->{package} }

sub _method_map   { $_[0]->{methods} }
sub _attribute_map{ $_[0]->{attributes} }

sub namespace{
    my $name = $_[0]->{package};
    no strict 'refs';
    return \%{ $name . '::' };
}

sub add_method {
    my($self, $name, $code) = @_;

    if(!defined $name){
        $self->throw_error('You must pass a defined name');
    }
    if(!defined $code){
        $self->throw_error('You must pass a defined code');
    }

    if(ref($code) ne 'CODE'){
        $code = \&{$code}; # coerce
    }

    $self->{methods}->{$name} = $code; # Moose stores meta object here.

    my $pkg = $self->name;
    no strict 'refs';
    no warnings 'redefine', 'once';
    *{ $pkg . '::' . $name } = $code;
    return;
}

package
    Mouse::Meta::Class;

sub method_metaclass    { $_[0]->{method_metaclass}    || 'Mouse::Meta::Method'    }
sub attribute_metaclass { $_[0]->{attribute_metaclass} || 'Mouse::Meta::Attribute' }

sub constructor_class { $_[0]->{constructor_class} || 'Mouse::Meta::Method::Constructor' }
sub destructor_class  { $_[0]->{destructor_class}  || 'Mouse::Meta::Method::Destructor'  }

sub is_anon_class{
    return exists $_[0]->{anon_serial_id};
}

sub roles { $_[0]->{roles} }

sub linearized_isa { @{ get_linear_isa($_[0]->{package}) } }

sub get_all_attributes {
    my($self) = @_;
    my %attrs = map { %{ $self->initialize($_)->{attributes} } } reverse $self->linearized_isa;
    return values %attrs;
}

sub new_object {
    my $self = shift;
    my %args = (@_ == 1 ? %{$_[0]} : @_);

    my $object = bless {}, $self->name;

    $self->_initialize_object($object, \%args);
    return $object;
}

sub _initialize_object{
    my($self, $object, $args, $ignore_triggers) = @_;

    my @triggers_queue;

    foreach my $attribute ($self->get_all_attributes) {
        my $init_arg = $attribute->init_arg;
        my $slot     = $attribute->name;

        if (defined($init_arg) && exists($args->{$init_arg})) {
            $object->{$slot} = $attribute->_coerce_and_verify($args->{$init_arg}, $object);

            weaken($object->{$slot})
                if ref($object->{$slot}) && $attribute->is_weak_ref;

            if ($attribute->has_trigger) {
                push @triggers_queue, [ $attribute->trigger, $object->{$slot} ];
            }
        }
        else { # no init arg
            if ($attribute->has_default || $attribute->has_builder) {
                if (!$attribute->is_lazy) {
                    my $default = $attribute->default;
                    my $builder = $attribute->builder;
                    my $value =   $builder                ? $object->$builder()
                                : ref($default) eq 'CODE' ? $object->$default()
                                :                           $default;

                    $object->{$slot} = $attribute->_coerce_and_verify($value, $object);

                    weaken($object->{$slot})
                        if ref($object->{$slot}) && $attribute->is_weak_ref;
                }
            }
            elsif($attribute->is_required) {
                $self->throw_error("Attribute (".$attribute->name.") is required");
            }
        }
    }

    if(!$ignore_triggers){
        foreach my $trigger_and_value(@triggers_queue){
            my($trigger, $value) = @{$trigger_and_value};
            $trigger->($object, $value);
        }
    }

    if($self->is_anon_class){
        $object->{__METACLASS__} = $self;
    }

    return;
}


package
    Mouse::Meta::Role;

sub method_metaclass{ $_[0]->{method_metaclass} || 'Mouse::Meta::Role::Method' }

sub is_anon_role{
    return exists $_[0]->{anon_serial_id};
}

sub get_roles { $_[0]->{roles} }

package
    Mouse::Meta::Attribute;

require Mouse::Meta::Method::Accessor;

sub accessor_metaclass{ $_[0]->{accessor_metaclass} || 'Mouse::Meta::Method::Accessor' }

# readers

sub name                 { $_[0]->{name}                   }
sub associated_class     { $_[0]->{associated_class}       }

sub accessor             { $_[0]->{accessor}               }
sub reader               { $_[0]->{reader}                 }
sub writer               { $_[0]->{writer}                 }
sub predicate            { $_[0]->{predicate}              }
sub clearer              { $_[0]->{clearer}                }
sub handles              { $_[0]->{handles}                }

sub _is_metadata         { $_[0]->{is}                     }
sub is_required          { $_[0]->{required}               }
sub default              { $_[0]->{default}                }
sub is_lazy              { $_[0]->{lazy}                   }
sub is_lazy_build        { $_[0]->{lazy_build}             }
sub is_weak_ref          { $_[0]->{weak_ref}               }
sub init_arg             { $_[0]->{init_arg}               }
sub type_constraint      { $_[0]->{type_constraint}        }

sub trigger              { $_[0]->{trigger}                }
sub builder              { $_[0]->{builder}                }
sub should_auto_deref    { $_[0]->{auto_deref}             }
sub should_coerce        { $_[0]->{coerce}                 }

sub documentation        { $_[0]->{documentation}          }

# predicates

sub has_accessor         { exists $_[0]->{accessor}        }
sub has_reader           { exists $_[0]->{reader}          }
sub has_writer           { exists $_[0]->{writer}          }
sub has_predicate        { exists $_[0]->{predicate}       }
sub has_clearer          { exists $_[0]->{clearer}         }
sub has_handles          { exists $_[0]->{handles}         }

sub has_default          { exists $_[0]->{default}         }
sub has_type_constraint  { exists $_[0]->{type_constraint} }
sub has_trigger          { exists $_[0]->{trigger}         }
sub has_builder          { exists $_[0]->{builder}         }

sub has_documentation    { exists $_[0]->{documentation}   }

package
    Mouse::Meta::TypeConstraint;

sub name    { $_[0]->{name}    }
sub parent  { $_[0]->{parent}  }
sub message { $_[0]->{message} }

sub _compiled_type_constraint{ $_[0]->{compiled_type_constraint} }

sub _compiled_type_coercion  { $_[0]->{_compiled_type_coercion}  }

sub has_coercion{ exists $_[0]->{_compiled_type_coercion} }


sub compile_type_constraint{
    my($self) = @_;

    # add parents first
    my @checks;
    for(my $parent = $self->{parent}; defined $parent; $parent = $parent->{parent}){
         if($parent->{hand_optimized_type_constraint}){
            unshift @checks, $parent->{hand_optimized_type_constraint};
            last; # a hand optimized constraint must include all the parents
        }
        elsif($parent->{constraint}){
            unshift @checks, $parent->{constraint};
        }
    }

    # then add child
    if($self->{constraint}){
        push @checks, $self->{constraint};
    }

    if($self->{type_constraints}){ # Union
        my @types = map{ $_->{compiled_type_constraint} } @{ $self->{type_constraints} };
        push @checks, sub{
            foreach my $c(@types){
                return 1 if $c->($_[0]);
            }
            return 0;
        };
    }

    if(@checks == 0){
        $self->{compiled_type_constraint} = \&Mouse::Util::TypeConstraints::Any;
    }
    else{
        $self->{compiled_type_constraint} =  sub{
            my(@args) = @_;
            local $_ = $args[0];
            foreach my $c(@checks){
                return undef if !$c->(@args);
            }
            return 1;
        };
    }
    return;
}

package
    Mouse::Object;


sub BUILDARGS {
    my $class = shift;

    if (scalar @_ == 1) {
        (ref($_[0]) eq 'HASH')
            || $class->meta->throw_error("Single parameters to new() must be a HASH ref");

        return {%{$_[0]}};
    }
    else {
        return {@_};
    }
}

sub new {
    my $class = shift;

    $class->meta->throw_error('Cannot call new() on an instance') if ref $class;

    my $args = $class->BUILDARGS(@_);

    my $meta = Mouse::Meta::Class->initialize($class);
    my $self = $meta->new_object($args);

    # BUILDALL
    if( $self->can('BUILD') ) {
        for my $class (reverse $meta->linearized_isa) {
            my $build = Mouse::Util::get_code_ref($class, 'BUILD')
                || next;

            $self->$build($args);
        }
    }

    return $self;
}

sub DESTROY {
    my $self = shift;

    return unless $self->can('DEMOLISH'); # short circuit

    local $?;

    my $e = do{
        local $@;
        eval{

            # DEMOLISHALL

            # We cannot count on being able to retrieve a previously made
            # metaclass, _or_ being able to make a new one during global
            # destruction. However, we should still be able to use mro at
            # that time (at least tests suggest so ;)

            foreach my $class (@{ Mouse::Util::get_linear_isa(ref $self) }) {
                my $demolish = Mouse::Util::get_code_ref($class, 'DEMOLISH')
                    || next;

                $self->$demolish();
            }
        };
        $@;
    };

    no warnings 'misc';
    die $e if $e; # rethrow
}

}
BEGIN{ # lib/Mouse/Exporter.pm
package Mouse::Exporter;
use strict;
use warnings;

use Carp qw(confess);

my %SPEC;

use constant _strict_bits => strict::bits(qw(subs refs vars));

# it must be "require", because Mouse::Util depends on Mouse::Exporter,
# which depends on Mouse::Util::import()
require Mouse::Util;

sub import{
    $^H              |= _strict_bits;         # strict->import;
    ${^WARNING_BITS} |= $warnings::Bits{all}; # warnings->import;
    return;
}


sub setup_import_methods{
    my($class, %args) = @_;

    my $exporting_package = $args{exporting_package} ||= caller();

    my($import, $unimport) = $class->build_import_methods(%args);

    no strict 'refs';

    *{$exporting_package . '::import'}    = $import;
    *{$exporting_package . '::unimport'}  = $unimport;

    # for backward compatibility
    *{$exporting_package . '::export_to_level'} = sub{
        my($package, $level, undef, @args) = @_; # the third argument is redundant
        $package->import({ into_level => $level + 1 }, @args);
    };
    *{$exporting_package . '::export'} = sub{
        my($package, $into, @args) = @_;
        $package->import({ into => $into }, @args);
    };
    return;
}

sub build_import_methods{
    my($class, %args) = @_;

    my $exporting_package = $args{exporting_package} ||= caller();

    $SPEC{$exporting_package} = \%args;

    # canonicalize args
    my @export_from;
    if($args{also}){
        my %seen;
        my @stack = ($exporting_package);

        while(my $current = shift @stack){
            push @export_from, $current;

            my $also = $SPEC{$current}{also} or next;
            push @stack, grep{ !$seen{$_}++ } ref($also) ? @{ $also } : $also;
        }
    }
    else{
        @export_from = ($exporting_package);
    }

    {
        my %exports;
        my @removables;
        my @all;

        my @init_meta_methods;

        foreach my $package(@export_from){
            my $spec = $SPEC{$package} or next;

            if(my $as_is = $spec->{as_is}){
                foreach my $thingy (@{$as_is}){
                    my($code_package, $code_name, $code);

                    if(ref($thingy)){
                        $code = $thingy;
                        ($code_package, $code_name) = Mouse::Util::get_code_info($code);
                    }
                    else{
                        no strict 'refs';
                        $code_package = $package;
                        $code_name    = $thingy;
                        $code         = \&{ $code_package . '::' . $code_name };
                   }

                    push @all, $code_name;
                    $exports{$code_name} = $code;
                    if($code_package eq $package){
                        push @removables, $code_name;
                    }
                }
            }

            if(my $init_meta = $package->can('init_meta')){
                if(!grep{ $_ == $init_meta } @init_meta_methods){
                    push @init_meta_methods, $init_meta;
                }
            }
        }
        $args{EXPORTS}    = \%exports;
        $args{REMOVABLES} = \@removables;

        $args{groups}{all}     ||= \@all;

        if(my $default_list = $args{groups}{default}){
            my %default;
            foreach my $keyword(@{$default_list}){
                $default{$keyword} = $exports{$keyword}
                    || confess(qq{The $exporting_package package does not export "$keyword"});
            }
            $args{DEFAULT} = \%default;
        }
        else{
            $args{groups}{default} ||= \@all;
            $args{DEFAULT}           = $args{EXPORTS};
        }

        if(@init_meta_methods){
            $args{INIT_META} = \@init_meta_methods;
        }
    }

    return (\&do_import, \&do_unimport);
}


# the entity of general import()
sub do_import {
    my($package, @args) = @_;

    my $spec = $SPEC{$package}
        || confess("The package $package package does not use Mouse::Exporter");

    my $into = _get_caller_package(ref($args[0]) ? shift @args : undef);

    my @exports;
    my @traits;

    while(@args){
        my $arg = shift @args;
        if($arg =~ s/^-//){
            if($arg eq 'traits'){
                push @traits, ref($args[0]) ? @{shift(@args)} : shift(@args);
            }
            else {
                Mouse::Util::not_supported("-$arg");
            }
        }
        elsif($arg =~ s/^://){
            my $group = $spec->{groups}{$arg}
                || confess(qq{The $package package does not export the group "$arg"});
            push @exports, @{$group};
        }
        else{
            push @exports, $arg;
        }
    }

    $^H              |= _strict_bits;         # strict->import;
    ${^WARNING_BITS} |= $warnings::Bits{all}; # warnings->import;

    if($spec->{INIT_META}){
        my $meta;
        foreach my $init_meta(@{$spec->{INIT_META}}){
            $meta = $into->$init_meta(for_class => $into);
        }

        if(@traits){
            my $type = (split /::/, ref $meta)[-1]; # e.g. "Class" for "My::Meta::Class"
            @traits =
                map{
                    ref($_) ? $_
                            : Mouse::Util::resolve_metaclass_alias($type => $_, trait => 1)
                } @traits;

            require Mouse::Util::MetaRole;
            Mouse::Util::MetaRole::apply_metaclass_roles(
                for_class       => $into,
                metaclass_roles => \@traits,
            );
        }
    }
    elsif(@traits){
        Carp::confess("Cannot provide traits when $package does not have an init_meta() method");
    }

    if(@exports){
        foreach my $keyword(@exports){
            no strict 'refs';
            *{$into.'::'.$keyword} = $spec->{EXPORTS}{$keyword}
                || confess(qq{The $package package does not export "$keyword"});
        }
    }
    else{
        my $default = $spec->{DEFAULT};
        while(my($keyword, $code) = each %{$default}){
            no strict 'refs';
            *{$into.'::'.$keyword} = $code;
        }
    }
    return;
}

# the entity of general unimport()
sub do_unimport {
    my($package, $arg) = @_;

    my $spec = $SPEC{$package}
        || confess("The package $package does not use Mouse::Exporter");

    my $from = _get_caller_package($arg);

    my $stash = do{
        no strict 'refs';
        \%{$from . '::'}
    };

    for my $keyword (@{ $spec->{REMOVABLES} }) {
        my $gv = \$stash->{$keyword};
        if(ref($gv) eq 'GLOB' && *{$gv}{CODE} == $spec->{EXPORTS}{$keyword}){ # make sure it is from us
            delete $stash->{$keyword};
        }
    }
    return;
}

# 1 extra level because it's called by import so there's a layer
# of indirection
sub _LEVEL(){ 1 }

sub _get_caller_package {
    my($arg) = @_;

    if(ref $arg){
        return defined($arg->{into})       ? $arg->{into}
             : defined($arg->{into_level}) ? scalar caller(_LEVEL + $arg->{into_level})
             :                               scalar caller(_LEVEL);
    }
    else{
        return scalar caller(_LEVEL);
    }
}

#sub _spec{ %SPEC }

}
BEGIN{ # lib/Mouse/Util.pm
package Mouse::Util;
use Mouse::Exporter; # enables strict and warnings

sub get_linear_isa($;$); # must be here

BEGIN{
    # This is used in Mouse::PurePerl
    Mouse::Exporter->setup_import_methods(
        as_is => [qw(
            find_meta
            does_role
            resolve_metaclass_alias
            apply_all_roles
            english_list

            load_class
            is_class_loaded

            get_linear_isa
            get_code_info

            get_code_package
            get_code_ref

            not_supported

            does meta dump
        )],
        groups => {
            default => [], # export no functions by default

            # The ':meta' group is 'use metaclass' for Mouse
            meta    => [qw(does meta dump)],
        },
    );


    # Because Mouse::Util is loaded first in all the Mouse sub-modules,
    # XS loader is placed here, not in Mouse.pm.

    our $VERSION = '0.43';

    my $xs = !(exists $INC{'Mouse/PurePerl.pm'} || $ENV{MOUSE_PUREPERL});

    if($xs){
        # XXX: XSLoader tries to get the object path from caller's file name
        #      $hack_mouse_file fools its mechanism

        (my $hack_mouse_file = __FILE__) =~ s/.Util//; # .../Mouse/Util.pm -> .../Mouse.pm
        $xs = eval sprintf("#line %d %s\n", __LINE__, $hack_mouse_file) . q{
            require XSLoader;
            XSLoader::load('Mouse', $VERSION);
            Mouse::Util->import({ into => 'Mouse::Meta::Method::Constructor::XS' }, ':meta');
            Mouse::Util->import({ into => 'Mouse::Meta::Method::Destructor::XS'  }, ':meta');
            Mouse::Util->import({ into => 'Mouse::Meta::Method::Accessor::XS'    }, ':meta');
            return 1;
        };
        #warn $@ if $@;
    }

    if(!$xs){
        require 'Mouse/PurePerl.pm'; # we don't want to create its namespace
    }

    *MOUSE_XS = sub(){ $xs };
}

use Carp         ();
use Scalar::Util ();

use constant _MOUSE_VERBOSE => !!$ENV{MOUSE_VERBOSE};

# aliases as public APIs
# it must be 'require', not 'use', because Mouse::Meta::Module depends on Mouse::Util
require Mouse::Meta::Module; # for the entities of metaclass cache utilities

BEGIN {
    *class_of                    = \&Mouse::Meta::Module::_class_of;
    *get_metaclass_by_name       = \&Mouse::Meta::Module::_get_metaclass_by_name;
    *get_all_metaclass_instances = \&Mouse::Meta::Module::_get_all_metaclass_instances;
    *get_all_metaclass_names     = \&Mouse::Meta::Module::_get_all_metaclass_names;

    # is-a predicates
    generate_isa_predicate_for('Mouse::Meta::TypeConstraint' => 'is_a_type_constraint');
    generate_isa_predicate_for('Mouse::Meta::Class'          => 'is_a_metaclass');
    generate_isa_predicate_for('Mouse::Meta::Role'           => 'is_a_metarole');
}

our $in_global_destruction = 0;
END{ $in_global_destruction = 1 }

# Moose::Util compatible utilities

sub find_meta{
    return class_of( $_[0] );
}

sub does_role{
    my ($class_or_obj, $role_name) = @_;

    my $meta = class_of($class_or_obj);

    (defined $role_name)
        || ($meta || 'Mouse::Meta::Class')->throw_error("You must supply a role name to does()");

    return defined($meta) && $meta->does_role($role_name);
}

BEGIN {
    my $get_linear_isa;
    if ($] >= 5.009_005) {
        require mro;
        $get_linear_isa = \&mro::get_linear_isa;
    } else {
#       VVVVV   CODE TAKEN FROM MRO::COMPAT   VVVVV
        my $_get_linear_isa_dfs; # this recurses so it isn't pretty
        $_get_linear_isa_dfs = sub {
            my($classname) = @_;

            my @lin = ($classname);
            my %stored;

            no strict 'refs';
            foreach my $parent (@{"$classname\::ISA"}) {
                my $plin = $_get_linear_isa_dfs->($parent);
                foreach  my $p(@$plin) {
                    next if exists $stored{$p};
                    push(@lin, $p);
                    $stored{$p} = 1;
                }
            }
            return \@lin;
        };
#       ^^^^^   CODE TAKEN FROM MRO::COMPAT   ^^^^^

        eval{ require Class::C3 };

        # MRO::Compat::__get_linear_isa has no prototype, so
        # we define a prototyped version for compatibility with core's
        # See also MRO::Compat::__get_linear_isa.
        $get_linear_isa = sub ($;$){
            my($classname, $type) = @_;
            package # hide from PAUSE
                Class::C3;
            if(!defined $type){
                our %MRO;
                $type = exists $MRO{$classname} ? 'c3' : 'dfs';
            }
            return $type eq 'c3'
                ? [calculateMRO($classname)]
                : $_get_linear_isa_dfs->($classname);
        };
    }

    *get_linear_isa = $get_linear_isa;
}


# taken from Mouse::Util (0.90)
{
    my %cache;

    sub resolve_metaclass_alias {
        my ( $type, $metaclass_name, %options ) = @_;

        my $cache_key = $type . q{ } . ( $options{trait} ? '-Trait' : '' );

        return $cache{$cache_key}{$metaclass_name} ||= do{

            my $possible_full_name = join '::',
                'Mouse::Meta', $type, 'Custom', ($options{trait} ? 'Trait' : ()), $metaclass_name
            ;

            my $loaded_class = load_first_existing_class(
                $possible_full_name,
                $metaclass_name
            );

            $loaded_class->can('register_implementation')
                ? $loaded_class->register_implementation
                : $loaded_class;
        };
    }
}

# Utilities from Class::MOP

sub get_code_info;
sub get_code_package;

# taken from Class/MOP.pm
sub is_valid_class_name {
    my $class = shift;

    return 0 if ref($class);
    return 0 unless defined($class);

    return 1 if $class =~ /\A \w+ (?: :: \w+ )* \z/xms;

    return 0;
}

# taken from Class/MOP.pm
sub load_first_existing_class {
    my @classes = @_
      or return;

    my %exceptions;
    for my $class (@classes) {
        my $e = _try_load_one_class($class);

        if ($e) {
            $exceptions{$class} = $e;
        }
        else {
            return $class;
        }
    }

    # not found
    Carp::confess join(
        "\n",
        map {
            sprintf( "Could not load class (%s) because : %s",
                $_, $exceptions{$_} )
          } @classes
    );
}

# taken from Class/MOP.pm
my %is_class_loaded_cache;
sub _try_load_one_class {
    my $class = shift;

    unless ( is_valid_class_name($class) ) {
        my $display = defined($class) ? $class : 'undef';
        Carp::confess "Invalid class name ($display)";
    }

    return undef if $is_class_loaded_cache{$class} ||= is_class_loaded($class);

    my $file = $class . '.pm';
    $file =~ s{::}{/}g;

    return do {
        local $@;
        eval { require($file) };
        $@;
    };
}


sub load_class {
    my $class = shift;
    my $e = _try_load_one_class($class);
    Carp::confess "Could not load class ($class) because : $e" if $e;

    return 1;
}

sub is_class_loaded;

sub apply_all_roles {
    my $applicant = Scalar::Util::blessed($_[0])
        ?                                shift   # instance
        : Mouse::Meta::Class->initialize(shift); # class or role name

    my @roles;

    # Basis of Data::OptList
    my $max = scalar(@_);
    for (my $i = 0; $i < $max ; $i++) {
        if ($i + 1 < $max && ref($_[$i + 1])) {
            push @roles, [ $_[$i] => $_[++$i] ];
        } else {
            push @roles, [ $_[$i] => undef ];
        }
        my $role_name = $roles[-1][0];
        load_class($role_name);

        is_a_metarole( get_metaclass_by_name($role_name) )
            || $applicant->meta->throw_error("You can only consume roles, $role_name is not a Mouse role");
    }

    if ( scalar @roles == 1 ) {
        my ( $role_name, $params ) = @{ $roles[0] };
        get_metaclass_by_name($role_name)->apply( $applicant, defined $params ? $params : () );
    }
    else {
        Mouse::Meta::Role->combine(@roles)->apply($applicant);
    }
    return;
}

# taken from Moose::Util 0.90
sub english_list {
    return $_[0] if @_ == 1;

    my @items = sort @_;

    return "$items[0] and $items[1]" if @items == 2;

    my $tail = pop @items;

    return join q{, }, @items, "and $tail";
}

# common utilities

sub not_supported{
    my($feature) = @_;

    $feature ||= ( caller(1) )[3]; # subroutine name

    local $Carp::CarpLevel = $Carp::CarpLevel + 1;
    Carp::confess("Mouse does not currently support $feature");
}

# general meta() method
sub meta :method{
    return Mouse::Meta::Class->initialize(ref($_[0]) || $_[0]);
}

# general dump() method
sub dump :method {
    my($self, $maxdepth) = @_;

    require 'Data/Dumper.pm'; # we don't want to create its namespace
    my $dd = Data::Dumper->new([$self]);
    $dd->Maxdepth(defined($maxdepth) ? $maxdepth : 2);
    $dd->Indent(1);
    return $dd->Dump();
}

# general does() method
sub does :method;
*does = \&does_role; # alias

}
BEGIN{ # lib/Mouse/Meta/TypeConstraint.pm
package Mouse::Meta::TypeConstraint;
use Mouse::Util qw(:meta); # enables strict and warnings

use overload
    'bool'   => sub { 1 },             # always true

    '""'     => sub { $_[0]->name },   # stringify to tc name

    '|'      => sub {                  # or-combination
        require Mouse::Util::TypeConstraints;
        return Mouse::Util::TypeConstraints::find_or_parse_type_constraint(
            "$_[0] | $_[1]",
        );
    },

    fallback => 1;

use Carp         ();

sub new {
    my($class, %args) = @_;

    $args{name} = '__ANON__' if !defined $args{name};

    my $check = delete $args{optimized};

    if($args{_compiled_type_constraint}){
        Carp::cluck("'_compiled_type_constraint' has been deprecated, use 'optimized' instead")
            if Mouse::Util::_MOUSE_VERBOSE;

        $check = $args{_compiled_type_constraint};
    }

    if($check){
        $args{hand_optimized_type_constraint} = $check;
        $args{compiled_type_constraint}       = $check;
    }

    $check = $args{constraint};

    if(defined($check) && ref($check) ne 'CODE'){
        Carp::confess("Constraint for $args{name} is not a CODE reference");
    }

    $args{package_defined_in} ||= caller;

    my $self = bless \%args, $class;
    $self->compile_type_constraint() if !$self->{hand_optimized_type_constraint};

    if($self->{type_constraints}){ # Union
        my @coercions;
        foreach my $type(@{$self->{type_constraints}}){
            if($type->has_coercion){
                push @coercions, $type;
            }
        }
        if(@coercions){
            $self->{_compiled_type_coercion} = sub {
                my($thing) = @_;
                foreach my $type(@coercions){
                    my $value = $type->coerce($thing);
                    return $value if $self->check($value);
                }
                return $thing;
            };
        }
    }

    return $self;
}

sub create_child_type{
    my $self = shift;
    # XXX: FIXME
    return ref($self)->new(
        # a child inherits its parent's attributes
        %{$self},

        # but does not inherit 'compiled_type_constraint' and 'hand_optimized_type_constraint'
        compiled_type_constraint       => undef,
        hand_optimized_type_constraint => undef,

        # and is given child-specific args, of course.
        @_,

        # and its parent
        parent => $self,
   );
}

sub _add_type_coercions{
    my $self = shift;

    my $coercions = ($self->{_coercion_map} ||= []);
    my %has       = map{ $_->[0] => undef } @{$coercions};

    for(my $i = 0; $i < @_; $i++){
        my $from   = $_[  $i];
        my $action = $_[++$i];

        if(exists $has{$from}){
            Carp::confess("A coercion action already exists for '$from'");
        }

        my $type = Mouse::Util::TypeConstraints::find_or_parse_type_constraint($from)
            or Carp::confess("Could not find the type constraint ($from) to coerce from");

        push @{$coercions}, [ $type => $action ];
    }

    # compile
    if(exists $self->{type_constraints}){ # union type
        Carp::confess("Cannot add additional type coercions to Union types");
    }
    else{
        $self->{_compiled_type_coercion} = sub {
           my($thing) = @_;
           foreach my $pair (@{$coercions}) {
                #my ($constraint, $converter) = @$pair;
                if ($pair->[0]->check($thing)) {
                  local $_ = $thing;
                  return $pair->[1]->($thing);
                }
           }
           return $thing;
        };
    }
    return;
}

sub check {
    my $self = shift;
    return $self->_compiled_type_constraint->(@_);
}

sub coerce {
    my $self = shift;

    return $_[0] if $self->_compiled_type_constraint->(@_);

    my $coercion = $self->_compiled_type_coercion;
    return $coercion ? $coercion->(@_) : $_[0];
}

sub get_message {
    my ($self, $value) = @_;
    if ( my $msg = $self->message ) {
        local $_ = $value;
        return $msg->($value);
    }
    else {
        $value = ( defined $value ? overload::StrVal($value) : 'undef' );
        return "Validation failed for '$self' failed with value $value";
    }
}

sub is_a_type_of{
    my($self, $other) = @_;

    # ->is_a_type_of('__ANON__') is always false
    return 0 if !ref($other) && $other eq '__ANON__';

    (my $other_name = $other) =~ s/\s+//g;

    return 1 if $self->name eq $other_name;

    if(exists $self->{type_constraints}){ # union
        foreach my $type(@{$self->{type_constraints}}){
            return 1 if $type->name eq $other_name;
        }
    }

    for(my $parent = $self->parent; defined $parent; $parent = $parent->parent){
        return 1 if $parent->name eq $other_name;
    }

    return 0;
}

# See also Moose::Meta::TypeConstraint::Parameterizable
sub parameterize{
    my($self, $param, $name) = @_;

    if(!ref $param){
        require Mouse::Util::TypeConstraints;
        $param = Mouse::Util::TypeConstraints::find_or_create_isa_type_constraint($param);
    }

    $name ||= sprintf '%s[%s]', $self->name, $param->name;

    my $generator = $self->{constraint_generator}
        || Carp::confess("The $name constraint cannot be used, because $param doesn't subtype from a parameterizable type");

    return Mouse::Meta::TypeConstraint->new(
        name        => $name,
        parent      => $self,
        parameter   => $param,
        constraint  => $generator->($param), # must be 'constraint', not 'optimized'

        type        => 'Parameterized',
    );
}

}
BEGIN{ # lib/Mouse/Util/TypeConstraints.pm
package Mouse::Util::TypeConstraints;
use Mouse::Util qw(does_role not_supported); # enables strict and warnings

use Carp qw(confess);
use Scalar::Util ();

use Mouse::Meta::TypeConstraint;
use Mouse::Exporter;

Mouse::Exporter->setup_import_methods(
    as_is => [qw(
        as where message optimize_as
        from via
        type subtype coerce class_type role_type enum
        find_type_constraint
    )],
);

my %TYPE;

sub as          ($) { (as          => $_[0]) }
sub where       (&) { (where       => $_[0]) }
sub message     (&) { (message     => $_[0]) }
sub optimize_as (&) { (optimize_as => $_[0]) }

sub from    { @_ }
sub via (&) { $_[0] }

BEGIN {
    my %builtins = (
        Any        => undef, # null check
        Item       => undef, # null check
        Maybe      => undef, # null check

        Bool       => \&Bool,
        Undef      => \&Undef,
        Defined    => \&Defined,
        Value      => \&Value,
        Num        => \&Num,
        Int        => \&Int,
        Str        => \&Str,
        Ref        => \&Ref,

        ScalarRef  => \&ScalarRef,
        ArrayRef   => \&ArrayRef,
        HashRef    => \&HashRef,
        CodeRef    => \&CodeRef,
        RegexpRef  => \&RegexpRef,
        GlobRef    => \&GlobRef,

        FileHandle => \&FileHandle,

        Object     => \&Object,

        ClassName  => \&ClassName,
        RoleName   => \&RoleName,
    );

    while (my ($name, $code) = each %builtins) {
        $TYPE{$name} = Mouse::Meta::TypeConstraint->new(
            name      => $name,
            optimized => $code,
        );
    }

    sub optimized_constraints { # DEPRECATED
        Carp::cluck('optimized_constraints() has been deprecated');
        return \%TYPE;
    }

    my @builtins = keys %TYPE;
    sub list_all_builtin_type_constraints { @builtins }

    sub list_all_type_constraints         { keys %TYPE }
}

sub _create_type{
    my $mode = shift;

    my $name;
    my %args;

    if(@_ == 1 && ref $_[0]){   # @_ : { name => $name, where => ... }
        %args = %{$_[0]};
    }
    elsif(@_ == 2 && ref $_[1]){ # @_ : $name => { where => ... }
        $name = $_[0];
        %args = %{$_[1]};
    }
    elsif(@_ % 2){               # @_ : $name => ( where => ... )
        ($name, %args) = @_;
    }
    else{                        # @_ : (name => $name, where => ...)
        %args = @_;
    }

    if(!defined $name){
        if(!defined($name = $args{name})){
            $name = '__ANON__';
        }
    }

    $args{name} = $name;
    my $parent;
    if($mode eq 'subtype'){
        $parent = delete $args{as};
        if(!$parent){
            $parent = delete $args{name};
            $name   = '__ANON__';
        }
    }

    my $package_defined_in = $args{package_defined_in} ||= caller(1);

    my $existing = $TYPE{$name};
    if($existing && $existing->{package_defined_in} ne $package_defined_in){
        confess("The type constraint '$name' has already been created in "
              . "$existing->{package_defined_in} and cannot be created again in $package_defined_in");
    }

    $args{constraint} = delete $args{where}        if exists $args{where};
    $args{optimized}  = delete $args{optimized_as} if exists $args{optimized_as};

    my $constraint;
    if($mode eq 'subtype'){
        $constraint = find_or_create_isa_type_constraint($parent)->create_child_type(%args);
    }
    else{
        $constraint = Mouse::Meta::TypeConstraint->new(%args);
    }

    return $TYPE{$name} = $constraint;
}

sub type {
    return _create_type('type', @_);
}

sub subtype {
    return _create_type('subtype', @_);
}

sub coerce {
    my $type_name = shift;

    my $type = find_type_constraint($type_name)
        or confess("Cannot find type '$type_name', perhaps you forgot to load it.");

    $type->_add_type_coercions(@_);
    return;
}

sub class_type {
    my($name, $options) = @_;
    my $class = $options->{class} || $name;
    return _create_type 'subtype', $name => (
        as           => 'Object',
        optimized_as => Mouse::Util::generate_isa_predicate_for($class),

        type => 'Class',
    );
}

sub role_type {
    my($name, $options) = @_;
    my $role = $options->{role} || $name;
    return _create_type 'subtype', $name => (
        as           => 'Object',
        optimized_as => sub { Scalar::Util::blessed($_[0]) && does_role($_[0], $role) },

        type => 'Role',
    );
}

sub typecast_constraints { # DEPRECATED
    my($class, $pkg, $type, $value) = @_;
    Carp::croak("wrong arguments count") unless @_ == 4;

    Carp::cluck("typecast_constraints() has been deprecated, which was an internal utility anyway");

    return $type->coerce($value);
}

sub enum {
    my($name, %valid);

    # enum ['small', 'medium', 'large']
    if (ref($_[0]) eq 'ARRAY') {
        %valid = map{ $_ => undef } @{ $_[0] };
        $name  = sprintf '(%s)', join '|', sort @{$_[0]};
    }
    # enum size => 'small', 'medium', 'large'
    else{
        $name  = shift;
        %valid = map{ $_ => undef } @_;
    }
    return _create_type 'type', $name => (
        optimized_as  => sub{ defined($_[0]) && !ref($_[0]) && exists $valid{$_[0]} },

        type => 'Enum',
    );
}

sub _find_or_create_regular_type{
    my($spec)  = @_;

    return $TYPE{$spec} if exists $TYPE{$spec};

    my $meta = Mouse::Util::get_metaclass_by_name($spec)
        or return undef;

    if(Mouse::Util::is_a_metarole($meta)){
        return role_type($spec);
    }
    else{
        return class_type($spec);
    }
}

$TYPE{ArrayRef}{constraint_generator} = \&_parameterize_ArrayRef_for;
$TYPE{HashRef}{constraint_generator}  = \&_parameterize_HashRef_for;
$TYPE{Maybe}{constraint_generator}    = \&_parameterize_Maybe_for;

sub _find_or_create_parameterized_type{
    my($base, $param) = @_;

    my $name = sprintf '%s[%s]', $base->name, $param->name;

    $TYPE{$name} ||= $base->parameterize($param, $name);
}

sub _find_or_create_union_type{
    my @types = sort map{ $_->{type_constraints} ? @{$_->{type_constraints}} : $_ } @_;

    my $name = join '|', @types;

    $TYPE{$name} ||= Mouse::Meta::TypeConstraint->new(
        name              => $name,
        type_constraints  => \@types,

        type              => 'Union',
    );
}

# The type parser
sub _parse_type{
    my($spec, $start) = @_;

    my @list;
    my $subtype;

    my $len = length $spec;
    my $i;

    for($i = $start; $i < $len; $i++){
        my $char = substr($spec, $i, 1);

        if($char eq '['){
            my $base = _find_or_create_regular_type( substr($spec, $start, $i - $start) )
                or return;

            ($i, $subtype) = _parse_type($spec, $i+1)
                or return;
            $start = $i+1; # reset

            push @list, _find_or_create_parameterized_type($base => $subtype);
        }
        elsif($char eq ']'){
            $len = $i+1;
            last;
        }
        elsif($char eq '|'){
            my $type = _find_or_create_regular_type( substr($spec, $start, $i - $start) );

            if(!defined $type){
                # XXX: Mouse creates a new class type, but Moose does not.
                $type = class_type( substr($spec, $start, $i - $start) );
            }

            push @list, $type;

            ($i, $subtype) = _parse_type($spec, $i+1)
                or return;

            $start = $i+1; # reset

            push @list, $subtype;
        }
    }
    if($i - $start){
        my $type = _find_or_create_regular_type( substr $spec, $start, $i - $start );

        if(defined $type){
            push @list, $type;
        }
        elsif($start != 0) {
            # RT #50421
            # create a new class type
            push @list, class_type( substr $spec, $start, $i - $start );
        }
    }

    if(@list == 0){
       return;
    }
    elsif(@list == 1){
        return ($len, $list[0]);
    }
    else{
        return ($len, _find_or_create_union_type(@list));
    }
}


sub find_type_constraint {
    my($spec) = @_;
    return $spec if Mouse::Util::is_a_type_constraint($spec);

    $spec =~ s/\s+//g;
    return $TYPE{$spec};
}

sub find_or_parse_type_constraint {
    my($spec) = @_;
    return $spec if Mouse::Util::is_a_type_constraint($spec);

    $spec =~ s/\s+//g;
    return $TYPE{$spec} || do{
        my($pos, $type) = _parse_type($spec, 0);
        $type;
    };
}

sub find_or_create_does_type_constraint{
    # XXX: Moose does not register a new role_type, but Mouse does.
    return find_or_parse_type_constraint(@_) || role_type(@_);
}

sub find_or_create_isa_type_constraint {
    # XXX: Moose does not register a new class_type, but Mouse does.
    return find_or_parse_type_constraint(@_) || class_type(@_);
}

}
BEGIN{ # lib/Mouse.pm
package Mouse;
use 5.006_002;

use Mouse::Exporter; # enables strict and warnings

our $VERSION = '0.43';

use Carp         qw(confess);
use Scalar::Util qw(blessed);

use Mouse::Util qw(load_class is_class_loaded get_code_package not_supported);

use Mouse::Meta::Module;
use Mouse::Meta::Class;
use Mouse::Meta::Role;
use Mouse::Meta::Attribute;
use Mouse::Object;
use Mouse::Util::TypeConstraints ();

Mouse::Exporter->setup_import_methods(
    as_is => [qw(
        extends with
        has
        before after around
        override super
        augment  inner
    ),
        \&Scalar::Util::blessed,
        \&Carp::confess,
   ],
);


sub extends {
    Mouse::Meta::Class->initialize(scalar caller)->superclasses(@_);
    return;
}

sub with {
    Mouse::Util::apply_all_roles(scalar(caller), @_);
    return;
}

sub has {
    my $meta = Mouse::Meta::Class->initialize(scalar caller);
    my $name = shift;

    $meta->throw_error(q{Usage: has 'name' => ( key => value, ... )})
        if @_ % 2; # odd number of arguments

    if(ref $name){ # has [qw(foo bar)] => (...)
        for (@{$name}){
            $meta->add_attribute($_ => @_);
        }
    }
    else{ # has foo => (...)
        $meta->add_attribute($name => @_);
    }
    return;
}

sub before {
    my $meta = Mouse::Meta::Class->initialize(scalar caller);

    my $code = pop;

    for (@_) {
        $meta->add_before_method_modifier($_ => $code);
    }
    return;
}

sub after {
    my $meta = Mouse::Meta::Class->initialize(scalar caller);

    my $code = pop;

    for (@_) {
        $meta->add_after_method_modifier($_ => $code);
    }
    return;
}

sub around {
    my $meta = Mouse::Meta::Class->initialize(scalar caller);

    my $code = pop;

    for (@_) {
        $meta->add_around_method_modifier($_ => $code);
    }
    return;
}

our $SUPER_PACKAGE;
our $SUPER_BODY;
our @SUPER_ARGS;

sub super {
    # This check avoids a recursion loop - see
    # t/100_bugs/020_super_recursion.t
    return if  defined $SUPER_PACKAGE && $SUPER_PACKAGE ne caller();
    return if !defined $SUPER_BODY;
    $SUPER_BODY->(@SUPER_ARGS);
}

sub override {
    # my($name, $method) = @_;
    Mouse::Meta::Class->initialize(scalar caller)->add_override_method_modifier(@_);
}

our %INNER_BODY;
our %INNER_ARGS;

sub inner {
    my $pkg = caller();
    if ( my $body = $INNER_BODY{$pkg} ) {
        my $args = $INNER_ARGS{$pkg};
        local $INNER_ARGS{$pkg};
        local $INNER_BODY{$pkg};
        return $body->(@{$args});
    }
    else {
        return;
    }
}

sub augment {
    #my($name, $method) = @_;
    Mouse::Meta::Class->initialize(scalar caller)->add_augment_method_modifier(@_);
    return;
}

sub init_meta {
    shift;
    my %args = @_;

    my $class = $args{for_class}
                    or confess("Cannot call init_meta without specifying a for_class");

    my $base_class = $args{base_class} || 'Mouse::Object';
    my $metaclass  = $args{metaclass}  || 'Mouse::Meta::Class';

    my $meta = $metaclass->initialize($class);

    $meta->add_method(meta => sub{
        return $metaclass->initialize(ref($_[0]) || $_[0]);
    });

    $meta->superclasses($base_class)
        unless $meta->superclasses;

    # make a class type for each Mouse class
    Mouse::Util::TypeConstraints::class_type($class)
        unless Mouse::Util::TypeConstraints::find_type_constraint($class);

    return $meta;
}

}
BEGIN{ # lib/Mouse/Meta/Attribute.pm
package Mouse::Meta::Attribute;
use Mouse::Util qw(:meta); # enables strict and warnings

use Carp ();

use Mouse::Meta::TypeConstraint;

#use Mouse::Meta::Method::Accessor;
use Mouse::Meta::Method::Delegation;

sub _process_options{
    my($class, $name, $args) = @_;

    # XXX: for backward compatibility (with method modifiers)
    if($class->can('canonicalize_args') != \&canonicalize_args){
        %{$args} = $class->canonicalize_args($name, %{$args});
    }

    # taken from Class::MOP::Attribute::new

    defined($name)
        or $class->throw_error('You must provide a name for the attribute');

    if(!exists $args->{init_arg}){
        $args->{init_arg} = $name;
    }

    # 'required' requires eigher 'init_arg', 'builder', or 'default'
    my $can_be_required = defined( $args->{init_arg} );

    if(exists $args->{builder}){
        # XXX:
        # Moose refuses a CODE ref builder, but Mouse doesn't for backward compatibility
        # This feature will be changed in a future. (gfx)
        $class->throw_error('builder must be a defined scalar value which is a method name')
            #if ref $args->{builder} || !defined $args->{builder};
            if !defined $args->{builder};

        $can_be_required++;
    }
    elsif(exists $args->{default}){
        if(ref $args->{default} && ref($args->{default}) ne 'CODE'){
            $class->throw_error("References are not allowed as default values, you must "
                              . "wrap the default of '$name' in a CODE reference (ex: sub { [] } and not [])");
        }
        $can_be_required++;
    }

    if( $args->{required} && !$can_be_required ) {
        $class->throw_error("You cannot have a required attribute ($name) without a default, builder, or an init_arg");
    }

    # taken from Mouse::Meta::Attribute->new and _process_args->

    if(exists $args->{is}){
        my $is = $args->{is};

        if($is eq 'ro'){
            $args->{reader} ||= $name;
        }
        elsif($is eq 'rw'){
            if(exists $args->{writer}){
                $args->{reader} ||= $name;
             }
             else{
                $args->{accessor} ||= $name;
             }
        }
        elsif($is eq 'bare'){
            # do nothing, but don't complain (later) about missing methods
        }
        else{
            $is = 'undef' if !defined $is;
            $class->throw_error("I do not understand this option (is => $is) on attribute ($name)");
        }
    }

    my $tc;
    if(exists $args->{isa}){
        $args->{type_constraint} = Mouse::Util::TypeConstraints::find_or_create_isa_type_constraint($args->{isa});
    }
    elsif(exists $args->{does}){
        $args->{type_constraint} = Mouse::Util::TypeConstraints::find_or_create_does_type_constraint($args->{does});
    }
    $tc = $args->{type_constraint};

    if($args->{coerce}){
        defined($tc)
            || $class->throw_error("You cannot have coercion without specifying a type constraint on attribute ($name)");

        $args->{weak_ref}
            && $class->throw_error("You cannot have a weak reference to a coerced value on attribute ($name)");
    }

    if ($args->{lazy_build}) {
        exists($args->{default})
            && $class->throw_error("You can not use lazy_build and default for the same attribute ($name)");

        $args->{lazy}      = 1;
        $args->{builder} ||= "_build_${name}";
        if ($name =~ /^_/) {
            $args->{clearer}   ||= "_clear${name}";
            $args->{predicate} ||= "_has${name}";
        }
        else {
            $args->{clearer}   ||= "clear_${name}";
            $args->{predicate} ||= "has_${name}";
        }
    }

    if ($args->{auto_deref}) {
        defined($tc)
            || $class->throw_error("You cannot auto-dereference without specifying a type constraint on attribute ($name)");

        ( $tc->is_a_type_of('ArrayRef') || $tc->is_a_type_of('HashRef') )
            || $class->throw_error("You cannot auto-dereference anything other than a ArrayRef or HashRef on attribute ($name)");
    }

    if (exists $args->{trigger}) {
        ('CODE' eq ref $args->{trigger})
            || $class->throw_error("Trigger must be a CODE ref on attribute ($name)");
    }

    if ($args->{lazy}) {
        (exists $args->{default} || defined $args->{builder})
            || $class->throw_error("You cannot have lazy attribute ($name) without specifying a default value for it");
    }

    return;
}

sub new {
    my $class = shift;
    my $name  = shift;

    my %args  = (@_ == 1) ? %{ $_[0] } : @_;

    $class->_process_options($name, \%args);

    $args{name} = $name;

    my $self = bless \%args, $class;

    # extra attributes
    if($class ne __PACKAGE__){
        $class->meta->_initialize_object($self, \%args);
    }

# XXX: there is no fast way to check attribute validity
#    my @bad = ...;
#    if(@bad){
#        @bad = sort @bad;
#        Carp::cluck("Found unknown argument(s) passed to '$name' attribute constructor in '$class': @bad");
#    }

    return $self;
}

sub has_read_method      { $_[0]->has_reader || $_[0]->has_accessor }
sub has_write_method     { $_[0]->has_writer || $_[0]->has_accessor }

sub _create_args { # DEPRECATED
    $_[0]->{_create_args} = $_[1] if @_ > 1;
    $_[0]->{_create_args}
}

sub interpolate_class{
    my($class, $args) = @_;

    if(my $metaclass = delete $args->{metaclass}){
        $class = Mouse::Util::resolve_metaclass_alias( Attribute => $metaclass );
    }

    my @traits;
    if(my $traits_ref = delete $args->{traits}){

        for (my $i = 0; $i < @{$traits_ref}; $i++) {
            my $trait = Mouse::Util::resolve_metaclass_alias(Attribute => $traits_ref->[$i], trait => 1);

            next if $class->does($trait);

            push @traits, $trait;

            # are there options?
            push @traits, $traits_ref->[++$i]
                if ref($traits_ref->[$i+1]);
        }

        if (@traits) {
            $class = Mouse::Meta::Class->create_anon_class(
                superclasses => [ $class ],
                roles        => \@traits,
                cache        => 1,
            )->name;
        }
    }

    return( $class, @traits );
}

sub canonicalize_args{ # DEPRECATED
    my ($self, $name, %args) = @_;

    Carp::cluck("$self->canonicalize_args has been deprecated."
        . "Use \$self->_process_options instead.")
            if Mouse::Util::_MOUSE_VERBOSE;

    return %args;
}

sub create { # DEPRECATED
    my ($self, $class, $name, %args) = @_;

    Carp::cluck("$self->create has been deprecated."
        . "Use \$meta->add_attribute and \$attr->install_accessors instead.")
            if Mouse::Util::_MOUSE_VERBOSE;

    # noop
    return $self;
}

sub _coerce_and_verify {
    my($self, $value, $instance) = @_;

    my $type_constraint = $self->{type_constraint};
    return $value if !defined $type_constraint;

    if ($self->should_coerce && $type_constraint->has_coercion) {
        $value = $type_constraint->coerce($value);
    }

    $self->verify_against_type_constraint($value);

    return $value;
}

sub verify_against_type_constraint {
    my ($self, $value) = @_;

    my $type_constraint = $self->{type_constraint};
    return 1 if !$type_constraint;
    return 1 if $type_constraint->check($value);

    $self->verify_type_constraint_error($self->name, $value, $type_constraint);
}

sub verify_type_constraint_error {
    my($self, $name, $value, $type) = @_;
    $self->throw_error("Attribute ($name) does not pass the type constraint because: "
        . $type->get_message($value));
}

sub coerce_constraint { # DEPRECATED
    my $type = $_[0]->{type_constraint}
        or return $_[1];

    Carp::cluck("coerce_constraint() has been deprecated, which was an internal utility anyway");

    return Mouse::Util::TypeConstraints->typecast_constraints($_[0]->associated_class->name, $type, $_[1]);
}

sub clone_and_inherit_options{
    my($self, %args) = @_;

    my($attribute_class, @traits) = ref($self)->interpolate_class(\%args);

    $args{traits} = \@traits if @traits;
    # do not inherit the 'handles' attribute
    foreach my $name(keys %{$self}){
        if(!exists $args{$name} && $name ne 'handles'){
            $args{$name} = $self->{$name};
        }
    }
    return $attribute_class->new($self->name, %args);
}

sub clone_parent { # DEPRECATED
    my $self  = shift;
    my $class = shift;
    my $name  = shift;
    my %args  = ($self->get_parent_args($class, $name), @_);

    Carp::cluck("$self->clone_parent has been deprecated."
        . "Use \$meta->add_attribute and \$attr->install_accessors instead.")
        if Mouse::Util::_MOUSE_VERBOSE;

    $self->clone_and_inherited_args($class, $name, %args);
}

sub get_parent_args { # DEPRECATED
    my $self  = shift;
    my $class = shift;
    my $name  = shift;

    for my $super ($class->linearized_isa) {
        my $super_attr = $super->can("meta") && $super->meta->get_attribute($name)
            or next;
        return %{ $super_attr->_create_args };
    }

    $self->throw_error("Could not find an attribute by the name of '$name' to inherit from");
}


sub get_read_method {
    $_[0]->reader || $_[0]->accessor
}
sub get_write_method {
    $_[0]->writer || $_[0]->accessor
}

sub get_read_method_ref{
    my($self) = @_;

    $self->{_read_method_ref} ||= do{
        my $metaclass = $self->associated_class
            or $self->throw_error('No asocciated class for ' . $self->name);

        my $reader = $self->{reader} || $self->{accessor};
        if($reader){
            $metaclass->name->can($reader);
        }
        else{
            $self->accessor_metaclass->_generate_reader($self, $metaclass);
        }
    };
}

sub get_write_method_ref{
    my($self) = @_;

    $self->{_write_method_ref} ||= do{
        my $metaclass = $self->associated_class
            or $self->throw_error('No asocciated class for ' . $self->name);

        my $reader = $self->{writer} || $self->{accessor};
        if($reader){
            $metaclass->name->can($reader);
        }
        else{
            $self->accessor_metaclass->_generate_writer($self, $metaclass);
        }
    };
}

sub _canonicalize_handles {
    my($self, $handles) = @_;

    if (ref($handles) eq 'HASH') {
        return %$handles;
    }
    elsif (ref($handles) eq 'ARRAY') {
        return map { $_ => $_ } @$handles;
    }
    elsif (ref($handles) eq 'Regexp') {
        my $class_or_role = ($self->{isa} || $self->{does})
            || $self->throw_error("Cannot delegate methods based on a Regexp without a type constraint (isa)");

        my $meta = Mouse::Meta::Class->initialize("$class_or_role"); # "" for stringify
        return map  { $_ => $_ }
               grep { !Mouse::Object->can($_) && $_ =~ $handles }
                   Mouse::Util::is_a_metarole($meta)
                        ? $meta->get_method_list
                        : $meta->get_all_method_names;
    }
    else {
        $self->throw_error("Unable to canonicalize the 'handles' option with $handles");
    }
}

sub associate_method{
    my ($attribute, $method_name) = @_;
    $attribute->{associated_methods}++;
    return;
}

sub delegation_metaclass() { 'Mouse::Meta::Method::Delegation' }

sub install_accessors{
    my($attribute) = @_;

    my $metaclass      = $attribute->associated_class;
    my $accessor_class = $attribute->accessor_metaclass;

    foreach my $type(qw(accessor reader writer predicate clearer)){
        if(exists $attribute->{$type}){
            my $generator = '_generate_' . $type;
            my $code      = $accessor_class->$generator($attribute, $metaclass);
            $metaclass->add_method($attribute->{$type} => $code);
            $attribute->associate_method($attribute->{$type});
        }
    }

    # install delegation
    if(exists $attribute->{handles}){
        my $delegation_class = $attribute->delegation_metaclass;
        my %handles = $attribute->_canonicalize_handles($attribute->{handles});
        my $reader  = $attribute->get_read_method_ref;

        while(my($handle_name, $method_to_call) = each %handles){
            my $code = $delegation_class->_generate_delegation($attribute, $metaclass,
                $reader, $handle_name, $method_to_call);

            $metaclass->add_method($handle_name => $code);
            $attribute->associate_method($handle_name);
        }
    }

    if($attribute->can('create') != \&create){
        # backword compatibility
        $attribute->create($metaclass, $attribute->name, %{$attribute});
    }

    return;
}

sub throw_error{
    my $self = shift;

    my $metaclass = (ref $self && $self->associated_class) || 'Mouse::Meta::Class';
    $metaclass->throw_error(@_, depth => 1);
}

}
BEGIN{ # lib/Mouse/Meta/Class.pm
package Mouse::Meta::Class;
use Mouse::Util qw/:meta get_linear_isa not_supported/; # enables strict and warnings

use Scalar::Util qw/blessed weaken/;

use Mouse::Meta::Module;
our @ISA = qw(Mouse::Meta::Module);

sub attribute_metaclass;
sub method_metaclass;

sub constructor_class;
sub destructor_class;

my @MetaClassTypes = qw(
    attribute_metaclass
    method_metaclass
    constructor_class
    destructor_class
);

sub _construct_meta {
    my($class, %args) = @_;

    $args{attributes} = {};
    $args{methods}    = {};
    $args{roles}      = [];

    $args{superclasses} = do {
        no strict 'refs';
        \@{ $args{package} . '::ISA' };
    };

    my $self = bless \%args, ref($class) || $class;
    if(ref($self) ne __PACKAGE__){
        $self->meta->_initialize_object($self, \%args);
    }
    return $self;
}

sub create_anon_class{
    my $self = shift;
    return $self->create(undef, @_);
}

sub is_anon_class;

sub roles;

sub calculate_all_roles {
    my $self = shift;
    my %seen;
    return grep { !$seen{ $_->name }++ }
           map  { $_->calculate_all_roles } @{ $self->roles };
}

sub superclasses {
    my $self = shift;

    if (@_) {
        foreach my $super(@_){
            Mouse::Util::load_class($super);
            my $meta = Mouse::Util::get_metaclass_by_name($super);

            next if not defined $meta;

            if(Mouse::Util::is_a_metarole($meta)){
                $self->throw_error("You cannot inherit from a Mouse Role ($super)");
            }

            next if $self->isa(ref $meta); # _superclass_meta_is_compatible

            $self->_reconcile_with_superclass_meta($meta);
        }
        @{ $self->{superclasses} } = @_;
    }

    return @{ $self->{superclasses} };
}

sub _reconcile_with_superclass_meta {
    my($self, $super_meta) = @_;

    my @incompatibles;

    foreach my $metaclass_type(@MetaClassTypes){
        my $super_c = $super_meta->$metaclass_type();
        my $self_c  = $self->$metaclass_type();

        if(!$super_c->isa($self_c)){
            push @incompatibles, ($metaclass_type => $super_c);
        }
    }

    my @roles;

    foreach my $role($self->meta->calculate_all_roles){
        if(!$super_meta->meta->does_role($role->name)){
            push @roles, $role->name;
        }
    }

    #print "reconcile($self vs. $super_meta; @roles; @incompatibles)\n";

    require Mouse::Util::MetaRole;
    Mouse::Util::MetaRole::apply_metaclass_roles(
        for_class       => $self,
        metaclass       => ref $super_meta,
        metaclass_roles => \@roles,
        @incompatibles,
    );
    return;
}

sub find_method_by_name{
    my($self, $method_name) = @_;
    defined($method_name)
        or $self->throw_error('You must define a method name to find');

    foreach my $class( $self->linearized_isa ){
        my $method = $self->initialize($class)->get_method($method_name);
        return $method if defined $method;
    }
    return undef;
}

sub get_all_methods {
    my($self) = @_;
    return map{ $self->find_method_by_name($_) } $self->get_all_method_names;
}

sub get_all_method_names {
    my $self = shift;
    my %uniq;
    return grep { $uniq{$_}++ == 0 }
            map { Mouse::Meta::Class->initialize($_)->get_method_list() }
            $self->linearized_isa;
}

sub find_attribute_by_name{
    my($self, $name) = @_;
    my $attr;
    foreach my $class($self->linearized_isa){
        my $meta = Mouse::Util::get_metaclass_by_name($class) or next;
        $attr = $meta->get_attribute($name) and last;
    }
    return $attr;
}

sub add_attribute {
    my $self = shift;

    my($attr, $name);

    if(blessed $_[0]){
        $attr = $_[0];

        $attr->isa('Mouse::Meta::Attribute')
            || $self->throw_error("Your attribute must be an instance of Mouse::Meta::Attribute (or a subclass)");

        $name = $attr->name;
    }
    else{
        # _process_attribute
        $name = shift;

        my %args = (@_ == 1) ? %{$_[0]} : @_;

        defined($name)
            or $self->throw_error('You must provide a name for the attribute');

        if ($name =~ s/^\+//) { # inherited attributes
            my $inherited_attr = $self->find_attribute_by_name($name)
                or $self->throw_error("Could not find an attribute by the name of '$name' to inherit from in ".$self->name);

            $attr = $inherited_attr->clone_and_inherit_options(%args);
        }
        else{
            my($attribute_class, @traits) = $self->attribute_metaclass->interpolate_class(\%args);
            $args{traits} = \@traits if @traits;

            $attr = $attribute_class->new($name, %args);
        }
    }

    weaken( $attr->{associated_class} = $self );

    $self->{attributes}{$attr->name} = $attr;
    $attr->install_accessors();

    if(Mouse::Util::_MOUSE_VERBOSE && !$attr->{associated_methods} && ($attr->{is} || '') ne 'bare'){
        Carp::cluck(qq{Attribute (}.$attr->name.qq{) of class }.$self->name.qq{ has no associated methods (did you mean to provide an "is" argument?)});
    }
    return $attr;
}

sub compute_all_applicable_attributes {
    Carp::cluck('compute_all_applicable_attributes() has been deprecated')
        if Mouse::Util::_MOUSE_VERBOSE;
    return shift->get_all_attributes(@_)
}

sub linearized_isa;

sub new_object;

sub clone_object {
    my $class  = shift;
    my $object = shift;
    my %params = (@_ == 1) ? %{$_[0]} : @_;

    (blessed($object) && $object->isa($class->name))
        || $class->throw_error("You must pass an instance of the metaclass (" . $class->name . "), not ($object)");

    my $cloned = bless { %$object }, ref $object;
    $class->_initialize_object($cloned, \%params);

    return $cloned;
}

sub clone_instance {
    my ($class, $instance, %params) = @_;

    Carp::cluck('clone_instance has been deprecated. Use clone_object instead')
        if Mouse::Util::_MOUSE_VERBOSE;
    return $class->clone_object($instance, %params);
}


sub immutable_options {
    my ( $self, @args ) = @_;

    return (
        inline_constructor => 1,
        inline_destructor  => 1,
        constructor_name   => 'new',
        @args,
    );
}


sub make_immutable {
    my $self = shift;
    my %args = $self->immutable_options(@_);

    $self->{is_immutable}++;

    if ($args{inline_constructor}) {
        my $c = $self->constructor_class;
        Mouse::Util::load_class($c);
        $self->add_method($args{constructor_name} =>
            $c->_generate_constructor($self, \%args));
    }

    if ($args{inline_destructor}) {
        my $c = $self->destructor_class;
        Mouse::Util::load_class($c);
        $self->add_method(DESTROY =>
            $c->_generate_destructor($self, \%args));
    }

    # Moose's make_immutable returns true allowing calling code to skip setting an explicit true value
    # at the end of a source file. 
    return 1;
}

sub make_mutable { not_supported }

sub is_immutable {  $_[0]->{is_immutable} }
sub is_mutable   { !$_[0]->{is_immutable} }

sub _install_modifier_pp{
    my( $self, $type, $name, $code ) = @_;
    my $into = $self->name;

    my $original = $into->can($name)
        or $self->throw_error("The method '$name' is not found in the inheritance hierarchy for class $into");

    my $modifier_table = $self->{modifiers}{$name};

    if(!$modifier_table){
        my(@before, @after, @around, $cache, $modified);

        $cache = $original;

        $modified = sub {
            for my $c (@before) { $c->(@_) }

            if(wantarray){ # list context
                my @rval = $cache->(@_);

                for my $c(@after){ $c->(@_) }
                return @rval;
            }
            elsif(defined wantarray){ # scalar context
                my $rval = $cache->(@_);

                for my $c(@after){ $c->(@_) }
                return $rval;
            }
            else{ # void context
                $cache->(@_);

                for my $c(@after){ $c->(@_) }
                return;
            }
        };

        $self->{modifiers}{$name} = $modifier_table = {
            original => $original,

            before   => \@before,
            after    => \@after,
            around   => \@around,

            cache    => \$cache, # cache for around modifiers
        };

        $self->add_method($name => $modified);
    }

    if($type eq 'before'){
        unshift @{$modifier_table->{before}}, $code;
    }
    elsif($type eq 'after'){
        push @{$modifier_table->{after}}, $code;
    }
    else{ # around
        push @{$modifier_table->{around}}, $code;

        my $next = ${ $modifier_table->{cache} };
        ${ $modifier_table->{cache} } = sub{ $code->($next, @_) };
    }

    return;
}

sub _install_modifier {
    my ( $self, $type, $name, $code ) = @_;

    # load Class::Method::Modifiers first
    my $no_cmm_fast = do{
        local $@;
        eval q{ require Class::Method::Modifiers::Fast };
        $@;
    };

    my $impl;
    if($no_cmm_fast){
        $impl = \&_install_modifier_pp;
    }
    else{
        my $install_modifier = Class::Method::Modifiers::Fast->can('_install_modifier');
        $impl = sub {
            my ( $self, $type, $name, $code ) = @_;
            my $into = $self->name;
            $install_modifier->($into, $type, $name, $code);

            $self->add_method($name => do{
                no strict 'refs';
                \&{ $into . '::' . $name };
            });
            return;
        };
    }

    # replace this method itself :)
    {
        no warnings 'redefine';
        *_install_modifier = $impl;
    }

    $self->$impl( $type, $name, $code );
}

sub add_before_method_modifier {
    my ( $self, $name, $code ) = @_;
    $self->_install_modifier( 'before', $name, $code );
}

sub add_around_method_modifier {
    my ( $self, $name, $code ) = @_;
    $self->_install_modifier( 'around', $name, $code );
}

sub add_after_method_modifier {
    my ( $self, $name, $code ) = @_;
    $self->_install_modifier( 'after', $name, $code );
}

sub add_override_method_modifier {
    my ($self, $name, $code) = @_;

    if($self->has_method($name)){
        $self->throw_error("Cannot add an override method if a local method is already present");
    }

    my $package = $self->name;

    my $super_body = $package->can($name)
        or $self->throw_error("You cannot override '$name' because it has no super method");

    $self->add_method($name => sub {
        local $Mouse::SUPER_PACKAGE = $package;
        local $Mouse::SUPER_BODY    = $super_body;
        local @Mouse::SUPER_ARGS    = @_;

        $code->(@_);
    });
    return;
}

sub add_augment_method_modifier {
    my ($self, $name, $code) = @_;
    if($self->has_method($name)){
        $self->throw_error("Cannot add an augment method if a local method is already present");
    }

    my $super = $self->find_method_by_name($name)
        or $self->throw_error("You cannot augment '$name' because it has no super method");

    my $super_package = $super->package_name;
    my $super_body    = $super->body;

    $self->add_method($name => sub{
        local $Mouse::INNER_BODY{$super_package} = $code;
        local $Mouse::INNER_ARGS{$super_package} = [@_];
        $super_body->(@_);
    });
    return;
}

sub does_role {
    my ($self, $role_name) = @_;

    (defined $role_name)
        || $self->throw_error("You must supply a role name to look for");

    for my $class ($self->linearized_isa) {
        my $meta = Mouse::Util::get_metaclass_by_name($class)
            or next;

        for my $role (@{ $meta->roles }) {

            return 1 if $role->does_role($role_name);
        }
    }

    return 0;
}

}
BEGIN{ # lib/Mouse/Meta/Method.pm
package Mouse::Meta::Method;
use Mouse::Util qw(:meta); # enables strict and warnings

use overload
    '&{}' => sub{ $_[0]->body },
    fallback => 1,
;

sub wrap{
    my $class = shift;

    return $class->_new(@_);
}

sub _new{
    my($class, %args) = @_;
    my $self = bless \%args, $class;

    if($class ne __PACKAGE__){
        $self->meta->_initialize_object($self, \%args);
    }
    return $self;
}

sub body                 { $_[0]->{body}    }
sub name                 { $_[0]->{name}    }
sub package_name         { $_[0]->{package} }
sub associated_metaclass { $_[0]->{associated_metaclass} }

sub fully_qualified_name {
    my($self) = @_;
    return $self->package_name . '::' . $self->name;
}

}
BEGIN{ # lib/Mouse/Meta/Method/Accessor.pm
package Mouse::Meta::Method::Accessor;
use Mouse::Util qw(:meta); # enables strict and warnings

sub _inline_slot{
    my(undef, $self_var, $attr_name) = @_;
    return sprintf '%s->{q{%s}}', $self_var, $attr_name;
}

sub _generate_accessor_any{
    my($method_class, $type, $attribute, $class) = @_;

    my $name          = $attribute->name;
    my $default       = $attribute->default;
    my $constraint    = $attribute->type_constraint;
    my $builder       = $attribute->builder;
    my $trigger       = $attribute->trigger;
    my $is_weak       = $attribute->is_weak_ref;
    my $should_deref  = $attribute->should_auto_deref;
    my $should_coerce = (defined($constraint) && $constraint->has_coercion && $attribute->should_coerce);

    my $compiled_type_constraint = defined($constraint) ? $constraint->_compiled_type_constraint : undef;

    my $self  = '$_[0]';
    my $slot  = $method_class->_inline_slot($self, $name);;

    my $accessor = sprintf(qq{package %s;\n#line 1 "%s for %s (%s)"\n}, $class->name, $type, $name, __FILE__)
                 . "sub {\n";

    if ($type eq 'rw' || $type eq 'wo') {
        if($type eq 'rw'){
            $accessor .= 
                'if (scalar(@_) >= 2) {' . "\n";
        }
        else{ # writer
            $accessor .= 
                'if(@_ < 2){ Carp::confess("Not enough arguments for the writer of '.$name.'") }'.
                '{' . "\n";
        }
                
        my $value = '$_[1]';

        if (defined $constraint) {
            if ($should_coerce) {
                $accessor .=
                    "\n".
                    'my $val = $constraint->coerce('.$value.');';
                $value = '$val';
            }
            $accessor .= 
                "\n".
                '$compiled_type_constraint->('.$value.') or
                    $attribute->verify_type_constraint_error($name, '.$value.', $constraint);' . "\n";
        }

        # if there's nothing left to do for the attribute we can return during
        # this setter
        $accessor .= 'return ' if !$is_weak && !$trigger && !$should_deref;

        $accessor .= "$slot = $value;\n";

        if ($is_weak) {
            $accessor .= "Scalar::Util::weaken($slot) if ref $slot;\n";
        }

        if ($trigger) {
            $accessor .= '$trigger->('.$self.', '.$value.');' . "\n";
        }

        $accessor .= "}\n";
    }
    elsif($type eq 'ro') {
        $accessor .= 'Carp::confess("Cannot assign a value to a read-only accessor") if scalar(@_) >= 2;' . "\n";
    }
    else{
        $class->throw_error("Unknown accessor type '$type'");
    }

    if ($attribute->is_lazy) {
        my $value;

        if (defined $builder){
            $value = "$self->\$builder()";
        }
        elsif (ref($default) eq 'CODE'){
            $value = "$self->\$default()";
        }
        else{
            $value = '$default';
        }

        $accessor .= "if(!exists $slot){\n";
        if($should_coerce){
            $accessor .= "$slot = \$constraint->coerce($value)";
        }
        elsif(defined $constraint){
            $accessor .= "my \$tmp = $value;\n";

            $accessor .= "\$compiled_type_constraint->(\$tmp)";
            $accessor .= " || \$attribute->verify_type_constraint_error(\$name, \$tmp, \$constraint);\n";
            $accessor .= "$slot = \$tmp;\n";
        }
        else{
            $accessor .= "$slot = $value;\n";
        }
        if ($is_weak) {
            $accessor .= "Scalar::Util::weaken($slot) if ref $slot;\n";
        }
        $accessor .= "}\n";
    }

    if ($should_deref) {
        if ($constraint->is_a_type_of('ArrayRef')) {
            $accessor .= "return \@{ $slot || [] } if wantarray;\n";
        }
        elsif($constraint->is_a_type_of('HashRef')){
            $accessor .= "return \%{ $slot || {} } if wantarray;\n";
        }
        else{
            $class->throw_error("Can not auto de-reference the type constraint " . $constraint->name);
        }
    }

    $accessor .= "return $slot;\n}\n";

    #print $accessor, "\n";
    my $code;
    my $e = do{
        local $@;
        $code = eval $accessor;
        $@;
    };
    die $e if $e;

    return $code;
}

sub _generate_accessor{
    my $class = shift;
    return $class->_generate_accessor_any(rw => @_);
}

sub _generate_reader {
    my $class = shift;
    return $class->_generate_accessor_any(ro => @_);
}

sub _generate_writer {
    my $class = shift;
    return $class->_generate_accessor_any(wo => @_);
}

sub _generate_predicate {
    my (undef, $attribute, $class) = @_;

    my $slot = $attribute->name;
    return sub{
        return exists $_[0]->{$slot};
    };
}

sub _generate_clearer {
    my (undef, $attribute, $class) = @_;

    my $slot = $attribute->name;
    return sub{
        delete $_[0]->{$slot};
    };
}

}
BEGIN{ # lib/Mouse/Meta/Method/Constructor.pm
package Mouse::Meta::Method::Constructor;
use Mouse::Util qw(:meta); # enables strict and warnings

sub _inline_slot{
    my(undef, $self_var, $attr_name) = @_;
    return sprintf '%s->{q{%s}}', $self_var, $attr_name;
}

sub _generate_constructor {
    my ($class, $metaclass, $args) = @_;

    my $associated_metaclass_name = $metaclass->name;

    my @attrs         = $metaclass->get_all_attributes;

    my $buildall      = $class->_generate_BUILDALL($metaclass);
    my $buildargs     = $class->_generate_BUILDARGS($metaclass);
    my $processattrs  = $class->_generate_processattrs($metaclass, \@attrs);

    my @checks = map { $_ && $_->_compiled_type_constraint }
                 map { $_->type_constraint } @attrs;

    my $source = sprintf("#line %d %s\n", __LINE__, __FILE__).<<"...";
        sub \{
            my \$class = shift;
            return \$class->Mouse::Object::new(\@_)
                if \$class ne q{$associated_metaclass_name};
            # BUILDARGS
            $buildargs;
            my \$instance = bless {}, \$class;
            # process attributes
            $processattrs;
            # BUILDALL
            $buildall;
            return \$instance;
        }
...
    #warn $source;
    my $code;
    my $e = do{
        local $@;
        $code = eval $source;
        $@;
    };
    die $e if $e;
    return $code;
}

sub _generate_processattrs {
    my ($method_class, $metaclass, $attrs) = @_;
    my @res;

    my $has_triggers;

    for my $index (0 .. @$attrs - 1) {
        my $code = '';

        my $attr = $attrs->[$index];
        my $key  = $attr->name;

        my $init_arg        = $attr->init_arg;
        my $type_constraint = $attr->type_constraint;
        my $is_weak_ref     = $attr->is_weak_ref;
        my $need_coercion;

        my $instance_slot  = $method_class->_inline_slot('$instance', $key);
        my $attr_var       = "\$attrs[$index]";
        my $constraint_var;

        if(defined $type_constraint){
             $constraint_var = "$attr_var\->{type_constraint}";
             $need_coercion  = ($attr->should_coerce && $type_constraint->has_coercion);
        }

        $code .= "# initialize $key\n";

        my $post_process = '';
        if(defined $type_constraint){
            $post_process .= "\$checks[$index]->($instance_slot)";
            $post_process .= "  or $attr_var->verify_type_constraint_error(q{$key}, $instance_slot, $constraint_var);\n";
        }
        if($is_weak_ref){
            $post_process .= "Scalar::Util::weaken($instance_slot) if ref $instance_slot;\n";
        }

        if (defined $init_arg) {
            my $value = "\$args->{q{$init_arg}}";

            $code .= "if (exists $value) {\n";

            if($need_coercion){
                $value = "$constraint_var->coerce($value)";
            }

            $code .= "$instance_slot = $value;\n";
            $code .= $post_process;

            if ($attr->has_trigger) {
                $has_triggers++;
                $code .= "push \@triggers, [$attr_var\->{trigger}, $instance_slot];\n";
            }

            $code .= "\n} else {\n";
        }

        if ($attr->has_default || $attr->has_builder) {
            unless ($attr->is_lazy) {
                my $default = $attr->default;
                my $builder = $attr->builder;

                my $value;
                if (defined($builder)) {
                    $value = "\$instance->$builder()";
                }
                elsif (ref($default) eq 'CODE') {
                    $value = "$attr_var\->{default}->(\$instance)";
                }
                elsif (defined($default)) {
                    $value = "$attr_var\->{default}";
                }
                else {
                    $value = 'undef';
                }

                if($need_coercion){
                    $value = "$constraint_var->coerce($value)";
                }

                $code .= "$instance_slot = $value;\n";
                if($is_weak_ref){
                    $code .= "Scalar::Util::weaken($instance_slot);\n";
                }
            }
        }
        elsif ($attr->is_required) {
            $code .= "Carp::confess('Attribute ($key) is required');";
        }

        $code .= "}\n" if defined $init_arg;

        push @res, $code;
    }

    if($metaclass->is_anon_class){
        push @res, q{$instance->{__METACLASS__} = $metaclass;};
    }

    if($has_triggers){
        unshift @res, q{my @triggers;};
        push    @res,  q{$_->[0]->($instance, $_->[1]) for @triggers;};
    }

    return join "\n", @res;
}

sub _generate_BUILDARGS {
    my(undef, $metaclass) = @_;

    my $class = $metaclass->name;
    if ( $class->can('BUILDARGS') && $class->can('BUILDARGS') != \&Mouse::Object::BUILDARGS ) {
        return 'my $args = $class->BUILDARGS(@_)';
    }

    return <<'...';
        my $args;
        if ( scalar @_ == 1 ) {
            ( ref( $_[0] ) eq 'HASH' )
                || Carp::confess "Single parameters to new() must be a HASH ref";
            $args = +{ %{ $_[0] } };
        }
        else {
            $args = +{@_};
        }
...
}

sub _generate_BUILDALL {
    my (undef, $metaclass) = @_;

    return '' unless $metaclass->name->can('BUILD');

    my @code;
    for my $class ($metaclass->linearized_isa) {
        if (Mouse::Util::get_code_ref($class, 'BUILD')) {
            unshift  @code, qq{${class}::BUILD(\$instance, \$args);};
        }
    }
    return join "\n", @code;
}

}
BEGIN{ # lib/Mouse/Meta/Method/Delegation.pm
package Mouse::Meta::Method::Delegation;
use Mouse::Util qw(:meta); # enables strict and warnings
use Scalar::Util;

sub _generate_delegation{
    my (undef, $attribute, $metaclass, $reader, $handle_name, $method_to_call) = @_;

    return sub {
        my $instance = shift;
        my $proxy    = $instance->$reader();

        my $error = !defined($proxy)                              ? ' is not defined'
                  : ref($proxy) && !Scalar::Util::blessed($proxy) ? qq{ is not an object (got '$proxy')}
                                                                  : undef;
        if ($error) {
            $instance->meta->throw_error(
                "Cannot delegate $handle_name to $method_to_call because "
                    . "the value of "
                    . $attribute->name
                    . $error
             );
        }
        $proxy->$method_to_call(@_);
    };
}


}
BEGIN{ # lib/Mouse/Meta/Method/Destructor.pm
package Mouse::Meta::Method::Destructor;
use Mouse::Util qw(:meta); # enables strict and warnings

sub _empty_DESTROY{ }

sub _generate_destructor{
    my (undef, $metaclass) = @_;

    if(!$metaclass->name->can('DEMOLISH')){
        return \&_empty_DESTROY;
    }

    my $demolishall = '';
    for my $class ($metaclass->linearized_isa) {
        if (Mouse::Util::get_code_ref($class, 'DEMOLISH')) {
            $demolishall .= "${class}::DEMOLISH(\$self);\n";
        }
    }

    my $source = sprintf("#line %d %s\n", __LINE__, __FILE__) . <<"...";
    sub {
        my \$self = shift;
        local \$?;

        my \$e = do{
            local \$@;
            eval{
                $demolishall;
            };
            \$@;
        };
        no warnings 'misc';
        die \$e if \$e; # rethrow
    }
...

    my $code;
    my $e = do{
        local $@;
        $code = eval $source;
        $@;
    };
    die $e if $e;
    return $code;
}

}
BEGIN{ # lib/Mouse/Meta/Module.pm
package Mouse::Meta::Module;
use Mouse::Util qw/:meta get_code_package get_code_ref load_class not_supported/; # enables strict and warnings

use Carp         ();
use Scalar::Util ();

my %METAS;

# XXX: work around a warning "useless use of a constant in void context" in 5.6.2
if(&Mouse::Util::MOUSE_XS){
    # register meta storage for performance
    Mouse::Util::__register_metaclass_storage(\%METAS, 0);

    # ensure thread safety
    *CLONE = sub { Mouse::Util::__register_metaclass_storage(\%METAS, 1) };
}

sub _metaclass_cache { # DEPRECATED
    my($class, $name) = @_;
    return $METAS{$name};
}

sub initialize {
    my($class, $package_name, @args) = @_;

    ($package_name && !ref($package_name))
        || $class->throw_error("You must pass a package name and it cannot be blessed");

    return $METAS{$package_name}
        ||= $class->_construct_meta(package => $package_name, @args);
}

sub reinitialize {
    my($class, $package_name, @args) = @_;

    $package_name = $package_name->name if ref $package_name;

    ($package_name && !ref($package_name))
        || $class->throw_error("You must pass a package name and it cannot be blessed");

    delete $METAS{$package_name};
    return $class->initialize($package_name, @args);
}

sub _class_of{
    my($class_or_instance) = @_;
    return undef unless defined $class_or_instance;
    return $METAS{ ref($class_or_instance) || $class_or_instance };
}

# Means of accessing all the metaclasses that have
# been initialized thus far
#sub _get_all_metaclasses         {        %METAS         }
sub _get_all_metaclass_instances { values %METAS         }
sub _get_all_metaclass_names     { keys   %METAS         }
sub _get_metaclass_by_name       { $METAS{$_[0]}         }
#sub _store_metaclass_by_name     { $METAS{$_[0]} = $_[1] }
#sub _weaken_metaclass            { weaken($METAS{$_[0]}) }
#sub _does_metaclass_exist        { defined $METAS{$_[0]} }
#sub _remove_metaclass_by_name    { delete $METAS{$_[0]}  }

sub name;

sub namespace;

# The followings are Class::MOP specific methods

#sub version   { no strict 'refs'; ${shift->name.'::VERSION'}   }
#sub authority { no strict 'refs'; ${shift->name.'::AUTHORITY'} }
#sub identifier {
#    my $self = shift;
#    return join '-' => (
#       $self->name,
#        ($self->version   || ()),
#        ($self->authority || ()),
#    );
#}

# add_attribute is an abstract method

sub get_attribute_map { # DEPRECATED
    Carp::cluck('get_attribute_map() has been deprecated');
    return $_[0]->{attributes};
}

sub has_attribute     { exists $_[0]->{attributes}->{$_[1]} }
sub get_attribute     {        $_[0]->{attributes}->{$_[1]} }
sub remove_attribute  { delete $_[0]->{attributes}->{$_[1]} }

sub get_attribute_list{ keys   %{$_[0]->{attributes}} }

# XXX: for backward compatibility
my %foreign = map{ $_ => undef } qw(
    Mouse Mouse::Role Mouse::Util Mouse::Util::TypeConstraints
    Carp Scalar::Util List::Util
);
sub _code_is_mine{
#    my($self, $code) = @_;

    return !exists $foreign{ get_code_package($_[1]) };
}

sub add_method;

sub has_method {
    my($self, $method_name) = @_;

    defined($method_name)
        or $self->throw_error('You must define a method name');

    return defined($self->{methods}{$method_name}) || do{
        my $code = get_code_ref($self->{package}, $method_name);
        $code && $self->_code_is_mine($code);
    };
}

sub get_method_body {
    my($self, $method_name) = @_;

    defined($method_name)
        or $self->throw_error('You must define a method name');

    return $self->{methods}{$method_name} ||= do{
        my $code = get_code_ref($self->{package}, $method_name);
        $code && $self->_code_is_mine($code) ? $code : undef;
    };
}

sub get_method{
    my($self, $method_name) = @_;

    if(my $code = $self->get_method_body($method_name)){
        my $method_metaclass = $self->method_metaclass;
        load_class($method_metaclass);

        return $method_metaclass->wrap(
            body                 => $code,
            name                 => $method_name,
            package              => $self->name,
            associated_metaclass => $self,
        );
    }

    return undef;
}

sub get_method_list {
    my($self) = @_;

    return grep { $self->has_method($_) } keys %{ $self->namespace };
}

{
    my $ANON_SERIAL = 0;

    my %IMMORTALS;

    sub create {
        my($self, $package_name, %options) = @_;

        my $class = ref($self) || $self;
        $self->throw_error('You must pass a package name') if @_ < 2;

        my $superclasses;
        if(exists $options{superclasses}){
            if(Mouse::Util::is_a_metarole($self)){
                delete $options{superclasses};
            }
            else{
                $superclasses = delete $options{superclasses};
                (ref $superclasses eq 'ARRAY')
                    || $self->throw_error("You must pass an ARRAY ref of superclasses");
            }
        }

        my $attributes = delete $options{attributes};
        if(defined $attributes){
            (ref $attributes eq 'ARRAY' || ref $attributes eq 'HASH')
                || $self->throw_error("You must pass an ARRAY ref of attributes");
        }
        my $methods = delete $options{methods};
        if(defined $methods){
            (ref $methods eq 'HASH')
                || $self->throw_error("You must pass a HASH ref of methods");
        }
        my $roles = delete $options{roles};
        if(defined $roles){
            (ref $roles eq 'ARRAY')
                || $self->throw_error("You must pass an ARRAY ref of roles");
        }
        my $mortal;
        my $cache_key;

        if(!defined $package_name){ # anonymous
            $mortal = !$options{cache};

            # anonymous but immortal
            if(!$mortal){
                    # something like Super::Class|Super::Class::2=Role|Role::1
                    $cache_key = join '=' => (
                        join('|',      @{$superclasses || []}),
                        join('|', sort @{$roles        || []}),
                    );
                    return $IMMORTALS{$cache_key} if exists $IMMORTALS{$cache_key};
            }
            $options{anon_serial_id} = ++$ANON_SERIAL;
            $package_name = $class . '::__ANON__::' . $ANON_SERIAL;
        }

        # instantiate a module
        {
            no strict 'refs';
            ${ $package_name . '::VERSION'   } = delete $options{version}   if exists $options{version};
            ${ $package_name . '::AUTHORITY' } = delete $options{authority} if exists $options{authority};
        }

        my $meta = $self->initialize( $package_name, %options);

        Scalar::Util::weaken $METAS{$package_name}
            if $mortal;

        $meta->add_method(meta => sub{
            $self->initialize(ref($_[0]) || $_[0]);
        });

        $meta->superclasses(@{$superclasses})
            if defined $superclasses;

        # NOTE:
        # process attributes first, so that they can
        # install accessors, but locally defined methods
        # can then overwrite them. It is maybe a little odd, but
        # I think this should be the order of things.
        if (defined $attributes) {
            if(ref($attributes) eq 'ARRAY'){
                # array of Mouse::Meta::Attribute
                foreach my $attr (@{$attributes}) {
                    $meta->add_attribute($attr);
                }
            }
            else{
                # hash map of name and attribute spec pairs
                while(my($name, $attr) = each %{$attributes}){
                    $meta->add_attribute($name => $attr);
                }
            }
        }
        if (defined $methods) {
            while(my($method_name, $method_body) = each %{$methods}){
                $meta->add_method($method_name, $method_body);
            }
        }
        if (defined $roles){
            Mouse::Util::apply_all_roles($package_name, @{$roles});
        }

        if($cache_key){
            $IMMORTALS{$cache_key} = $meta;
        }

        return $meta;
    }

    sub DESTROY{
        my($self) = @_;

        return if $Mouse::Util::in_global_destruction;

        my $serial_id = $self->{anon_serial_id};

        return if !$serial_id;

        # @ISA is a magical variable, so we clear it manually.
        @{$self->{superclasses}} = () if exists $self->{superclasses};

        # Then, clear the symbol table hash
        %{$self->namespace} = ();

        my $name = $self->name;
        delete $METAS{$name};

        $name =~ s/ $serial_id \z//xms;

        no strict 'refs';
        delete ${$name}{ $serial_id . '::' };

        return;
    }
}

sub throw_error{
    my($class, $message, %args) = @_;

    local $Carp::CarpLevel  = $Carp::CarpLevel + 1 + ($args{depth} || 0);
    local $Carp::MaxArgNums = 20; # default is 8, usually we use named args which gets messier though

    if(exists $args{longmess} && !$args{longmess}){ # intentionaly longmess => 0
        Carp::croak($message);
    }
    else{
        Carp::confess($message);
    }
}

}
BEGIN{ # lib/Mouse/Meta/Role.pm
package Mouse::Meta::Role;
use Mouse::Util qw(:meta not_supported english_list); # enables strict and warnings

use Mouse::Meta::Module;
our @ISA = qw(Mouse::Meta::Module);

sub method_metaclass;

sub _construct_meta {
    my $class = shift;

    my %args  = @_;

    $args{methods}          = {};
    $args{attributes}       = {};
    $args{required_methods} = [];
    $args{roles}            = [];

    my $self = bless \%args, ref($class) || $class;
    if($class ne __PACKAGE__){
        $self->meta->_initialize_object($self, \%args);
    }

    return $self;
}

sub create_anon_role{
    my $self = shift;
    return $self->create(undef, @_);
}

sub is_anon_role;

sub get_roles;

sub calculate_all_roles {
    my $self = shift;
    my %seen;
    return grep { !$seen{ $_->name }++ }
           ($self, map  { $_->calculate_all_roles } @{ $self->get_roles });
}

sub get_required_method_list{
    return @{ $_[0]->{required_methods} };
}

sub add_required_methods {
    my($self, @methods) = @_;
    my %required = map{ $_ => 1 } @{$self->{required_methods}};
    push @{$self->{required_methods}}, grep{ !$required{$_}++ && !$self->has_method($_) } @methods;
    return;
}

sub requires_method {
    my($self, $name) = @_;
    return scalar( grep{ $_ eq $name } @{ $self->{required_methods} } ) != 0;
}

sub add_attribute {
    my $self = shift;
    my $name = shift;

    $self->{attributes}->{$name} = (@_ == 1) ? $_[0] : { @_ };
    return;
}

sub _check_required_methods{
    my($role, $applicant, $args) = @_;

    if($args->{_to} eq 'role'){
        $applicant->add_required_methods($role->get_required_method_list);
    }
    else{ # to class or instance
        my $applicant_class_name = $applicant->name;

        my @missing;
        foreach my $method_name(@{$role->{required_methods}}){
            next if exists $args->{aliased_methods}{$method_name};
            next if exists $role->{methods}{$method_name};
            next if $applicant_class_name->can($method_name);

            push @missing, $method_name;
        }
        if(@missing){
            $role->throw_error(sprintf "'%s' requires the method%s %s to be implemented by '%s'",
                $role->name,
                (@missing == 1 ? '' : 's'), # method or methods
                english_list(map{ sprintf q{'%s'}, $_ } @missing),
                $applicant_class_name);
        }
    }

    return;
}

sub _apply_methods{
    my($role, $applicant, $args) = @_;

    my $alias    = $args->{-alias};
    my $excludes = $args->{-excludes};

    foreach my $method_name($role->get_method_list){
        next if $method_name eq 'meta';

        my $code = $role->get_method_body($method_name);

        if(!exists $excludes->{$method_name}){
            if(!$applicant->has_method($method_name)){
                # The third argument $role is used in Role::Composite
                $applicant->add_method($method_name => $code, $role);
            }
        }

        if(exists $alias->{$method_name}){
            my $dstname = $alias->{$method_name};

            my $dstcode = $applicant->get_method_body($dstname);

            if(defined($dstcode) && $dstcode != $code){
                $role->throw_error("Cannot create a method alias if a local method of the same name exists");
            }
            else{
                $applicant->add_method($dstname => $code, $role);
            }
        }
    }

    return;
}

sub _apply_attributes{
    my($role, $applicant, $args) = @_;

    for my $attr_name ($role->get_attribute_list) {
        next if $applicant->has_attribute($attr_name);

        $applicant->add_attribute($attr_name => $role->get_attribute($attr_name));
    }
    return;
}

sub _apply_modifiers{
    my($role, $applicant, $args) = @_;

    if(my $modifiers = $role->{override_method_modifiers}){
        foreach my $method_name (keys %{$modifiers}){
            $applicant->add_override_method_modifier($method_name => $modifiers->{$method_name});
        }
    }

    for my $modifier_type (qw/before around after/) {
        my $modifiers = $role->{"${modifier_type}_method_modifiers"}
            or next;

        my $add_modifier = "add_${modifier_type}_method_modifier";

        foreach my $method_name (keys %{$modifiers}){
            foreach my $code(@{ $modifiers->{$method_name} }){
                next if $applicant->{"_applied_$modifier_type"}{$method_name, $code}++; # skip applied modifiers
                $applicant->$add_modifier($method_name => $code);
            }
        }
    }
    return;
}

sub _append_roles{
    my($role, $applicant, $args) = @_;

    my $roles = ($args->{_to} eq 'role') ? $applicant->get_roles : $applicant->roles;

    foreach my $r($role, @{$role->get_roles}){
        if(!$applicant->does_role($r->name)){
            push @{$roles}, $r;
        }
    }
    return;
}

# Moose uses Application::ToInstance, Application::ToClass, Application::ToRole
sub apply {
    my $self      = shift;
    my $applicant = shift;

    my %args = (@_ == 1) ? %{ $_[0] } : @_;

    my $instance;

    if(Mouse::Util::is_a_metaclass($applicant)){  # Application::ToClass
        $args{_to} = 'class';
    }
    elsif(Mouse::Util::is_a_metarole($applicant)){ # Application::ToRole
        $args{_to} = 'role';
    }
    else{                                       # Appplication::ToInstance
        $args{_to} = 'instance';
        $instance = $applicant;

        $applicant = (Mouse::Util::class_of($instance) || 'Mouse::Meta::Class')->create_anon_class(
            superclasses => [ref $instance],
            cache        => 1,
        );
    }

    if($args{alias} && !exists $args{-alias}){
        $args{-alias} = $args{alias};
    }
    if($args{excludes} && !exists $args{-excludes}){
        $args{-excludes} = $args{excludes};
    }

    $args{aliased_methods} = {};
    if(my $alias = $args{-alias}){
        @{$args{aliased_methods}}{ values %{$alias} } = ();
    }

    if(my $excludes = $args{-excludes}){
        $args{-excludes} = {}; # replace with a hash ref
        if(ref $excludes){
            %{$args{-excludes}} = (map{ $_ => undef } @{$excludes});
        }
        else{
            $args{-excludes}{$excludes} = undef;
        }
    }

    $self->_check_required_methods($applicant, \%args);
    $self->_apply_attributes($applicant, \%args);
    $self->_apply_methods($applicant, \%args);
    $self->_apply_modifiers($applicant, \%args);
    $self->_append_roles($applicant, \%args);


    if(defined $instance){ # Application::ToInstance
        # rebless instance
        bless $instance, $applicant->name;
        $applicant->_initialize_object($instance, $instance);
    }

    return;
}


sub combine {
    my($role_class, @role_specs) = @_;

    require 'Mouse/Meta/Role/Composite.pm'; # we don't want to create its namespace

    my $composite = Mouse::Meta::Role::Composite->create_anon_role();

    foreach my $role_spec (@role_specs) {
        my($role_name, $args) = @{$role_spec};
        $role_name->meta->apply($composite, %{$args});
    }
    return $composite;
}

sub add_before_method_modifier {
    my ($self, $method_name, $method) = @_;

    push @{ $self->{before_method_modifiers}{$method_name} ||= [] }, $method;
    return;
}
sub add_around_method_modifier {
    my ($self, $method_name, $method) = @_;

    push @{ $self->{around_method_modifiers}{$method_name} ||= [] }, $method;
    return;
}
sub add_after_method_modifier {
    my ($self, $method_name, $method) = @_;

    push @{ $self->{after_method_modifiers}{$method_name} ||= [] }, $method;
    return;
}

sub get_before_method_modifiers {
    my ($self, $method_name) = @_;
    return @{ $self->{before_method_modifiers}{$method_name} ||= [] }
}
sub get_around_method_modifiers {
    my ($self, $method_name) = @_;
    return @{ $self->{around_method_modifiers}{$method_name} ||= [] }
}
sub get_after_method_modifiers {
    my ($self, $method_name) = @_;
    return @{ $self->{after_method_modifiers}{$method_name} ||= [] }
}

sub add_override_method_modifier{
    my($self, $method_name, $method) = @_;

    if($self->has_method($method_name)){
        # This error happens in the override keyword or during role composition,
        # so I added a message, "A local method of ...", only for compatibility (gfx)
        $self->throw_error("Cannot add an override of method '$method_name' "
                   . "because there is a local version of '$method_name'"
                   . "(A local method of the same name as been found)");
    }

    $self->{override_method_modifiers}->{$method_name} = $method;
}

sub get_override_method_modifier {
    my ($self, $method_name) = @_;
    return $self->{override_method_modifiers}->{$method_name};
}

sub does_role {
    my ($self, $role_name) = @_;

    (defined $role_name)
        || $self->throw_error("You must supply a role name to look for");

    # if we are it,.. then return true
    return 1 if $role_name eq $self->name;
    # otherwise.. check our children
    for my $role (@{ $self->get_roles }) {
        return 1 if $role->does_role($role_name);
    }
    return 0;
}

}
BEGIN{ # lib/Mouse/Meta/Role/Composite.pm
package Mouse::Meta::Role::Composite;
use Mouse::Util qw(english_list); # enables strict and warnings
use Mouse::Meta::Role;
our @ISA = qw(Mouse::Meta::Role);

sub get_method_list{
    my($self) = @_;
    return keys %{ $self->{methods} };
}

sub add_method {
    my($self, $method_name, $code, $role) = @_;

    if( ($self->{methods}{$method_name} || 0) == $code){
        # This role already has the same method.
        return;
    }

    if($method_name ne 'meta'){
        my $roles = $self->{composed_roles_by_method}{$method_name} ||= [];
        push @{$roles}, $role;
        if(@{$roles} > 1){
            $self->{conflicting_methods}{$method_name}++;
        }
    }

    $self->{methods}{$method_name} = $code;
    # no need to add a subroutine to the stash
    return;
}

sub get_method_body {
    my($self, $method_name) = @_;
    return $self->{methods}{$method_name};
}

sub has_method {
    # my($self, $method_name) = @_;
    return 0; # to fool _apply_methods() in combine()
}

sub has_attribute{
    # my($self, $method_name) = @_;
    return 0; # to fool _appply_attributes() in combine()
}

sub has_override_method_modifier{
    # my($self, $method_name) = @_;
    return 0; # to fool _apply_modifiers() in combine()
}

sub add_attribute{
    my($self, $attr_name, $spec) = @_;

    my $existing = $self->{attributes}{$attr_name};
    if($existing && $existing != $spec){
        $self->throw_error("We have encountered an attribute conflict with '$attr_name' "
                         . "during composition. This is fatal error and cannot be disambiguated.");
    }
    $self->SUPER::add_attribute($attr_name, $spec);
    return;
}

sub add_override_method_modifier{
    my($self, $method_name, $code) = @_;

    my $existing = $self->{override_method_modifiers}{$method_name};
    if($existing && $existing != $code){
        $self->throw_error( "We have encountered an 'override' method conflict with '$method_name' during "
                          . "composition (Two 'override' methods of the same name encountered). "
                          . "This is fatal error.")
    }
    $self->SUPER::add_override_method_modifier($method_name, $code);
    return;
}

# components of apply()

sub _apply_methods{
    my($self, $applicant, $args) = @_;

    if(exists $self->{conflicting_methods}){
        my $applicant_class_name = $applicant->name;

        my @conflicting = sort grep{ !$applicant_class_name->can($_) } keys %{ $self->{conflicting_methods} };

        if(@conflicting == 1){
            my $method_name = $conflicting[0];
            my @roles       = sort @{ $self->{composed_roles_by_method}{$method_name} };
            $self->throw_error(
               sprintf q{Due to a method name conflict in roles %s, the method '%s' must be implemented or excluded by '%s'},
                   english_list(map{ sprintf q{'%s'}, $_->name } @roles), $method_name, $applicant->name
            );
        }
        elsif(@conflicting > 1){
            my $methods = english_list(map{ sprintf q{'%s'}, $_ } @conflicting);

            my %seen;
            my $roles   = english_list(
                sort map{ my $name = $_->name; $seen{$name}++ ? () : sprintf q{'%s'}, $name }
                map{ @{$_} } @{ $self->{composed_roles_by_method} }{@conflicting}
            );

            $self->throw_error(
               sprintf q{Due to method name conflicts in roles %s, the methods %s must be implemented or excluded by '%s'},
                   $roles, $methods, $applicant->name
            );
        }
    }

    $self->SUPER::_apply_methods($applicant, $args);
    return;
}
}
BEGIN{ # lib/Mouse/Meta/Role/Method.pm
package Mouse::Meta::Role::Method;
use Mouse::Util; # enables strict and warnings

use Mouse::Meta::Method;
our @ISA = qw(Mouse::Meta::Method);

sub _new{
    my($class, %args) = @_;
    my $self = bless \%args, $class;

    if($class ne __PACKAGE__){
        $self->meta->_initialize_object($self, \%args);
    }
    return $self;
}

}
BEGIN{ # lib/Mouse/Object.pm
package Mouse::Object;
use Mouse::Util qw(does dump meta); # enables strict and warnings

sub new;

sub BUILDALL {
    my $self = shift;

    # short circuit
    return unless $self->can('BUILD');

    for my $class (reverse $self->meta->linearized_isa) {
        my $build = Mouse::Util::get_code_ref($class, 'BUILD')
            || next;

        $self->$build(@_);
    }
    return;
}

sub DEMOLISHALL {
    my $self = shift;

    # short circuit
    return unless $self->can('DEMOLISH');

    # We cannot count on being able to retrieve a previously made
    # metaclass, _or_ being able to make a new one during global
    # destruction. However, we should still be able to use mro at
    # that time (at least tests suggest so ;)

    foreach my $class (@{ Mouse::Util::get_linear_isa(ref $self) }) {
        my $demolish = Mouse::Util::get_code_ref($class, 'DEMOLISH')
            || next;

        $self->$demolish();
    }
    return;
}

}
BEGIN{ # lib/Mouse/Role.pm
package Mouse::Role;
use Mouse::Exporter; # enables strict and warnings

our $VERSION = '0.43';

use Carp         qw(confess);
use Scalar::Util qw(blessed);

use Mouse::Util  qw(not_supported);
use Mouse::Meta::Role;
use Mouse ();

Mouse::Exporter->setup_import_methods(
    as_is => [qw(
        extends with
        has
        before after around
        override super
        augment  inner

        requires excludes
    ),
        \&Scalar::Util::blessed,
        \&Carp::confess,
    ],
);


sub extends  {
    Carp::croak "Roles do not support 'extends'";
}

sub with     {
    my $meta = Mouse::Meta::Role->initialize(scalar caller);
    Mouse::Util::apply_all_roles($meta->name, @_);
    return;
}

sub has {
    my $meta = Mouse::Meta::Role->initialize(scalar caller);
    my $name = shift;

    $meta->throw_error(q{Usage: has 'name' => ( key => value, ... )})
        if @_ % 2; # odd number of arguments

    if(ref $name){ # has [qw(foo bar)] => (...)
        for (@{$name}){
            $meta->add_attribute($_ => @_);
        }
    }
    else{ # has foo => (...)
        $meta->add_attribute($name => @_);
    }
    return;
}

sub before {
    my $meta = Mouse::Meta::Role->initialize(scalar caller);

    my $code = pop;
    for (@_) {
        $meta->add_before_method_modifier($_ => $code);
    }
    return;
}

sub after {
    my $meta = Mouse::Meta::Role->initialize(scalar caller);

    my $code = pop;
    for (@_) {
        $meta->add_after_method_modifier($_ => $code);
    }
    return;
}

sub around {
    my $meta = Mouse::Meta::Role->initialize(scalar caller);

    my $code = pop;
    for (@_) {
        $meta->add_around_method_modifier($_ => $code);
    }
    return;
}


sub super {
    return if !defined $Mouse::SUPER_BODY;
    $Mouse::SUPER_BODY->(@Mouse::SUPER_ARGS);
}

sub override {
    # my($name, $code) = @_;
    Mouse::Meta::Role->initialize(scalar caller)->add_override_method_modifier(@_);
    return;
}

# We keep the same errors messages as Moose::Role emits, here.
sub inner {
    Carp::croak "Roles cannot support 'inner'";
}

sub augment {
    Carp::croak "Roles cannot support 'augment'";
}

sub requires {
    my $meta = Mouse::Meta::Role->initialize(scalar caller);
    $meta->throw_error("Must specify at least one method") unless @_;
    $meta->add_required_methods(@_);
    return;
}

sub excludes {
    not_supported;
}

sub init_meta{
    shift;
    my %args = @_;

    my $class = $args{for_class}
        or Carp::confess("Cannot call init_meta without specifying a for_class");

    my $metaclass  = $args{metaclass}  || 'Mouse::Meta::Role';

    my $meta = $metaclass->initialize($class);

    $meta->add_method(meta => sub{
        $metaclass->initialize(ref($_[0]) || $_[0]);
    });

    # make a role type for each Mouse role
    Mouse::Util::TypeConstraints::role_type($class)
        unless Mouse::Util::TypeConstraints::find_type_constraint($class);

    return $meta;
}

}
BEGIN{ # lib/Mouse/Util/MetaRole.pm
package Mouse::Util::MetaRole;
use Mouse::Util; # enables strict and warnings

my @MetaClassTypes = qw(
    metaclass
    attribute_metaclass
    method_metaclass
    constructor_class
    destructor_class
);

# In Mouse::Exporter::do_import():
# apply_metaclass_roles(for_class => $class, metaclass_roles => \@traits)
sub apply_metaclass_roles {
    my %options = @_;

    my $for = Scalar::Util::blessed($options{for_class})
        ? $options{for_class}
        : Mouse::Util::get_metaclass_by_name($options{for_class});

    my $new_metaclass = _make_new_class( ref $for,
        $options{metaclass_roles},
        $options{metaclass} ? [$options{metaclass}] : undef,
    );

    my @metaclass_map;

    foreach my $mc_type(@MetaClassTypes){
        next if !$for->can($mc_type);

        if(my $roles = $options{ $mc_type . '_roles' }){
            push @metaclass_map,
                ($mc_type => _make_new_class($for->$mc_type(), $roles));
        }
        elsif(my $mc = $options{$mc_type}){
            push @metaclass_map, ($mc_type => $mc);
        }
    }

    return $new_metaclass->reinitialize( $for, @metaclass_map );
}

sub apply_base_class_roles {
    my %options = @_;

    my $for = $options{for_class};

    my $meta = Mouse::Util::class_of($for);

    my $new_base = _make_new_class(
        $for,
        $options{roles},
        [ $meta->superclasses() ],
    );

    $meta->superclasses($new_base)
        if $new_base ne $meta->name();
    return;
}

sub _make_new_class {
    my($existing_class, $roles, $superclasses) = @_;

    if(!$superclasses){
        return $existing_class if !$roles;

        my $meta = Mouse::Meta::Class->initialize($existing_class);

        return $existing_class
            if !grep { !ref($_) && !$meta->does_role($_) } @{$roles};
    }

    return Mouse::Meta::Class->create_anon_class(
        superclasses => $superclasses ? $superclasses : [$existing_class],
        roles        => $roles,
        cache        => 1,
    )->name();
}

}
END_OF_TINY
    die $@ if $@;
} # unless Mouse.pm is loaded
package Mouse::Tiny;

Mouse::Exporter->setup_import_methods(also => 'Mouse');

1;
