#!/usr/bin/env perl

# This chunk of stuff was generated by App::FatPacker. To find the original
# file's code, look for the end of this BEGIN block or the string 'FATPACK'
BEGIN {
my %fatpacked;

$fatpacked{"Algorithm/C3.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'ALGORITHM_C3';

  package Algorithm::C3;

  use strict;
  use warnings;

  use Carp 'confess';

  our $VERSION = '0.10';

  sub merge {
      my ($root, $parent_fetcher, $cache) = @_;

      $cache ||= {};

      my @STACK; # stack for simulating recursion

      my $pfetcher_is_coderef = ref($parent_fetcher) eq 'CODE';

      unless ($pfetcher_is_coderef or $root->can($parent_fetcher)) {
          confess "Could not find method $parent_fetcher in $root";
      }

      my $current_root = $root;
      my $current_parents = [ $root->$parent_fetcher ];
      my $recurse_mergeout = [];
      my $i = 0;
      my %seen = ( $root => 1 );

      my ($new_root, $mergeout, %tails);
      while(1) {
          if($i < @$current_parents) {
              $new_root = $current_parents->[$i++];

              if($seen{$new_root}) {
                  my @isastack;
                  my $reached;
                  for(my $i = 0; $i < $#STACK; $i += 4) {
                      if($reached || ($reached = ($STACK[$i] eq $new_root))) {
                          push(@isastack, $STACK[$i]);
                      }
                  }
                  my $isastack = join(q{ -> }, @isastack, $current_root, $new_root);
                  die "Infinite loop detected in parents of '$root': $isastack";
              }
              $seen{$new_root} = 1;

              unless ($pfetcher_is_coderef or $new_root->can($parent_fetcher)) {
                  confess "Could not find method $parent_fetcher in $new_root";
              }

              push(@STACK, $current_root, $current_parents, $recurse_mergeout, $i);

              $current_root = $new_root;
              $current_parents = $cache->{pfetch}->{$current_root} ||= [ $current_root->$parent_fetcher ];
              $recurse_mergeout = [];
              $i = 0;
              next;
          }

          $seen{$current_root} = 0;

          $mergeout = $cache->{merge}->{$current_root} ||= do {

              # This do-block is the code formerly known as the function
              # that was a perl-port of the python code at
              # http://www.python.org/2.3/mro.html :)

              # Initial set (make sure everything is copied - it will be modded)
              my @seqs = map { [@$_] } @$recurse_mergeout;
              push(@seqs, [@$current_parents]) if @$current_parents;

              # Construct the tail-checking hash (actually, it's cheaper and still
              #   correct to re-use it throughout this function)
              foreach my $seq (@seqs) {
                  $tails{$seq->[$_]}++ for (1..$#$seq);
              }

              my @res = ( $current_root );
              while (1) {
                  my $cand;
                  my $winner;
                  foreach (@seqs) {
                      next if !@$_;
                      if(!$winner) {              # looking for a winner
                          $cand = $_->[0];        # seq head is candidate
                          next if $tails{$cand};  # he loses if in %tails

                          # Handy warn to give a output like the ones on
                          # http://www.python.org/download/releases/2.3/mro/
                          #warn " = " . join(' + ', @res) . "  + merge([" . join('] [',  map { join(', ', @$_) } grep { @$_ } @seqs) . "])\n";
                          push @res => $winner = $cand;
                          shift @$_;                # strip off our winner
                          $tails{$_->[0]}-- if @$_; # keep %tails sane
                      }
                      elsif($_->[0] eq $winner) {
                          shift @$_;                # strip off our winner
                          $tails{$_->[0]}-- if @$_; # keep %tails sane
                      }
                  }

                  # Handy warn to give a output like the ones on
                  # http://www.python.org/download/releases/2.3/mro/
                  #warn " = " . join(' + ', @res) . "\n" if !$cand;

                  last if !$cand;
                  die q{Inconsistent hierarchy found while merging '}
                      . $current_root . qq{':\n\t}
                      . qq{current merge results [\n\t\t}
                      . (join ",\n\t\t" => @res)
                      . qq{\n\t]\n\t} . qq{merging failed on '$cand'\n}
                    if !$winner;
              }
              \@res;
          };

          return @$mergeout if !@STACK;

          $i = pop(@STACK);
          $recurse_mergeout = pop(@STACK);
          $current_parents = pop(@STACK);
          $current_root = pop(@STACK);

          push(@$recurse_mergeout, $mergeout);
      }
  }

  1;

  __END__

  =pod

  =head1 NAME

  Algorithm::C3 - A module for merging hierarchies using the C3 algorithm

  =head1 SYNOPSIS

    use Algorithm::C3;

    # merging a classic diamond
    # inheritance graph like this:
    #
    #    <A>
    #   /   \
    # <B>   <C>
    #   \   /
    #    <D>

    my @merged = Algorithm::C3::merge(
        'D',
        sub {
            # extract the ISA array
            # from the package
            no strict 'refs';
            @{$_[0] . '::ISA'};
        }
    );

    print join ", " => @merged; # prints D, B, C, A

  =head1 DESCRIPTION

  This module implements the C3 algorithm. I have broken this out
  into it's own module because I found myself copying and pasting
  it way too often for various needs. Most of the uses I have for
  C3 revolve around class building and metamodels, but it could
  also be used for things like dependency resolution as well since
  it tends to do such a nice job of preserving local precedence
  orderings.

  Below is a brief explanation of C3 taken from the L<Class::C3>
  module. For more detailed information, see the L<SEE ALSO> section
  and the links there.

  =head2 What is C3?

  C3 is the name of an algorithm which aims to provide a sane method
  resolution order under multiple inheritance. It was first introduced
  in the language Dylan (see links in the L<SEE ALSO> section), and
  then later adopted as the preferred MRO (Method Resolution Order)
  for the new-style classes in Python 2.3. Most recently it has been
  adopted as the 'canonical' MRO for Perl 6 classes, and the default
  MRO for Parrot objects as well.

  =head2 How does C3 work.

  C3 works by always preserving local precedence ordering. This
  essentially means that no class will appear before any of it's
  subclasses. Take the classic diamond inheritance pattern for
  instance:

       <A>
      /   \
    <B>   <C>
      \   /
       <D>

  The standard Perl 5 MRO would be (D, B, A, C). The result being that
  B<A> appears before B<C>, even though B<C> is the subclass of B<A>.
  The C3 MRO algorithm however, produces the following MRO (D, B, C, A),
  which does not have this same issue.

  This example is fairly trivial, for more complex examples and a deeper
  explanation, see the links in the L<SEE ALSO> section.

  =head1 FUNCTION

  =over 4

  =item B<merge ($root, $func_to_fetch_parent, $cache)>

  This takes a C<$root> node, which can be anything really it
  is up to you. Then it takes a C<$func_to_fetch_parent> which
  can be either a CODE reference (see L<SYNOPSIS> above for an
  example), or a string containing a method name to be called
  on all the items being linearized. An example of how this
  might look is below:

    {
        package A;

        sub supers {
            no strict 'refs';
            @{$_[0] . '::ISA'};
        }

        package C;
        our @ISA = ('A');
        package B;
        our @ISA = ('A');
        package D;
        our @ISA = ('B', 'C');
    }

    print join ", " => Algorithm::C3::merge('D', 'supers');

  The purpose of C<$func_to_fetch_parent> is to provide a way
  for C<merge> to extract the parents of C<$root>. This is
  needed for C3 to be able to do it's work.

  The C<$cache> parameter is an entirely optional performance
  measure, and should not change behavior.

  If supplied, it should be a hashref that merge can use as a
  private cache between runs to speed things up.  Generally
  speaking, if you will be calling merge many times on related
  things, and the parent fetching function will return constant
  results given the same arguments during all of these calls,
  you can and should reuse the same shared cache hash for all
  of the calls.  Example:

    sub do_some_merging {
        my %merge_cache;
        my @foo_mro = Algorithm::C3::Merge('Foo', \&get_supers, \%merge_cache);
        my @bar_mro = Algorithm::C3::Merge('Bar', \&get_supers, \%merge_cache);
        my @baz_mro = Algorithm::C3::Merge('Baz', \&get_supers, \%merge_cache);
        my @quux_mro = Algorithm::C3::Merge('Quux', \&get_supers, \%merge_cache);
        # ...
    }

  =back

  =head1 CODE COVERAGE

  I use B<Devel::Cover> to test the code coverage of my tests, below
  is the B<Devel::Cover> report on this module's test suite.

   ------------------------ ------ ------ ------ ------ ------ ------ ------
   File                       stmt   bran   cond    sub    pod   time  total
   ------------------------ ------ ------ ------ ------ ------ ------ ------
   Algorithm/C3.pm           100.0  100.0  100.0  100.0  100.0  100.0  100.0
   ------------------------ ------ ------ ------ ------ ------ ------ ------
   Total                     100.0  100.0  100.0  100.0  100.0  100.0  100.0
   ------------------------ ------ ------ ------ ------ ------ ------ ------

  =head1 SEE ALSO

  =head2 The original Dylan paper

  =over 4

  =item L<http://www.webcom.com/haahr/dylan/linearization-oopsla96.html>

  =back

  =head2 The prototype Perl 6 Object Model uses C3

  =over 4

  =item L<http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel/>

  =back

  =head2 Parrot now uses C3

  =over 4

  =item L<http://aspn.activestate.com/ASPN/Mail/Message/perl6-internals/2746631>

  =item L<http://use.perl.org/~autrijus/journal/25768>

  =back

  =head2 Python 2.3 MRO related links

  =over 4

  =item L<http://www.python.org/2.3/mro.html>

  =item L<http://www.python.org/2.2.2/descrintro.html#mro>

  =back

  =head2 C3 for TinyCLOS

  =over 4

  =item L<http://www.call-with-current-continuation.org/eggs/c3.html>

  =back

  =head1 AUTHORS

  Stevan Little, E<lt>stevan@iinteractive.comE<gt>

  Brandon L. Black, E<lt>blblack@gmail.comE<gt>

  =head1 COPYRIGHT AND LICENSE

  Copyright 2006 by Infinity Interactive, Inc.

  L<http://www.iinteractive.com>

  This library is free software; you can redistribute it and/or modify
  it under the same terms as Perl itself.

  =cut
ALGORITHM_C3

$fatpacked{"B/Hooks/EndOfScope.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'B_HOOKS_ENDOFSCOPE';
  package B::Hooks::EndOfScope; # git description: 0.23-2-ga391106
  # ABSTRACT: Execute code after a scope finished compilation
  # KEYWORDS: code hooks execution scope

  use strict;
  use warnings;

  our $VERSION = '0.24';

  use 5.006001;

  BEGIN {
    use Module::Implementation 0.05;
    Module::Implementation::build_loader_sub(
      implementations => [ 'XS', 'PP' ],
      symbols => [ 'on_scope_end' ],
    )->();
  }

  use Sub::Exporter::Progressive 0.001006 -setup => {
    exports => [ 'on_scope_end' ],
    groups  => { default => ['on_scope_end'] },
  };

  1;

  __END__

  =pod

  =encoding UTF-8

  =head1 NAME

  B::Hooks::EndOfScope - Execute code after a scope finished compilation

  =head1 VERSION

  version 0.24

  =head1 SYNOPSIS

      on_scope_end { ... };

  =head1 DESCRIPTION

  This module allows you to execute code when perl finished compiling the
  surrounding scope.

  =head1 FUNCTIONS

  =head2 on_scope_end

      on_scope_end { ... };

      on_scope_end $code;

  Registers C<$code> to be executed after the surrounding scope has been
  compiled.

  This is exported by default. See L<Sub::Exporter> on how to customize it.

  =head1 LIMITATIONS

  =head2 Pure-perl mode caveat

  This caveat applies to B<any> version of perl where L<Variable::Magic>
  is unavailable or otherwise disabled.

  While L<Variable::Magic> has access to some very dark sorcery to make it
  possible to throw an exception from within a callback, the pure-perl
  implementation does not have access to these hacks. Therefore, what
  would have been a B<compile-time exception> is instead B<converted to a
  warning>, and your execution will continue as if the exception never
  happened.

  To explicitly request an XS (or PP) implementation one has two choices. Either
  to import from the desired implementation explicitly:

   use B::Hooks::EndOfScope::XS
     or
   use B::Hooks::EndOfScope::PP

  or by setting C<$ENV{B_HOOKS_ENDOFSCOPE_IMPLEMENTATION}> to either C<XS> or
  C<PP>.

  =head2 Perl 5.8.0 ~ 5.8.3

  Due to a L<core interpreter bug
  |https://rt.perl.org/Public/Bug/Display.html?id=27040#txn-82797> present in
  older perl versions, the implementation of B::Hooks::EndOfScope deliberately
  leaks a single empty hash for every scope being cleaned. This is done to
  avoid the memory corruption associated with the bug mentioned above.

  In order to stabilize this workaround use of L<Variable::Magic> is disabled
  on perls prior to version 5.8.4. On such systems loading/requesting
  L<B::Hooks::EndOfScope::XS> explicitly will result in a compile-time
  exception.

  =head2 Perl versions 5.6.x

  Versions of perl before 5.8.0 lack a feature allowing changing the visibility
  of C<%^H> via setting bit 17 within C<$^H>. As such the only way to achieve
  the effect necessary for this module to work, is to use the C<local> operator
  explicitly on these platforms. This might lead to unexpected interference
  with other scope-driven libraries relying on the same mechanism. On the flip
  side there are no such known incompatibilities at the time this note was
  written.

  For further details on the unavailable behavior please refer to the test
  file F<t/02-localise.t> included with the distribution.

  =head1 SEE ALSO

  L<Sub::Exporter>

  L<Variable::Magic>

  =head1 SUPPORT

  Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=B-Hooks-EndOfScope>
  (or L<bug-B-Hooks-EndOfScope@rt.cpan.org|mailto:bug-B-Hooks-EndOfScope@rt.cpan.org>).

  =head1 AUTHORS

  =over 4

  =item *

  Florian Ragwitz <rafl@debian.org>

  =item *

  Peter Rabbitson <ribasushi@leporine.io>

  =back

  =head1 CONTRIBUTORS

  =for stopwords Karen Etheridge Tatsuhiko Miyagawa Christian Walde Tomas Doran Graham Knop Simon Wilper

  =over 4

  =item *

  Karen Etheridge <ether@cpan.org>

  =item *

  Tatsuhiko Miyagawa <miyagawa@bulknews.net>

  =item *

  Christian Walde <walde.christian@googlemail.com>

  =item *

  Tomas Doran <bobtfish@bobtfish.net>

  =item *

  Graham Knop <haarg@haarg.org>

  =item *

  Simon Wilper <sxw@chronowerks.de>

  =back

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2008 by Florian Ragwitz.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =cut
B_HOOKS_ENDOFSCOPE

$fatpacked{"B/Hooks/EndOfScope/PP.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'B_HOOKS_ENDOFSCOPE_PP';
  package B::Hooks::EndOfScope::PP;
  # ABSTRACT: Execute code after a scope finished compilation - PP implementation

  use warnings;
  use strict;

  our $VERSION = '0.24';

  use constant _PERL_VERSION => "$]";

  BEGIN {
    if (_PERL_VERSION =~ /^5\.009/) {
      # CBA to figure out where %^H got broken and which H::U::HH is sane enough
      die "By design B::Hooks::EndOfScope does not operate in pure-perl mode on perl 5.9.X\n"
    }
    elsif (_PERL_VERSION < '5.010') {
      require B::Hooks::EndOfScope::PP::HintHash;
      *on_scope_end = \&B::Hooks::EndOfScope::PP::HintHash::on_scope_end;
    }
    else {
      require B::Hooks::EndOfScope::PP::FieldHash;
      *on_scope_end = \&B::Hooks::EndOfScope::PP::FieldHash::on_scope_end;
    }
  }

  use Sub::Exporter::Progressive 0.001006 -setup => {
    exports => ['on_scope_end'],
    groups  => { default => ['on_scope_end'] },
  };

  sub __invoke_callback {
    local $@;
    eval { $_[0]->(); 1 } or do {
      my $err = $@;
      require Carp;
      Carp::cluck( (join ' ',
        'A scope-end callback raised an exception, which can not be propagated when',
        'B::Hooks::EndOfScope operates in pure-perl mode. Your program will CONTINUE',
        'EXECUTION AS IF NOTHING HAPPENED AFTER THIS WARNING. Below is the complete',
        'exception text, followed by a stack-trace of the callback execution:',
      ) . "\n\n$err\n\r" );

      sleep 1 if -t *STDERR;  # maybe a bad idea...?
    };
  }

  1;

  __END__

  =pod

  =encoding UTF-8

  =head1 NAME

  B::Hooks::EndOfScope::PP - Execute code after a scope finished compilation - PP implementation

  =head1 VERSION

  version 0.24

  =head1 DESCRIPTION

  This is the pure-perl implementation of L<B::Hooks::EndOfScope> based only on
  modules available as part of the perl core. Its leaner sibling
  L<B::Hooks::EndOfScope::XS> will be automatically preferred if all
  dependencies are available and C<$ENV{B_HOOKS_ENDOFSCOPE_IMPLEMENTATION}> is
  not set to C<'PP'>.

  =head1 FUNCTIONS

  =head2 on_scope_end

      on_scope_end { ... };

      on_scope_end $code;

  Registers C<$code> to be executed after the surrounding scope has been
  compiled.

  This is exported by default. See L<Sub::Exporter> on how to customize it.

  =head1 SUPPORT

  Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=B-Hooks-EndOfScope>
  (or L<bug-B-Hooks-EndOfScope@rt.cpan.org|mailto:bug-B-Hooks-EndOfScope@rt.cpan.org>).

  =head1 AUTHORS

  =over 4

  =item *

  Florian Ragwitz <rafl@debian.org>

  =item *

  Peter Rabbitson <ribasushi@leporine.io>

  =back

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2008 by Florian Ragwitz.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =cut
B_HOOKS_ENDOFSCOPE_PP

$fatpacked{"B/Hooks/EndOfScope/PP/FieldHash.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'B_HOOKS_ENDOFSCOPE_PP_FIELDHASH';
  # Implementation of a pure-perl on_scope_end for perls > 5.10
  # (relies on Hash::Util:FieldHash)

  package # hide from pause
    B::Hooks::EndOfScope::PP::FieldHash;

  use strict;
  use warnings;

  our $VERSION = '0.24';

  use Tie::Hash ();
  use Hash::Util::FieldHash 'fieldhash';

  # Here we rely on a combination of several behaviors:
  #
  # * %^H is deallocated on scope exit, so any references to it disappear
  # * A lost weakref in a fieldhash causes the corresponding key to be deleted
  # * Deletion of a key on a tied hash triggers DELETE
  #
  # Therefore the DELETE of a tied fieldhash containing a %^H reference will
  # be the hook to fire all our callbacks.

  fieldhash my %hh;
  {
    package # hide from pause too
      B::Hooks::EndOfScope::PP::_TieHintHashFieldHash;
    our @ISA = ( 'Tie::StdHash' );  # in Tie::Hash, in core
    sub DELETE {
      my $ret = shift->SUPER::DELETE(@_);
      B::Hooks::EndOfScope::PP::__invoke_callback($_) for @$ret;
      $ret;
    }
  }

  sub on_scope_end (&) {
    $^H |= 0x020000;

    tie(%hh, 'B::Hooks::EndOfScope::PP::_TieHintHashFieldHash')
      unless tied %hh;

    push @{ $hh{\%^H} ||= [] }, $_[0];
  }

  1;
B_HOOKS_ENDOFSCOPE_PP_FIELDHASH

$fatpacked{"B/Hooks/EndOfScope/PP/HintHash.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'B_HOOKS_ENDOFSCOPE_PP_HINTHASH';
  # Implementation of a pure-perl on_scope_end for perls < 5.10
  # (relies on lack of compile/runtime duality of %^H before 5.10
  # which makes guard object operation possible)

  package # hide from the pauses
    B::Hooks::EndOfScope::PP::HintHash;

  use strict;
  use warnings;

  our $VERSION = '0.24';

  use Scalar::Util ();
  use constant _NEEDS_MEMORY_CORRUPTION_FIXUP => (
    "$]" >= 5.008
      and
    "$]" < 5.008004
  ) ? 1 : 0;


  use constant _PERL_VERSION => "$]";

  # This is the original implementation, which sadly is broken
  # on perl 5.10+ within string evals
  sub on_scope_end (&) {

    # the scope-implicit %^H localization is a 5.8+ feature
    $^H |= 0x020000
      if _PERL_VERSION >= 5.008;

    # the explicit localization of %^H works on anything < 5.10
    # but we use it only on 5.6 where fiddling $^H has no effect
    local %^H = %^H
      if _PERL_VERSION < 5.008;

    # Workaround for memory corruption during implicit $^H-induced
    # localization of %^H on 5.8.0~5.8.3, see extended comment below
    bless \%^H, 'B::Hooks::EndOfScope::PP::HintHash::__GraveyardTransport' if (
      _NEEDS_MEMORY_CORRUPTION_FIXUP
        and
      ref \%^H eq 'HASH'  # only bless if it is a "pure hash" to start with
    );

    # localised %^H behaves funny on 5.8 - a
    # 'local %^H;'
    # is in effect the same as
    # 'local %^H = %^H;'
    # therefore make sure we use different keys so that things do not
    # fire too early due to hashkey overwrite
    push @{
      $^H{sprintf '__B_H_EOS__guardstack_0X%x', Scalar::Util::refaddr(\%^H) }
        ||= bless ([], 'B::Hooks::EndOfScope::PP::_SG_STACK')
    }, $_[0];
  }

  sub B::Hooks::EndOfScope::PP::_SG_STACK::DESTROY {
    B::Hooks::EndOfScope::PP::__invoke_callback($_) for @{$_[0]};
  }

  # This scope implements a clunky yet effective workaround for a core perl bug
  # https://rt.perl.org/Public/Bug/Display.html?id=27040#txn-82797
  #
  # While we can not prevent the hinthash being marked for destruction twice,
  # we *can* intercept the first DESTROY pass, and squirrel away the entire
  # structure, until a time it can (hopefully) no longer do any visible harm
  #
  # There still *will* be corruption by the time we get to free it for real,
  # since we can not prevent Perl's erroneous SAVEFREESV mark. What we hope is
  # that by then the corruption will no longer matter
  #
  # Yes, this code does leak by design. Yes it is better than the alternative.
  {
    my @Hint_Hash_Graveyard;

    # "Leak" this entire structure: ensures it and its contents will not be
    # garbage collected until the very very very end
    push @Hint_Hash_Graveyard, \@Hint_Hash_Graveyard
      if _NEEDS_MEMORY_CORRUPTION_FIXUP;

    sub B::Hooks::EndOfScope::PP::HintHash::__GraveyardTransport::DESTROY {

      # Resurrect the hinthash being destroyed, persist it into the graveyard
      push @Hint_Hash_Graveyard, $_[0];

      # ensure we won't try to re-resurrect during GlobalDestroy
      bless $_[0], 'B::Hooks::EndOfScope::PP::HintHash::__DeactivateGraveyardTransport';

      # Perform explicit free of elements (if any) triggering all callbacks
      # This is what would have happened without this code being active
      %{$_[0]} = ();
    }
  }

  1;
B_HOOKS_ENDOFSCOPE_PP_HINTHASH

$fatpacked{"B/Hooks/EndOfScope/XS.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'B_HOOKS_ENDOFSCOPE_XS';
  package B::Hooks::EndOfScope::XS;
  # ABSTRACT: Execute code after a scope finished compilation - XS implementation

  use strict;
  use warnings;

  our $VERSION = '0.24';

  # Limit the V::M-based (XS) version to perl 5.8.4+
  #
  # Given the unorthodox stuff we do to work around the hinthash double-free
  # might as well play it safe and only implement it in the PP version
  # and leave it at that
  # https://rt.perl.org/Public/Bug/Display.html?id=27040#txn-82797
  #
  use 5.008004;

  use Variable::Magic 0.48 ();
  use Sub::Exporter::Progressive 0.001006 -setup => {
    exports => ['on_scope_end'],
    groups  => { default => ['on_scope_end'] },
  };

  my $wiz = Variable::Magic::wizard
    data => sub { [$_[1]] },
    free => sub { $_->() for @{ $_[1] }; () },
    # When someone localise %^H, our magic doesn't want to be copied
    # down. We want it to be around only for the scope we've initially
    # attached ourselves to. Merely having MGf_LOCAL and a noop svt_local
    # callback achieves this. If anything wants to attach more magic of our
    # kind to a localised %^H, things will continue to just work as we'll be
    # attached with a new and empty callback list.
    local => \undef
  ;

  sub on_scope_end (&) {
    $^H |= 0x020000;

    if (my $stack = Variable::Magic::getdata %^H, $wiz) {
      push @{ $stack }, $_[0];
    }
    else {
      Variable::Magic::cast %^H, $wiz, $_[0];
    }
  }

  1;

  __END__

  =pod

  =encoding UTF-8

  =head1 NAME

  B::Hooks::EndOfScope::XS - Execute code after a scope finished compilation - XS implementation

  =head1 VERSION

  version 0.24

  =head1 DESCRIPTION

  This is the implementation of L<B::Hooks::EndOfScope> based on
  L<Variable::Magic>, which is an XS module dependent on a compiler. It will
  always be automatically preferred if L<Variable::Magic> is available.

  =head1 FUNCTIONS

  =head2 on_scope_end

      on_scope_end { ... };

      on_scope_end $code;

  Registers C<$code> to be executed after the surrounding scope has been
  compiled.

  This is exported by default. See L<Sub::Exporter> on how to customize it.

  =head1 SUPPORT

  Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=B-Hooks-EndOfScope>
  (or L<bug-B-Hooks-EndOfScope@rt.cpan.org|mailto:bug-B-Hooks-EndOfScope@rt.cpan.org>).

  =head1 AUTHORS

  =over 4

  =item *

  Florian Ragwitz <rafl@debian.org>

  =item *

  Peter Rabbitson <ribasushi@leporine.io>

  =back

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2008 by Florian Ragwitz.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =cut
B_HOOKS_ENDOFSCOPE_XS

$fatpacked{"Bio/Cigar.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'BIO_CIGAR';
  package Bio::Cigar;

  use strict;
  use warnings;
  use 5.014;

  =encoding utf-8

  =head1 NAME

  Bio::Cigar - Parse CIGAR strings and translate coordinates to/from reference/query

  =head1 SYNOPSIS

      use 5.014;
      use Bio::Cigar;
      my $cigar = Bio::Cigar->new("2M1D1M1I4M");
      say "Query length is ", $cigar->query_length;
      say "Reference length is ", $cigar->reference_length;

      my ($qpos, $op) = $cigar->rpos_to_qpos(3);
      say "Alignment operation at reference position 3 is $op";

  =head1 DESCRIPTION

  Bio::Cigar is a small library to parse CIGAR strings ("Compact Idiosyncratic
  Gapped Alignment Report"), such as those used in the SAM file format.  CIGAR
  strings are a run-length encoding which minimally describes the alignment of a
  query sequence to an (often longer) reference sequence.

  Parsing follows the L<SAM v1 spec|http://samtools.github.io/hts-specs/SAMv1.pdf>
  for the C<CIGAR> column.

  Parsed strings are represented by an object that provides a few utility
  methods.

  =head1 ATTRIBUTES

  All attributes are read-only.

  =head2 string

  The CIGAR string for this object.

  =head2 reference_length

  The length of the reference sequence segment aligned with the query sequence
  described by the CIGAR string.

  =head2 query_length

  The length of the query sequence described by the CIGAR string.

  =head2 ops

  An arrayref of C<[length, operation]> tuples describing the CIGAR string.
  Lengths are integers, L<possible operations are below|/"CIGAR operations">.

  =cut

  our $VERSION = '1.01';

  use Moo;
  use Types::Standard qw< ArrayRef Tuple Int Enum StrMatch >;
  use List::Util qw< sum >;
  use Carp qw< croak >;
  use namespace::clean;

  =head3 CIGAR operations

  The CIGAR operations are given in the following table, taken from the SAM v1
  spec:

      Op  Description
      ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
      M   alignment match (can be a sequence match or mismatch)
      I   insertion to the reference
      D   deletion from the reference
      N   skipped region from the reference
      S   soft clipping (clipped sequences present in SEQ)
      H   hard clipping (clipped sequences NOT present in SEQ)
      P   padding (silent deletion from padded reference)
      =   sequence match
      X   sequence mismatch

      • H can only be present as the first and/or last operation.
      • S may only have H operations between them and the ends of the string.
      • For mRNA-to-genome alignment, an N operation represents an intron.
        For other types of alignments, the interpretation of N is not defined.
      • Sum of the lengths of the M/I/S/=/X operations shall equal the length of SEQ.

  =cut

  our $CIGAR_REGEX = qr/^
      (\d*H)?(\d*S)?
      (?<OP>\d*[MIDNP=X])*
      (\d*S)?(\d*H)?
  $/xa;


  has 'string',
      is       => 'ro',
      isa      => StrMatch[ $CIGAR_REGEX ],
      required => 1;

  has 'query_length',
      lazy    => 1,
      is      => 'ro',
      isa     => Int,
      default => sub { sum(map { $_ || 1 } $_[0]->string =~ /(\d*)[MIS=X]/ga) || 0 };

  has 'reference_length',
      lazy    => 1,
      is      => 'ro',
      isa     => Int,
      default => sub { sum(map { $_ || 1 } $_[0]->string =~ /(\d*)[MDN=X]/ga) || 0 };

  has 'ops',
      lazy    => 1,
      is      => 'ro',
      isa     => ArrayRef[ Tuple[ Int, Enum[split '', 'MIDNSHP=X'] ] ],
      builder => '_parse';

  sub BUILDARGS {
      my $class = shift;
      if (@_ == 1 and not ref $_[0]) {
          return { string => $_[0] };
      } else {
          croak sprintf "%s->new must be called with a string as the sole argument", __PACKAGE__;
      }
  }

  sub _parse {
      my $self  = shift;
      my $cigar = $self->string;
      my @ops;
      for my $op (grep defined, $cigar =~ /(\d*[MIDNSHP=X])/g) {
          my ($len, $type) = $op =~ /(\d*)(\D*)/a;
          push @ops, [ $len || 1, uc $type ];
      }
      return \@ops;
  }

  =head1 CONSTRUCTOR

  =head2 new

  Takes a CIGAR string as the sole argument and returns a new Bio::Cigar object.

  =head1 METHODS

  =head2 rpos_to_qpos

  Takes a reference position (origin 1, base-numbered) and returns the
  corresponding position (origin 1, base-numbered) on the query sequence.  Indels
  affect how the numbering maps from reference to query.

  In list context returns a tuple of C<[query position, operation at position]>.
  Operation is a single-character string.  See the
  L<table of CIGAR operations|/"CIGAR operations">.

  If the reference position does not map to the query sequence (as with a
  deletion, for example), returns C<undef> or C<[undef, operation]>.

  =head2 qpos_to_rpos

  Takes a query position (origin 1, base-numbered) and returns the corresponding
  position (origin 1, base-numbered) on the reference sequence.  Indels affect
  how the numbering maps from query to reference.

  In list context returns a tuple of C<[references position, operation at position]>.
  Operation is a single-character string.  See the
  L<table of CIGAR operations|/"CIGAR operations">.

  If the query position does not map to the reference sequence (as with an
  insertion, for example), returns C<undef> or C<[undef, operation]>.

  =head2 op_at_rpos

  Takes a reference position and returns the operation at that position.  Simply
  a shortcut for calling L</rpos_to_qpos> in list context and discarding the
  first return value.

  =head2 op_at_qpos

  Takes a query position and returns the operation at that position.  Simply
  a shortcut for calling L</qpos_to_rpos> in list context and discarding the
  first return value.

  =cut

  # Consumption table based on
  # https://github.com/samtools/htslib/blob/develop/htslib/sam.h#L81-L100
  my %op_consumes = (
      # op => [query, reference]
      'M' => [1, 1],
      'I' => [1, 0],
      'D' => [0, 1],
      'N' => [0, 1],
      'S' => [1, 0],
      'H' => [0, 0],
      'P' => [0, 0],
      '=' => [1, 1],
      'X' => [1, 1],
  );

  sub rpos_to_qpos {
      my $self = shift;
      return $self->_map_position( rpos => @_ );
  }

  sub qpos_to_rpos {
      my $self = shift;
      return $self->_map_position( qpos => @_ );
  }

  sub _map_position {
      my $self   = shift;
      my $from   = shift;
      my $target = shift;
      my $target_len = $from eq "rpos" ? "reference_length" : "query_length";

      my $rpos   = 0;
      my $qpos   = 0;

      croak sprintf "$from = %d is < 1 or > $target_len (%d)", $target, $self->$target_len
          if $target < 1 or $target > $self->$target_len;

      # Each cigar operation consumes the reference, query, or both.  We keep
      # track of both positions until the query/reference position hits the
      # target.  Then we return the equivalent other position.

      for my $op (@{ $self->ops }) {
          my ($len, $type) = @$op;
          my $consumes = $op_consumes{$type};
          next unless $consumes->[0] or $consumes->[1];

          $qpos += $len if $consumes->[0];
          $rpos += $len if $consumes->[1];

          # The logic could be written with more variables to reduce the
          # duplication in this if/else, but I think the clarity of the logic is
          # enhanced by the similarity of the if/else branches.  Adding more
          # varibles to make the logic generic muddies the simplicity.
          if ($from eq "rpos") {
              if ($rpos > $target) {
                  my $overshoot = $rpos - $target;
                  $rpos -= $overshoot;
                  $qpos -= $overshoot;
              }
              if ($rpos == $target) {
                  if ($consumes->[1] and not $consumes->[0]) {
                      # Reference positions which are missing in the query sequence
                      # don't have a corresponding query position.
                      return wantarray ? (undef, $type) : undef;
                  } else {
                      $qpos <= $self->query_length
                          or croak sprintf "Bug! Assertion failed: qpos <= qlen"
                                         . " (target = %d, rpos = %d, qpos = %d, qlen = %d, cigar = %s)",
                              $target, $rpos, $qpos, $self->query_length, $self->string;
                      return wantarray ? ($qpos, $type) : $qpos;
                  }
              }
          } else {
              if ($qpos > $target) {
                  my $overshoot = $qpos - $target;
                  $rpos -= $overshoot;
                  $qpos -= $overshoot;
              }
              if ($qpos == $target) {
                  if ($consumes->[0] and not $consumes->[1]) {
                      # Query positions which are insertions in the reference sequence
                      # don't have a corresponding reference position.
                      return wantarray ? (undef, $type) : undef;
                  } else {
                      $rpos <= $self->reference_length
                          or croak sprintf "Bug! Assertion failed: rpos <= rlen"
                                         . " (target = %d, qpos = %d, rpos = %d, rlen = %d, cigar = %s)",
                              $target, $qpos, $rpos, $self->reference_length, $self->string;
                      return wantarray ? ($rpos, $type) : $rpos;
                  }
              }
          }
      }
      croak sprintf "Bug! Ran out of ops but couldn't map %s %d"
                  . " (rpos = %d, qpos = %d, cigar = %s)",
          $from, $target, $rpos, $qpos, $self->string;
  }

  sub op_at_rpos {
      my $self = shift;
      my ($qpos, $type) = $self->rpos_to_qpos(@_);
      return $type;
  }

  sub op_at_qpos {
      my $self = shift;
      my ($rpos, $type) = $self->qpos_to_rpos(@_);
      return $type;
  }

  =head1 AUTHOR

  Thomas Sibley E<lt>trsibley@uw.eduE<gt>

  =head1 COPYRIGHT

  Copyright 2014- Mullins Lab, Department of Microbiology, University of Washington.

  =head1 LICENSE

  This library is free software; you can redistribute it and/or modify it under
  the GNU General Public License, version 2.

  =head1 SEE ALSO

  L<SAMv1 spec|http://samtools.github.io/hts-specs/SAMv1.pdf>

  =cut

  1;
BIO_CIGAR

$fatpacked{"Class/C3.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'CLASS_C3';
  package Class::C3;

  use strict;
  use warnings;

  our $VERSION = '0.34';

  our $C3_IN_CORE;
  our $C3_XS;

  BEGIN {
      if($] > 5.009_004) {
          $C3_IN_CORE = 1;
          require mro;
      }
      elsif($C3_XS or not defined $C3_XS) {
          my $error = do {
              local $@;
              eval { require Class::C3::XS };
              $@;
          };

          if ($error) {
              die $error if $error !~ /\blocate\b/;

              if ($C3_XS) {
                  require Carp;
                  Carp::croak( "XS explicitly requested but Class::C3::XS is not available" );
              }

              require Algorithm::C3;
              require Class::C3::next;
          }
          else {
              $C3_XS = 1;
          }
      }
  }

  # this is our global stash of both
  # MRO's and method dispatch tables
  # the structure basically looks like
  # this:
  #
  #   $MRO{$class} = {
  #      MRO => [ <class precedence list> ],
  #      methods => {
  #          orig => <original location of method>,
  #          code => \&<ref to original method>
  #      },
  #      has_overload_fallback => (1 | 0)
  #   }
  #
  our %MRO;

  # use these for debugging ...
  sub _dump_MRO_table { %MRO }
  our $TURN_OFF_C3 = 0;

  # state tracking for initialize()/uninitialize()
  our $_initialized = 0;

  sub import {
      my $class = caller();
      # skip if the caller is main::
      # since that is clearly not relevant
      return if $class eq 'main';

      return if $TURN_OFF_C3;
      mro::set_mro($class, 'c3') if $C3_IN_CORE;

      # make a note to calculate $class
      # during INIT phase
      $MRO{$class} = undef unless exists $MRO{$class};
  }

  ## initializers

  # This prevents silly warnings when Class::C3 is
  #  used explicitly along with MRO::Compat under 5.9.5+

  { no warnings 'redefine';

  sub initialize {
      %next::METHOD_CACHE = ();
      # why bother if we don't have anything ...
      return unless keys %MRO;
      if($C3_IN_CORE) {
          mro::set_mro($_, 'c3') for keys %MRO;
      }
      else {
          if($_initialized) {
              uninitialize();
              $MRO{$_} = undef foreach keys %MRO;
          }
          _calculate_method_dispatch_tables();
          _apply_method_dispatch_tables();
          $_initialized = 1;
      }
  }

  sub uninitialize {
      # why bother if we don't have anything ...
      %next::METHOD_CACHE = ();
      return unless keys %MRO;
      if($C3_IN_CORE) {
          mro::set_mro($_, 'dfs') for keys %MRO;
      }
      else {
          _remove_method_dispatch_tables();
          $_initialized = 0;
      }
  }

  sub reinitialize { goto &initialize }

  } # end of "no warnings 'redefine'"

  ## functions for applying C3 to classes

  sub _calculate_method_dispatch_tables {
      return if $C3_IN_CORE;
      my %merge_cache;
      foreach my $class (keys %MRO) {
          _calculate_method_dispatch_table($class, \%merge_cache);
      }
  }

  sub _calculate_method_dispatch_table {
      return if $C3_IN_CORE;
      my ($class, $merge_cache) = @_;
      no strict 'refs';
      my @MRO = calculateMRO($class, $merge_cache);
      $MRO{$class} = { MRO => \@MRO };
      my $has_overload_fallback;
      my %methods;
      # NOTE:
      # we do @MRO[1 .. $#MRO] here because it
      # makes no sense to interrogate the class
      # which you are calculating for.
      foreach my $local (@MRO[1 .. $#MRO]) {
          # if overload has tagged this module to
          # have use "fallback", then we want to
          # grab that value
          $has_overload_fallback = ${"${local}::()"}
              if !defined $has_overload_fallback && defined ${"${local}::()"};
          foreach my $method (grep { defined &{"${local}::$_"} } keys %{"${local}::"}) {
              # skip if already overridden in local class
              next unless !defined *{"${class}::$method"}{CODE};
              $methods{$method} = {
                  orig => "${local}::$method",
                  code => \&{"${local}::$method"}
              } unless exists $methods{$method};
          }
      }
      # now stash them in our %MRO table
      $MRO{$class}->{methods} = \%methods;
      $MRO{$class}->{has_overload_fallback} = $has_overload_fallback;
  }

  sub _apply_method_dispatch_tables {
      return if $C3_IN_CORE;
      foreach my $class (keys %MRO) {
          _apply_method_dispatch_table($class);
      }
  }

  sub _apply_method_dispatch_table {
      return if $C3_IN_CORE;
      my $class = shift;
      no strict 'refs';
      ${"${class}::()"} = $MRO{$class}->{has_overload_fallback}
          if !defined &{"${class}::()"}
             && defined $MRO{$class}->{has_overload_fallback};
      foreach my $method (keys %{$MRO{$class}->{methods}}) {
          if ( $method =~ /^\(/ ) {
              my $orig = $MRO{$class}->{methods}->{$method}->{orig};
              ${"${class}::$method"} = $$orig if defined $$orig;
          }
          *{"${class}::$method"} = $MRO{$class}->{methods}->{$method}->{code};
      }
  }

  sub _remove_method_dispatch_tables {
      return if $C3_IN_CORE;
      foreach my $class (keys %MRO) {
          _remove_method_dispatch_table($class);
      }
  }

  sub _remove_method_dispatch_table {
      return if $C3_IN_CORE;
      my $class = shift;
      no strict 'refs';
      delete ${"${class}::"}{"()"} if $MRO{$class}->{has_overload_fallback};
      foreach my $method (keys %{$MRO{$class}->{methods}}) {
          delete ${"${class}::"}{$method}
              if defined *{"${class}::${method}"}{CODE} &&
                 (*{"${class}::${method}"}{CODE} eq $MRO{$class}->{methods}->{$method}->{code});
      }
  }

  sub calculateMRO {
      my ($class, $merge_cache) = @_;

      return Algorithm::C3::merge($class, sub {
          no strict 'refs';
          @{$_[0] . '::ISA'};
      }, $merge_cache);
  }

  # Method overrides to support 5.9.5+ or Class::C3::XS

  sub _core_calculateMRO { @{mro::get_linear_isa($_[0], 'c3')} }

  if($C3_IN_CORE) {
      no warnings 'redefine';
      *Class::C3::calculateMRO = \&_core_calculateMRO;
  }
  elsif($C3_XS) {
      no warnings 'redefine';
      *Class::C3::calculateMRO = \&Class::C3::XS::calculateMRO;
      *Class::C3::_calculate_method_dispatch_table
          = \&Class::C3::XS::_calculate_method_dispatch_table;
  }

  1;

  __END__

  =pod

  =head1 NAME

  Class::C3 - A pragma to use the C3 method resolution order algorithm

  =head1 SYNOPSIS

      # NOTE - DO NOT USE Class::C3 directly as a user, use MRO::Compat instead!
      package ClassA;
      use Class::C3;
      sub hello { 'A::hello' }

      package ClassB;
      use base 'ClassA';
      use Class::C3;

      package ClassC;
      use base 'ClassA';
      use Class::C3;

      sub hello { 'C::hello' }

      package ClassD;
      use base ('ClassB', 'ClassC');
      use Class::C3;

      # Classic Diamond MI pattern
      #    <A>
      #   /   \
      # <B>   <C>
      #   \   /
      #    <D>

      package main;

      # initializez the C3 module
      # (formerly called in INIT)
      Class::C3::initialize();

      print join ', ' => Class::C3::calculateMRO('ClassD'); # prints ClassD, ClassB, ClassC, ClassA

      print ClassD->hello(); # prints 'C::hello' instead of the standard p5 'A::hello'

      ClassD->can('hello')->();          # can() also works correctly
      UNIVERSAL::can('ClassD', 'hello'); # as does UNIVERSAL::can()

  =head1 DESCRIPTION

  This is pragma to change Perl 5's standard method resolution order from depth-first left-to-right
  (a.k.a - pre-order) to the more sophisticated C3 method resolution order.

  B<NOTE:> YOU SHOULD NOT USE THIS MODULE DIRECTLY - The feature provided
  is integrated into perl version >= 5.9.5, and you should use L<MRO::Compat>
  instead, which will use the core implementation in newer perls, but fallback
  to using this implementation on older perls.

  =head2 What is C3?

  C3 is the name of an algorithm which aims to provide a sane method resolution order under multiple
  inheritance. It was first introduced in the language Dylan (see links in the L<SEE ALSO> section),
  and then later adopted as the preferred MRO (Method Resolution Order) for the new-style classes in
  Python 2.3. Most recently it has been adopted as the 'canonical' MRO for Perl 6 classes, and the
  default MRO for Parrot objects as well.

  =head2 How does C3 work.

  C3 works by always preserving local precedence ordering. This essentially means that no class will
  appear before any of its subclasses. Take the classic diamond inheritance pattern for instance:

       <A>
      /   \
    <B>   <C>
      \   /
       <D>

  The standard Perl 5 MRO would be (D, B, A, C). The result being that B<A> appears before B<C>, even
  though B<C> is the subclass of B<A>. The C3 MRO algorithm however, produces the following MRO
  (D, B, C, A), which does not have this same issue.

  This example is fairly trivial, for more complex examples and a deeper explanation, see the links in
  the L<SEE ALSO> section.

  =head2 How does this module work?

  This module uses a technique similar to Perl 5's method caching. When C<Class::C3::initialize> is
  called, this module calculates the MRO of all the classes which called C<use Class::C3>. It then
  gathers information from the symbol tables of each of those classes, and builds a set of method
  aliases for the correct dispatch ordering. Once all these C3-based method tables are created, it
  then adds the method aliases into the local classes symbol table.

  The end result is actually classes with pre-cached method dispatch. However, this caching does not
  do well if you start changing your C<@ISA> or messing with class symbol tables, so you should consider
  your classes to be effectively closed. See the L<CAVEATS> section for more details.

  =head1 OPTIONAL LOWERCASE PRAGMA

  This release also includes an optional module B<c3> in the F<opt/> folder. I did not include this in
  the regular install since lowercase module names are considered I<"bad"> by some people. However I
  think that code looks much nicer like this:

    package MyClass;
    use c3;

  This is more clunky:

    package MyClass;
    use Class::C3;

  But hey, it's your choice, that's why it is optional.

  =head1 FUNCTIONS

  =over 4

  =item B<calculateMRO ($class)>

  Given a C<$class> this will return an array of class names in the proper C3 method resolution order.

  =item B<initialize>

  This B<must be called> to initialize the C3 method dispatch tables, this module B<will not work> if
  you do not do this. It is advised to do this as soon as possible B<after> loading any classes which
  use C3. Here is a quick code example:

    package Foo;
    use Class::C3;
    # ... Foo methods here

    package Bar;
    use Class::C3;
    use base 'Foo';
    # ... Bar methods here

    package main;

    Class::C3::initialize(); # now it is safe to use Foo and Bar

  This function used to be called automatically for you in the INIT phase of the perl compiler, but
  that lead to warnings if this module was required at runtime. After discussion with my user base
  (the L<DBIx::Class> folks), we decided that calling this in INIT was more of an annoyance than a
  convenience. I apologize to anyone this causes problems for (although I would be very surprised if I had
  any other users other than the L<DBIx::Class> folks). The simplest solution of course is to define
  your own INIT method which calls this function.

  NOTE:

  If C<initialize> detects that C<initialize> has already been executed, it will L</uninitialize> and
  clear the MRO cache first.

  =item B<uninitialize>

  Calling this function results in the removal of all cached methods, and the restoration of the old Perl 5
  style dispatch order (depth-first, left-to-right).

  =item B<reinitialize>

  This is an alias for L</initialize> above.

  =back

  =head1 METHOD REDISPATCHING

  It is always useful to be able to re-dispatch your method call to the "next most applicable method". This
  module provides a pseudo package along the lines of C<SUPER::> or C<NEXT::> which will re-dispatch the
  method along the C3 linearization. This is best shown with an example.

    # a classic diamond MI pattern ...
    #    <A>
    #   /   \
    # <B>   <C>
    #   \   /
    #    <D>

    package ClassA;
    use Class::C3;
    sub foo { 'ClassA::foo' }

    package ClassB;
    use base 'ClassA';
    use Class::C3;
    sub foo { 'ClassB::foo => ' . (shift)->next::method() }

    package ClassC;
    use base 'ClassA';
    use Class::C3;
    sub foo { 'ClassC::foo => ' . (shift)->next::method() }

    package ClassD;
    use base ('ClassB', 'ClassC');
    use Class::C3;
    sub foo { 'ClassD::foo => ' . (shift)->next::method() }

    print ClassD->foo; # prints out "ClassD::foo => ClassB::foo => ClassC::foo => ClassA::foo"

  A few things to note. First, we do not require you to add on the method name to the C<next::method>
  call (this is unlike C<NEXT::> and C<SUPER::> which do require that). This helps to enforce the rule
  that you cannot dispatch to a method of a different name (this is how C<NEXT::> behaves as well).

  The next thing to keep in mind is that you will need to pass all arguments to C<next::method>.  It can
  not automatically use the current C<@_>.

  If C<next::method> cannot find a next method to re-dispatch the call to, it will throw an exception.
  You can use C<next::can> to see if C<next::method> will succeed before you call it like so:

    $self->next::method(@_) if $self->next::can;

  Additionally, you can use C<maybe::next::method> as a shortcut to only call the next method if it exists.
  The previous example could be simply written as:

    $self->maybe::next::method(@_);

  There are some caveats about using C<next::method>, see below for those.

  =head1 CAVEATS

  This module used to be labeled as I<experimental>, however it has now been pretty heavily tested by
  the good folks over at L<DBIx::Class> and I am confident this module is perfectly usable for
  whatever your needs might be.

  But there are still caveats, so here goes ...

  =over 4

  =item Use of C<SUPER::>.

  The idea of C<SUPER::> under multiple inheritance is ambiguous, and generally not recommended anyway.
  However, its use in conjunction with this module is very much not recommended, and in fact very
  discouraged. The recommended approach is to instead use the supplied C<next::method> feature, see
  more details on its usage above.

  =item Changing C<@ISA>.

  It is the author's opinion that changing C<@ISA> at runtime is pure insanity anyway. However, people
  do it, so I must caveat. Any changes to the C<@ISA> will not be reflected in the MRO calculated by this
  module, and therefore probably won't even show up. If you do this, you will need to call C<reinitialize>
  in order to recalculate B<all> method dispatch tables. See the C<reinitialize> documentation and an example
  in F<t/20_reinitialize.t> for more information.

  =item Adding/deleting methods from class symbol tables.

  This module calculates the MRO for each requested class by interrogating the symbol tables of said classes.
  So any symbol table manipulation which takes place after our INIT phase is run will not be reflected in
  the calculated MRO. Just as with changing the C<@ISA>, you will need to call C<reinitialize> for any
  changes you make to take effect.

  =item Calling C<next::method> from methods defined outside the class

  There is an edge case when using C<next::method> from within a subroutine which was created in a different
  module than the one it is called from. It sounds complicated, but it really isn't. Here is an example which
  will not work correctly:

    *Foo::foo = sub { (shift)->next::method(@_) };

  The problem exists because the anonymous subroutine being assigned to the glob C<*Foo::foo> will show up
  in the call stack as being called C<__ANON__> and not C<foo> as you might expect. Since C<next::method>
  uses C<caller> to find the name of the method it was called in, it will fail in this case.

  But fear not, there is a simple solution. The module C<Sub::Name> will reach into the perl internals and
  assign a name to an anonymous subroutine for you. Simply do this:

    use Sub::Name 'subname';
    *Foo::foo = subname 'Foo::foo' => sub { (shift)->next::method(@_) };

  and things will Just Work. Of course this is not always possible to do, but to be honest, I just can't
  manage to find a workaround for it, so until someone gives me a working patch this will be a known
  limitation of this module.

  =back

  =head1 COMPATIBILITY

  If your software requires Perl 5.9.5 or higher, you do not need L<Class::C3>, you can simply C<use mro 'c3'>, and not worry about C<initialize()>, avoid some of the above caveats, and get the best possible performance.  See L<mro> for more details.

  If your software is meant to work on earlier Perls, use L<Class::C3> as documented here.  L<Class::C3> will detect Perl 5.9.5+ and take advantage of the core support when available.

  =head1 Class::C3::XS

  This module will load L<Class::C3::XS> if it's installed and you are running on a Perl version older than 5.9.5.  The optional module will be automatically installed for you if a C compiler is available, as it results in significant performance improvements (but unlike the 5.9.5+ core support, it still has all of the same caveats as L<Class::C3>).

  =head1 CODE COVERAGE

  L<Devel::Cover> was reporting 94.4% overall test coverage earlier in this module's life.  Currently, the test suite does things that break under coverage testing, but it is fair to assume the coverage is still close to that value.

  =head1 SEE ALSO

  =head2 The original Dylan paper

  =over 4

  =item L<https://web.archive.org/web/20000817033012id_/http://www.webcom.com/haahr/dylan/linearization-oopsla96.html>

  =back

  =head2 The prototype Perl 6 Object Model uses C3

  =over 4

  =item L<http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel/>

  =back

  =head2 Parrot now uses C3

  =over 4

  =item L<http://aspn.activestate.com/ASPN/Mail/Message/perl6-internals/2746631>

  =item L<http://use.perl.org/~autrijus/journal/25768>

  =back

  =head2 Python 2.3 MRO related links

  =over 4

  =item L<http://www.python.org/2.3/mro.html>

  =item L<http://www.python.org/2.2.2/descrintro.html#mro>

  =back

  =head2 C3 for TinyCLOS

  =over 4

  =item L<http://www.call-with-current-continuation.org/eggs/c3.html>

  =back

  =head1 ACKNOWLEGEMENTS

  =over 4

  =item Thanks to Matt S. Trout for using this module in his module L<DBIx::Class>
  and finding many bugs and providing fixes.

  =item Thanks to Justin Guenther for making C<next::method> more robust by handling
  calls inside C<eval> and anon-subs.

  =item Thanks to Robert Norris for adding support for C<next::can> and
  C<maybe::next::method>.

  =back

  =head1 AUTHOR

  Stevan Little, <stevan@iinteractive.com>

  Brandon L. Black, <blblack@gmail.com>

  =head1 COPYRIGHT AND LICENSE

  Copyright 2005, 2006 by Infinity Interactive, Inc.

  L<http://www.iinteractive.com>

  This library is free software; you can redistribute it and/or modify
  it under the same terms as Perl itself.

  =cut
CLASS_C3

$fatpacked{"Class/C3/next.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'CLASS_C3_NEXT';
  package  # hide me from PAUSE
      next;

  use strict;
  use warnings;
  no warnings 'redefine'; # for 00load.t w/ core support

  use Scalar::Util 'blessed';

  our $VERSION = '0.34';

  our %METHOD_CACHE;

  sub method {
      my $self     = $_[0];
      my $class    = blessed($self) || $self;
      my $indirect = caller() =~ /^(?:next|maybe::next)$/;
      my $level = $indirect ? 2 : 1;

      my ($method_caller, $label, @label);
      while ($method_caller = (caller($level++))[3]) {
        @label = (split '::', $method_caller);
        $label = pop @label;
        last unless
          $label eq '(eval)' ||
          $label eq '__ANON__';
      }

      my $method;

      my $caller   = join '::' => @label;

      $method = $METHOD_CACHE{"$class|$caller|$label"} ||= do {

          my @MRO = Class::C3::calculateMRO($class);

          my $current;
          while ($current = shift @MRO) {
              last if $caller eq $current;
          }

          no strict 'refs';
          my $found;
          foreach my $class (@MRO) {
              next if (defined $Class::C3::MRO{$class} &&
                       defined $Class::C3::MRO{$class}{methods}{$label});
              last if (defined ($found = *{$class . '::' . $label}{CODE}));
          }

          $found;
      };

      return $method if $indirect;

      die "No next::method '$label' found for $self" if !$method;

      goto &{$method};
  }

  sub can { method($_[0]) }

  package  # hide me from PAUSE
      maybe::next;

  use strict;
  use warnings;
  no warnings 'redefine'; # for 00load.t w/ core support

  our $VERSION = '0.34';

  sub method { (next::method($_[0]) || return)->(@_) }

  1;

  __END__

  =pod

  =head1 NAME

  Class::C3::next - Pure-perl next::method and friends

  =head1 DESCRIPTION

  This module is used internally by L<Class::C3> when
  necessary, and shouldn't be used (or required in
  distribution dependencies) directly.  It
  defines C<next::method>, C<next::can>, and
  C<maybe::next::method> in pure perl.

  =head1 AUTHOR

  Stevan Little, <stevan@iinteractive.com>

  Brandon L. Black, <blblack@gmail.com>

  =head1 COPYRIGHT AND LICENSE

  Copyright 2005, 2006 by Infinity Interactive, Inc.

  L<http://www.iinteractive.com>

  This library is free software; you can redistribute it and/or modify
  it under the same terms as Perl itself.

  =cut
CLASS_C3_NEXT

$fatpacked{"Devel/GlobalDestruction.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'DEVEL_GLOBALDESTRUCTION';
  package Devel::GlobalDestruction;

  use strict;
  use warnings;

  our $VERSION = '0.14';

  use Sub::Exporter::Progressive -setup => {
    exports => [ qw(in_global_destruction) ],
    groups  => { default => [ -all ] },
  };

  # we run 5.14+ - everything is in core
  #
  if (defined ${^GLOBAL_PHASE}) {
    eval 'sub in_global_destruction () { ${^GLOBAL_PHASE} eq q[DESTRUCT] }; 1'
      or die $@;
  }
  # try to load the xs version if it was compiled
  #
  elsif (eval {
    require Devel::GlobalDestruction::XS;
    no warnings 'once';
    *in_global_destruction = \&Devel::GlobalDestruction::XS::in_global_destruction;
    1;
  }) {
    # the eval already installed everything, nothing to do
  }
  else {
    # internally, PL_main_cv is set to Nullcv immediately before entering
    # global destruction and we can use B to detect that.  B::main_cv will
    # only ever be a B::CV or a B::SPECIAL that is a reference to 0
    require B;
    eval 'sub in_global_destruction () { ${B::main_cv()} == 0 }; 1'
      or die $@;
  }

  1;  # keep require happy


  __END__

  =head1 NAME

  Devel::GlobalDestruction - Provides function returning the equivalent of
  C<${^GLOBAL_PHASE} eq 'DESTRUCT'> for older perls.

  =head1 SYNOPSIS

      package Foo;
      use Devel::GlobalDestruction;

      use namespace::clean; # to avoid having an "in_global_destruction" method

      sub DESTROY {
          return if in_global_destruction;

          do_something_a_little_tricky();
      }

  =head1 DESCRIPTION

  Perl's global destruction is a little tricky to deal with WRT finalizers
  because it's not ordered and objects can sometimes disappear.

  Writing defensive destructors is hard and annoying, and usually if global
  destruction is happening you only need the destructors that free up non
  process local resources to actually execute.

  For these constructors you can avoid the mess by simply bailing out if global
  destruction is in effect.

  =head1 EXPORTS

  This module uses L<Sub::Exporter::Progressive> so the exports may be renamed,
  aliased, etc. if L<Sub::Exporter> is present.

  =over 4

  =item in_global_destruction

  Returns true if the interpreter is in global destruction. In perl 5.14+, this
  returns C<${^GLOBAL_PHASE} eq 'DESTRUCT'>, and on earlier perls, detects it using
  the value of C<PL_main_cv> or C<PL_dirty>.

  =back

  =head1 AUTHORS

  Yuval Kogman E<lt>nothingmuch@woobling.orgE<gt>

  Florian Ragwitz E<lt>rafl@debian.orgE<gt>

  Jesse Luehrs E<lt>doy@tozt.netE<gt>

  Peter Rabbitson E<lt>ribasushi@cpan.orgE<gt>

  Arthur Axel 'fREW' Schmidt E<lt>frioux@gmail.comE<gt>

  Elizabeth Mattijsen E<lt>liz@dijkmat.nlE<gt>

  Greham Knop E<lt>haarg@haarg.orgE<gt>

  =head1 COPYRIGHT

      Copyright (c) 2008 Yuval Kogman. All rights reserved
      This program is free software; you can redistribute
      it and/or modify it under the same terms as Perl itself.

  =cut
DEVEL_GLOBALDESTRUCTION

$fatpacked{"Devel/TypeTiny/Perl56Compat.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'DEVEL_TYPETINY_PERL56COMPAT';
  package Devel::TypeTiny::Perl56Compat;

  use 5.006;
  use strict;
  use warnings;

  our $AUTHORITY = 'cpan:TOBYINK';
  our $VERSION   = '1.000005';

  #### B doesn't provide perlstring() in 5.6. Monkey patch it.

  use B ();

  unless (exists &B::perlstring)
  {
  	my $d;
  	*B::perlstring = sub {
  		no warnings 'uninitialized';
  		require Data::Dumper;
  		$d ||= 'Data::Dumper'->new([])->Indent(0)->Purity(0)->Pad('')->Useqq(1)->Terse(1)->Freezer('')->Toaster('');
  		my $perlstring = $d->Values([''.shift])->Dump;
  		($perlstring =~ /^"/) ? $perlstring : qq["$perlstring"];
  	};
  }

  push @B::EXPORT_OK, 'perlstring';

  #### Done!

  5.6;

  __END__

  =pod

  =encoding utf-8

  =for stopwords pragmas

  =head1 NAME

  Devel::TypeTiny::Perl56Compat - shims to allow Type::Tiny to run on Perl 5.6.x

  =head1 STATUS

  This module is considered part of Type-Tiny's internals. It is not
  covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  This is not considered part of Type::Tiny's public API.

  Currently this module just has one job: it patches L<B> to export a
  C<perlstring> function, as this was only added in Perl 5.8.0.

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

DEVEL_TYPETINY_PERL56COMPAT

$fatpacked{"Devel/TypeTiny/Perl58Compat.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'DEVEL_TYPETINY_PERL58COMPAT';
  package Devel::TypeTiny::Perl58Compat;

  use 5.006;
  use strict;
  use warnings;

  our $AUTHORITY = 'cpan:TOBYINK';
  our $VERSION   = '1.000005';

  #### re doesn't provide is_regexp in Perl < 5.10

  eval 'require re';

  unless (exists &re::is_regexp)
  {
  	require B;
  	*re::is_regexp = sub {
  		eval { B::svref_2object($_[0])->MAGIC->TYPE eq 'r' };
  	};
  }

  #### Done!

  5.6;

  __END__

  =pod

  =encoding utf-8

  =for stopwords pragmas

  =head1 NAME

  Devel::TypeTiny::Perl58Compat - shims to allow Type::Tiny to run on Perl 5.8.x

  =head1 STATUS

  This module is considered part of Type-Tiny's internals. It is not
  covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  This is not considered part of Type::Tiny's public API.

  Currently this module just has one job: it patches L<re> to provide a
  C<is_regexp> function, as this was only added in Perl 5.9.5.

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

DEVEL_TYPETINY_PERL58COMPAT

$fatpacked{"Error/TypeTiny.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'ERROR_TYPETINY';
  package Error::TypeTiny;

  use 5.006001;
  use strict;
  use warnings;

  BEGIN {
  	$Error::TypeTiny::AUTHORITY = 'cpan:TOBYINK';
  	$Error::TypeTiny::VERSION   = '1.000005';
  }

  use overload
  	q[""]    => sub { $_[0]->to_string },
  	q[bool]  => sub { 1 },
  	fallback => 1,
  ;

  our %CarpInternal;
  $CarpInternal{$_}++ for qw(
  	Eval::TypeTiny
  	Eval::TypeTiny::Sandbox
  	Exporter::Tiny
  	Test::TypeTiny
  	Type::Coercion
  	Type::Coercion::Union
  	Error::TypeTiny
  	Type::Library
  	Type::Params
  	Type::Registry
  	Types::Standard
  	Types::Standard::_Stringable
  	Types::TypeTiny
  	Type::Tiny
  	Type::Tiny::Class
  	Type::Tiny::Duck
  	Type::Tiny::Enum
  	Type::Tiny::Intersection
  	Type::Tiny::Role
  	Type::Tiny::Union
  	Type::Utils
  );

  sub new
  {
  	my $class = shift;
  	my %params = (@_==1) ? %{$_[0]} : @_;
  	return bless \%params, $class;
  }

  sub throw
  {
  	my $class = shift;

  	my ($level, @caller, %ctxt) = 0;
  	while (
  		defined scalar caller($level) and $CarpInternal{scalar caller($level)}
  	) { $level++ };
  	if ( ((caller($level - 1))[1]||"") =~ /^parameter validation for '(.+?)'$/ )
  	{
  		my ($pkg, $func) = ($1 =~ m{^(.+)::(\w+)$});
  		$level++ if caller($level) eq ($pkg||"");
  	}
  	@ctxt{qw/ package file line /} = caller($level);

  	my $stack = undef;
  	if (our $StackTrace)
  	{
  		require Devel::StackTrace;
  		$stack = "Devel::StackTrace"->new(
  			ignore_package => [ keys %CarpInternal ],
  		);
  	}

  	die(
  		our $LastError = $class->new(
  			context     => \%ctxt,
  			stack_trace => $stack,
  			@_,
  		)
  	);
  }

  sub message     { $_[0]{message} ||= $_[0]->_build_message };
  sub context     { $_[0]{context} };
  sub stack_trace { $_[0]{stack_trace} };

  sub to_string
  {
  	my $e = shift;
  	my $c = $e->context;
  	my $m = $e->message;

  	$m =~ /\n\z/s ? $m :
  	$c            ? sprintf("%s at %s line %s.\n", $m, $c->{file}||'file?', $c->{line}||'NaN') :
  	sprintf("%s\n", $m);
  }

  sub _build_message
  {
  	return 'An exception has occurred';
  }

  sub croak
  {
  	my ($fmt, @args) = @_;
  	@_ = (
  		__PACKAGE__,
  		message => sprintf($fmt, @args),
  	);
  	goto \&throw;
  }

  1;

  __END__

  =pod

  =encoding utf-8

  =head1 NAME

  Error::TypeTiny - exceptions for Type::Tiny and friends

  =head1 SYNOPSIS

     use Data::Dumper;
     use Try::Tiny;
     use Types::Standard qw(Str);

     try {
        Str->assert_valid(undef);
     }
     catch {
        my $exception = shift;
        warn "Encountered Error: $exception";
        warn Dumper($exception->explain)
           if $exception->isa("Error::TypeTiny::Assertion");
     };

  =head1 STATUS

  This module is covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  When Type::Tiny and its related modules encounter an error, they throw an
  exception object. These exception objects inherit from Error::TypeTiny.

  =head2 Constructors

  =over

  =item C<< new(%attributes) >>

  Moose-style constructor function.

  =item C<< throw(%attributes) >>

  Constructs an exception and passes it to C<die>.

  Automatically populates C<context> and C<stack_trace> if appropriate.

  =back

  =head2 Attributes

  =over

  =item C<message>

  The error message.

  =item C<context>

  Hashref containing the package, file and line that generated the error.

  =item C<stack_trace>

  A more complete stack trace. This feature requires L<Devel::StackTrace>;
  use the C<< $StackTrace >> package variable to switch it on.

  =back

  =head2 Methods

  =over

  =item C<to_string>

  Returns the message, followed by the context if it is set.

  =back

  =head2 Functions

  =over

  =item C<< Error::TypeTiny::croak($format, @args) >>

  Functional-style shortcut to C<throw> method. Takes an C<sprintf>-style
  format string and optional arguments to construct the C<message>.

  =back

  =head2 Overloading

  =over

  =item *

  Stringification is overloaded to call C<to_string>.

  =back

  =head2 Package Variables

  =over

  =item C<< %Error::TypeTiny::CarpInternal >>

  Serves a similar purpose to C<< %Carp::CarpInternal >>.

  =item C<< $Error::TypeTiny::StackTrace >>

  Boolean to toggle stack trace generation.

  =item C<< $Error::TypeTiny::LastError >>

  A reference to the last exception object thrown.

  =back

  =head1 CAVEATS

  Although Error::TypeTiny objects are thrown for errors produced by
  Type::Tiny, that doesn't mean every time you use Type::Tiny you'll get
  Error::TypeTinys whenever you want.

  For example, if you use a Type::Tiny type constraint in a Moose attribute,
  Moose will not call the constraint's C<assert_valid> method (which throws
  an exception). Instead it will call C<check> and C<get_message> (which do
  not), and will C<confess> an error message of its own. (The C<< $LastError >>
  package variable may save your bacon.)

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Error::TypeTiny::Assertion>,
  L<Error::TypeTiny::WrongNumberOfParameters>.

  L<Try::Tiny>, L<Try::Tiny::ByClass>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

ERROR_TYPETINY

$fatpacked{"Error/TypeTiny/Assertion.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'ERROR_TYPETINY_ASSERTION';
  package Error::TypeTiny::Assertion;

  use 5.006001;
  use strict;
  use warnings;

  BEGIN {
  	if ($] < 5.008) { require Devel::TypeTiny::Perl56Compat };
  }

  BEGIN {
  	$Error::TypeTiny::Assertion::AUTHORITY = 'cpan:TOBYINK';
  	$Error::TypeTiny::Assertion::VERSION   = '1.000005';
  }

  require Error::TypeTiny;
  our @ISA = 'Error::TypeTiny';

  sub type               { $_[0]{type} };
  sub value              { $_[0]{value} };
  sub varname            { $_[0]{varname} ||= '$_' };
  sub attribute_step     { $_[0]{attribute_step} };
  sub attribute_name     { $_[0]{attribute_name} };

  sub has_type           { defined $_[0]{type} }; # sic
  sub has_attribute_step { exists $_[0]{attribute_step} };
  sub has_attribute_name { exists $_[0]{attribute_name} };

  sub new
  {
  	my $class = shift;
  	my $self  = $class->SUPER::new(@_);

  	if (ref $Method::Generate::Accessor::CurrentAttribute)
  	{
  		require B;
  		my %d = %{$Method::Generate::Accessor::CurrentAttribute};
  		$self->{attribute_name} = $d{name} if defined $d{name};
  		$self->{attribute_step} = $d{step} if defined $d{step};

  		if (defined $d{init_arg})
  		{
  			$self->{varname} = sprintf('$args->{%s}', B::perlstring($d{init_arg}));
  		}
  		elsif (defined $d{name})
  		{
  			$self->{varname} = sprintf('$self->{%s}', B::perlstring($d{name}));
  		}
  	}

  	return $self;
  }

  sub message
  {
  	my $e = shift;
  	$e->varname eq '$_'
  		? $e->SUPER::message
  		: sprintf('%s (in %s)', $e->SUPER::message, $e->varname);
  }

  sub _build_message
  {
  	my $e = shift;
  	$e->has_type
  		? sprintf('%s did not pass type constraint "%s"', Type::Tiny::_dd($e->value), $e->type)
  		: sprintf('%s did not pass type constraint', Type::Tiny::_dd($e->value))
  }

  *to_string = sub
  {
  	my $e = shift;
  	my $msg = $e->message;

  	my $c = $e->context;
  	$msg .= sprintf(" at %s line %s", $c->{file}||'file?', $c->{line}||'NaN') if $c;

  	my $explain = $e->explain;
  	return $msg unless @{ $explain || [] };

  	$msg .= "\n";
  	for my $line (@$explain) {
  		$msg .= "    $line\n";
  	}

  	return $msg;
  } if $] >= 5.008;

  sub explain
  {
  	my $e = shift;
  	return undef unless $e->has_type;
  	$e->type->validate_explain($e->value, $e->varname);
  }

  1;

  __END__

  =pod

  =encoding utf-8

  =head1 NAME

  Error::TypeTiny::Assertion - exception when a value fails a type constraint

  =head1 STATUS

  This module is covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  This exception is thrown when a value fails a type constraint assertion.

  This package inherits from L<Error::TypeTiny>; see that for most
  documentation. Major differences are listed below:

  =head2 Attributes

  =over

  =item C<type>

  The type constraint that was checked against. Weakened links are involved,
  so this may end up being C<undef>.

  =item C<value>

  The value that was tested.

  =item C<varname>

  The name of the variable that was checked, if known. Defaults to C<< '$_' >>.

  =item C<attribute_name>

  If this exception was thrown as the result of an isa check or a failed
  coercion for a Moo attribute, then this will tell you which attribute (if
  your Moo is new enough).

  (Hopefully one day this will support other OO frameworks.)

  =item C<attribute_step>

  If this exception was thrown as the result of an isa check or a failed
  coercion for a Moo attribute, then this will contain either C<< "isa check" >>
  or C<< "coercion" >> to indicate which went wrong (if your Moo is new enough).

  (Hopefully one day this will support other OO frameworks.)

  =back

  =head2 Methods

  =over

  =item C<has_type>, C<has_attribute_name>, C<has_attribute_step>

  Predicate methods.

  =item C<message>

  Overridden to add C<varname> to the message if defined.

  =item C<explain>

  Attempts to explain why the value did not pass the type constraint. Returns
  an arrayref of strings providing step-by-step reasoning; or returns undef if
  no explanation is possible.

  =back

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Error::TypeTiny>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

ERROR_TYPETINY_ASSERTION

$fatpacked{"Error/TypeTiny/Compilation.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'ERROR_TYPETINY_COMPILATION';
  package Error::TypeTiny::Compilation;

  use 5.006001;
  use strict;
  use warnings;

  BEGIN {
  	$Error::TypeTiny::Compilation::AUTHORITY = 'cpan:TOBYINK';
  	$Error::TypeTiny::Compilation::VERSION   = '1.000005';
  }

  require Error::TypeTiny;
  our @ISA = 'Error::TypeTiny';

  sub code        { $_[0]{code} };
  sub environment { $_[0]{environment} ||= {} };
  sub errstr      { $_[0]{errstr} };

  sub _build_message
  {
  	my $self = shift;
  	sprintf("Failed to compile source because: %s", $self->errstr);
  }

  1;

  __END__

  =pod

  =encoding utf-8

  =head1 NAME

  Error::TypeTiny::Compilation - exception for Eval::TypeTiny

  =head1 STATUS

  This module is covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  Thrown when compiling a closure fails. Common causes are problems with
  inlined type constraints, and syntax errors when coercions are given as
  strings of Perl code.

  This package inherits from L<Error::TypeTiny>; see that for most
  documentation. Major differences are listed below:

  =head2 Attributes

  =over

  =item C<code>

  The Perl source code being compiled.

  =item C<environment>

  Hashref of variables being closed over.

  =item C<errstr>

  Error message from Perl compiler.

  =back

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Error::TypeTiny>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

ERROR_TYPETINY_COMPILATION

$fatpacked{"Error/TypeTiny/WrongNumberOfParameters.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'ERROR_TYPETINY_WRONGNUMBEROFPARAMETERS';
  package Error::TypeTiny::WrongNumberOfParameters;

  use 5.006001;
  use strict;
  use warnings;

  BEGIN {
  	$Error::TypeTiny::WrongNumberOfParameters::AUTHORITY = 'cpan:TOBYINK';
  	$Error::TypeTiny::WrongNumberOfParameters::VERSION   = '1.000005';
  }

  require Error::TypeTiny;
  our @ISA = 'Error::TypeTiny';

  sub minimum    { $_[0]{minimum} };
  sub maximum    { $_[0]{maximum} };
  sub got        { $_[0]{got} };

  sub has_minimum { exists $_[0]{minimum} };
  sub has_maximum { exists $_[0]{maximum} };

  sub _build_message
  {
  	my $e = shift;
  	if ($e->has_minimum and $e->has_maximum and $e->minimum == $e->maximum)
  	{
  		return sprintf(
  			"Wrong number of parameters; got %d; expected %d",
  			$e->got,
  			$e->minimum,
  		);
  	}
  	elsif ($e->has_minimum and $e->has_maximum and $e->minimum < $e->maximum)
  	{
  		return sprintf(
  			"Wrong number of parameters; got %d; expected %d to %d",
  			$e->got,
  			$e->minimum,
  			$e->maximum,
  		);
  	}
  	elsif ($e->has_minimum)
  	{
  		return sprintf(
  			"Wrong number of parameters; got %d; expected at least %d",
  			$e->got,
  			$e->minimum,
  		);
  	}
  	else
  	{
  		return sprintf(
  			"Wrong number of parameters; got %d",
  			$e->got,
  		);
  	}
  }

  1;

  __END__

  =pod

  =encoding utf-8

  =head1 NAME

  Error::TypeTiny::WrongNumberOfParameters - exception for Type::Params

  =head1 STATUS

  This module is covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  Thrown when a Type::Params compiled check is called with the wrong number
  of parameters.

  This package inherits from L<Error::TypeTiny>; see that for most
  documentation. Major differences are listed below:

  =head2 Attributes

  =over

  =item C<minimum>

  The minimum expected number of parameters.

  =item C<maximum>

  The maximum expected number of parameters.

  =item C<got>

  The number of parameters actually passed to the compiled check.

  =back

  =head2 Methods

  =over

  =item C<has_minimum>, C<has_maximum>

  Predicate methods.

  =back

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Error::TypeTiny>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

ERROR_TYPETINY_WRONGNUMBEROFPARAMETERS

$fatpacked{"Eval/TypeTiny.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'EVAL_TYPETINY';
  package Eval::TypeTiny;

  use strict;

  BEGIN {
  	*HAS_LEXICAL_SUBS = ($] >= 5.018) ? sub(){!!1} : sub(){!!0};
  };

  {
  	my $hlv;
  	sub HAS_LEXICAL_VARS () {
  		$hlv = !! eval {
  			require Devel::LexAlias;
  			exists(&Devel::LexAlias::lexalias);
  		} unless defined $hlv;
  		$hlv;
  	}
  }

  sub _clean_eval
  {
  	local $@;
  	local $SIG{__DIE__};
  	my $r = eval $_[0];
  	my $e = $@;
  	return ($r, $e);
  }

  our $AUTHORITY = 'cpan:TOBYINK';
  our $VERSION   = '1.000005';
  our @EXPORT    = qw( eval_closure );
  our @EXPORT_OK = qw( HAS_LEXICAL_SUBS HAS_LEXICAL_VARS );

  sub import
  {
  	# do the shuffle!
  	no warnings "redefine";
  	our @ISA = qw( Exporter::Tiny );
  	require Exporter::Tiny;
  	my $next = \&Exporter::Tiny::import;
  	*import = $next;
  	my $class = shift;
  	my $opts  = { ref($_[0]) ? %{+shift} : () };
  	$opts->{into} ||= scalar(caller);
  	return $class->$next($opts, @_);
  }

  use warnings;

  sub eval_closure
  {
  	my (%args) = @_;
  	my $src    = ref $args{source} eq "ARRAY" ? join("\n", @{$args{source}}) : $args{source};

  	$args{alias}  = 0 unless defined $args{alias};
  	$args{line}   = 1 unless defined $args{line};
  	$args{description} =~ s/[^\w .:-\[\]\(\)\{\}\']//g if defined $args{description};
  	$src = qq{#line $args{line} "$args{description}"\n$src} if defined $args{description} && !($^P & 0x10);
  	$args{environment} ||= {};

  #	for my $k (sort keys %{$args{environment}})
  #	{
  #		next if $k =~ /^\$/ && ref($args{environment}{$k}) =~ /^(SCALAR|REF)$/;
  #		next if $k =~ /^\@/ && ref($args{environment}{$k}) eq q(ARRAY);
  #		next if $k =~ /^\%/ && ref($args{environment}{$k}) eq q(HASH);
  #
  #		require Error::TypeTiny;
  #		Error::TypeTiny::croak("Expected a variable name and ref; got %s => %s", $k, $args{environment}{$k});
  #	}

  	my $sandpkg   = 'Eval::TypeTiny::Sandbox';
  	my $alias     = exists($args{alias}) ? $args{alias} : 0;
  	my @keys      = sort keys %{$args{environment}};
  	my $i         = 0;
  	my $source    = join "\n" => (
  		"package $sandpkg;",
  		"sub {",
  		map(_make_lexical_assignment($_, $i++, $alias), @keys),
  		$src,
  		"}",
  	);

  	_manufacture_ties() if $alias && !HAS_LEXICAL_VARS;

  	my ($compiler, $e) = _clean_eval($source);
  	if ($e)
  	{
  		chomp $e;
  		require Error::TypeTiny::Compilation;
  		"Error::TypeTiny::Compilation"->throw(
  			code        => (ref $args{source} eq "ARRAY" ? join("\n", @{$args{source}}) : $args{source}),
  			errstr      => $e,
  			environment => $args{environment},
  		);
  	}

  	my $code = $compiler->(@{$args{environment}}{@keys});
  	undef($compiler);

  	if ($alias && HAS_LEXICAL_VARS) {
  		Devel::LexAlias::lexalias($code, $_, $args{environment}{$_}) for grep !/^\&/, @keys;
  	}

  	return $code;
  }

  my $tmp;
  sub _make_lexical_assignment
  {
  	my ($key, $index, $alias) = @_;
  	my $name = substr($key, 1);

  	if (HAS_LEXICAL_SUBS and $key =~ /^\&/) {
  		$tmp++;
  		my $tmpname = '$__LEXICAL_SUB__'.$tmp;
  		return
  			"no warnings 'experimental::lexical_subs';".
  			"use feature 'lexical_subs';".
  			"my $tmpname = \$_[$index];".
  			"my sub $name { goto $tmpname };";
  	}

  	if (!$alias) {
  		my $sigil = substr($key, 0, 1);
  		return "my $key = $sigil\{ \$_[$index] };";
  	}
  	elsif (HAS_LEXICAL_VARS) {
  		return "my $key;";
  	}
  	else {
  		my $tieclass = {
  			'@' => 'Eval::TypeTiny::_TieArray',
  			'%' => 'Eval::TypeTiny::_TieHash',
  			'$' => 'Eval::TypeTiny::_TieScalar',
  		}->{ substr($key, 0, 1) };

  		return sprintf(
  			'tie(my(%s), "%s", $_[%d]);',
  			$key,
  			$tieclass,
  			$index,
  		);
  	}
  }

  { my $tie; sub _manufacture_ties { $tie ||= eval <<'FALLBACK'; } }
  no warnings qw(void once uninitialized numeric);

  {
  	package #
  		Eval::TypeTiny::_TieArray;
  	require Tie::Array;
  	our @ISA = qw( Tie::StdArray );
  	sub TIEARRAY {
  		my $class = shift;
  		bless $_[0] => $class;
  	}
  	sub AUTOLOAD {
  		my $self = shift;
  		my ($method) = (our $AUTOLOAD =~ /(\w+)$/);
  		defined tied(@$self) and return tied(@$self)->$method(@_);
  		require Carp;
  		Carp::croak(qq[Can't call method "$method" on an undefined value]);
  	}
  	sub can {
  		my $self = shift;
  		my $code = $self->SUPER::can(@_)
  			|| (defined tied(@$self) and tied(@$self)->can(@_));
  		return $code;
  	}
  	use overload
  		q[bool]  => sub { !!   tied @{$_[0]} },
  		q[""]    => sub { '' . tied @{$_[0]} },
  		q[0+]    => sub { 0  + tied @{$_[0]} },
  		fallback => 1,
  	;
  }
  {
  	package #
  		Eval::TypeTiny::_TieHash;
  	require Tie::Hash;
  	our @ISA = qw( Tie::StdHash );
  	sub TIEHASH {
  		my $class = shift;
  		bless $_[0] => $class;
  	}
  	sub AUTOLOAD {
  		my $self = shift;
  		my ($method) = (our $AUTOLOAD =~ /(\w+)$/);
  		defined tied(%$self) and return tied(%$self)->$method(@_);
  		require Carp;
  		Carp::croak(qq[Can't call method "$method" on an undefined value]);
  	}
  	sub can {
  		my $self = shift;
  		my $code = $self->SUPER::can(@_)
  			|| (defined tied(%$self) and tied(%$self)->can(@_));
  		return $code;
  	}
  	use overload
  		q[bool]  => sub { !!   tied %{$_[0]} },
  		q[""]    => sub { '' . tied %{$_[0]} },
  		q[0+]    => sub { 0  + tied %{$_[0]} },
  		fallback => 1,
  	;
  }
  {
  	package #
  		Eval::TypeTiny::_TieScalar;
  	require Tie::Scalar;
  	our @ISA = qw( Tie::StdScalar );
  	sub TIESCALAR {
  		my $class = shift;
  		bless $_[0] => $class;
  	}
  	sub AUTOLOAD {
  		my $self = shift;
  		my ($method) = (our $AUTOLOAD =~ /(\w+)$/);
  		defined tied($$self) and return tied($$self)->$method(@_);
  		require Carp;
  		Carp::croak(qq[Can't call method "$method" on an undefined value]);
  	}
  	sub can {
  		my $self = shift;
  		my $code = $self->SUPER::can(@_)
  			|| (defined tied($$self) and tied($$self)->can(@_));
  		return $code;
  	}
  	use overload
  		q[bool]  => sub { !!   tied ${$_[0]} },
  		q[""]    => sub { '' . tied ${$_[0]} },
  		q[0+]    => sub { 0  + tied ${$_[0]} },
  		fallback => 1,
  	;
  }

  1;
  FALLBACK

  1;

  __END__

  =pod

  =encoding utf-8

  =for stopwords pragmas coderefs

  =head1 NAME

  Eval::TypeTiny - utility to evaluate a string of Perl code in a clean environment

  =head1 STATUS

  This module is considered part of Type-Tiny's internals. It is not
  covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  This module is used by Type::Tiny to compile coderefs from strings of
  Perl code, and hashrefs of variables to close over.

  =head2 Functions

  This module exports one function, which works much like the similarly named
  function from L<Eval::Closure>:

  =over

  =item C<< eval_closure(source => $source, environment => \%env, %opt) >>

  =back

  =head2 Constants

  The following constants may be exported, but are not by default.

  =over

  =item C<< HAS_LEXICAL_SUBS >>

  Boolean indicating whether Eval::TypeTiny has support for lexical subs.
  (This feature requires Perl 5.18.)

  =item C<< HAS_LEXICAL_VARS >>

  Don't worry; closing over lexical variables in the closures is always
  supported! However, if this constant is true, it means that
  L<Devel::LexAlias> is available, which makes them slightly faster than
  the fallback solution which uses tied variables. (This only makes any
  difference when the C<< alias => 1 >> option is used.)

  =back

  =head1 EVALUATION ENVIRONMENT

  The evaluation is performed in the presence of L<strict>, but the absence of
  L<warnings>. (This is different to L<Eval::Closure> which enables warnings for
  compiled closures.)

  The L<feature> pragma is not active in the evaluation environment, so the
  following will not work:

     use feature qw(say);
     use Eval::TypeTiny qw(eval_closure);

     my $say_all = eval_closure(
        source => 'sub { say for @_ }',
     );
     $say_all->("Hello", "World");

  The L<feature> pragma does not "carry over" into the stringy eval. It is
  of course possible to import pragmas into the evaluated string as part of the
  string itself:

     use Eval::TypeTiny qw(eval_closure);

     my $say_all = eval_closure(
        source => 'sub { use feature qw(say); say for @_ }',
     );
     $say_all->("Hello", "World");

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Eval::Closure>, L<Error::TypeTiny::Compilation>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

EVAL_TYPETINY

$fatpacked{"Exporter/Shiny.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'EXPORTER_SHINY';
  package Exporter::Shiny;

  use 5.006001;
  use strict;
  use warnings;

  use Exporter::Tiny ();

  our $AUTHORITY = 'cpan:TOBYINK';
  our $VERSION   = '0.042';

  sub import {
  	my $me     = shift;
  	my $caller = caller;

  	(my $nominal_file = $caller) =~ s(::)(/)g;
  	$INC{"$nominal_file\.pm"} ||= __FILE__;

  	if (@_ == 2 and $_[0] eq -setup)
  	{
  		my (undef, $opts) = @_;
  		@_ = @{ delete($opts->{exports}) || [] };

  		if (%$opts) {
  			Exporter::Tiny::_croak(
  				'Unsupported Sub::Exporter-style options: %s',
  				join(q[, ], sort keys %$opts),
  			);
  		}
  	}

  	ref($_) && Exporter::Tiny::_croak('Expected sub name, got ref %s', $_) for @_;

  	no strict qw(refs);
  	push @{"$caller\::ISA"}, 'Exporter::Tiny';
  	push @{"$caller\::EXPORT_OK"}, @_;
  }

  1;

  __END__

  =pod

  =encoding utf-8

  =head1 NAME

  Exporter::Shiny - shortcut for Exporter::Tiny

  =head1 SYNOPSIS

     use Exporter::Shiny qw( foo bar );

  Is a shortcut for:

     use base "Exporter::Tiny";
     push our(@EXPORT_OK), qw( foo bar );

  For compatibility with L<Sub::Exporter>, the following longer syntax is
  also supported:

     use Exporter::Shiny -setup => {
        exports => [qw( foo bar )],
     };

  =head1 DESCRIPTION

  This is a very small wrapper to simplify using L<Exporter::Tiny>.

  It does the following:

  =over

  =item * Marks your package as loaded in C<< %INC >>;

  =item * Pushes any function names in the import list onto your C<< @EXPORT_OK >>; and

  =item * Pushes C<< "Exporter::Tiny" >> onto your C<< @ISA >>.

  =back

  It doesn't set up C<< %EXPORT_TAGS >> or C<< @EXPORT >>, but there's
  nothing stopping you doing that yourself.

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Exporter-Tiny>.

  =head1 SEE ALSO

  L<Exporter::Tiny>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

EXPORTER_SHINY

$fatpacked{"Exporter/Tiny.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'EXPORTER_TINY';
  package Exporter::Tiny;

  use 5.006001;
  use strict;
  use warnings; no warnings qw(void once uninitialized numeric redefine);

  our $AUTHORITY = 'cpan:TOBYINK';
  our $VERSION   = '0.042';
  our @EXPORT_OK = qw< mkopt mkopt_hash _croak _carp >;

  sub _croak ($;@) { require Carp; my $fmt = shift; @_ = sprintf($fmt, @_); goto \&Carp::croak }
  sub _carp  ($;@) { require Carp; my $fmt = shift; @_ = sprintf($fmt, @_); goto \&Carp::carp }

  my $_process_optlist = sub
  {
  	my $class = shift;
  	my ($global_opts, $opts, $want, $not_want) = @_;

  	while (@$opts)
  	{
  		my $opt = shift @{$opts};
  		my ($name, $value) = @$opt;

  		($name =~ m{\A\!(/.+/[msixpodual]+)\z}) ?
  			do {
  				my @not = $class->_exporter_expand_regexp($1, $value, $global_opts);
  				++$not_want->{$_->[0]} for @not;
  			} :
  		($name =~ m{\A\!(.+)\z}) ?
  			(++$not_want->{$1}) :
  		($name =~ m{\A[:-](.+)\z}) ?
  			push(@$opts, $class->_exporter_expand_tag($1, $value, $global_opts)) :
  		($name =~ m{\A/.+/[msixpodual]+\z}) ?
  			push(@$opts, $class->_exporter_expand_regexp($name, $value, $global_opts)) :
  		# else ?
  			push(@$want, $opt);
  	}
  };

  sub import
  {
  	my $class = shift;
  	my $global_opts = +{ @_ && ref($_[0]) eq q(HASH) ? %{+shift} : () };
  	$global_opts->{into} = caller unless exists $global_opts->{into};

  	my @want;
  	my %not_want; $global_opts->{not} = \%not_want;
  	my @args = do { no strict qw(refs); @_ ? @_ : @{"$class\::EXPORT"} };
  	my $opts = mkopt(\@args);
  	$class->$_process_optlist($global_opts, $opts, \@want, \%not_want);

  	my $permitted = $class->_exporter_permitted_regexp($global_opts);
  	$class->_exporter_validate_opts($global_opts);

  	for my $wanted (@want)
  	{
  		next if $not_want{$wanted->[0]};

  		my %symbols = $class->_exporter_expand_sub(@$wanted, $global_opts, $permitted);
  		$class->_exporter_install_sub($_, $wanted->[1], $global_opts, $symbols{$_})
  			for keys %symbols;
  	}
  }

  sub unimport
  {
  	my $class = shift;
  	my $global_opts = +{ @_ && ref($_[0]) eq q(HASH) ? %{+shift} : () };
  	$global_opts->{into} = caller unless exists $global_opts->{into};
  	$global_opts->{is_unimport} = 1;

  	my @want;
  	my %not_want; $global_opts->{not} = \%not_want;
  	my @args = do { our %TRACKED; @_ ? @_ : keys(%{$TRACKED{$class}{$global_opts->{into}}}) };
  	my $opts = mkopt(\@args);
  	$class->$_process_optlist($global_opts, $opts, \@want, \%not_want);

  	my $permitted = $class->_exporter_permitted_regexp($global_opts);
  	$class->_exporter_validate_unimport_opts($global_opts);

  	my $expando = $class->can('_exporter_expand_sub');
  	$expando = undef if $expando == \&_exporter_expand_sub;

  	for my $wanted (@want)
  	{
  		next if $not_want{$wanted->[0]};

  		if ($wanted->[1])
  		{
  			_carp("Passing options to unimport '%s' makes no sense", $wanted->[0])
  				unless (ref($wanted->[1]) eq 'HASH' and not keys %{$wanted->[1]});
  		}

  		my %symbols = defined($expando)
  			? $class->$expando(@$wanted, $global_opts, $permitted)
  			: ($wanted->[0] => sub { "dummy" });
  		$class->_exporter_uninstall_sub($_, $wanted->[1], $global_opts)
  			for keys %symbols;
  	}
  }

  # Called once per import/unimport, passed the "global" import options.
  # Expected to validate the options and carp or croak if there are problems.
  # Can also take the opportunity to do other stuff if needed.
  #
  sub _exporter_validate_opts          { 1 }
  sub _exporter_validate_unimport_opts { 1 }

  # Called after expanding a tag or regexp to merge the tag's options with
  # any sub-specific options.
  #
  sub _exporter_merge_opts
  {
  	my $class = shift;
  	my ($tag_opts, $global_opts, @stuff) = @_;

  	$tag_opts = {} unless ref($tag_opts) eq q(HASH);
  	_croak('Cannot provide an -as option for tags')
  		if exists $tag_opts->{-as};

  	my $optlist = mkopt(\@stuff);
  	for my $export (@$optlist)
  	{
  		next if defined($export->[1]) && ref($export->[1]) ne q(HASH);

  		my %sub_opts = ( %{ $export->[1] or {} }, %$tag_opts );
  		$sub_opts{-prefix} = sprintf('%s%s', $tag_opts->{-prefix}, $export->[1]{-prefix})
  			if exists($export->[1]{-prefix}) && exists($tag_opts->{-prefix});
  		$sub_opts{-suffix} = sprintf('%s%s', $export->[1]{-suffix}, $tag_opts->{-suffix})
  			if exists($export->[1]{-suffix}) && exists($tag_opts->{-suffix});
  		$export->[1] = \%sub_opts;
  	}
  	return @$optlist;
  }

  # Given a tag name, looks it up in %EXPORT_TAGS and returns the list of
  # associated functions. The default implementation magically handles tags
  # "all" and "default". The default implementation interprets any undefined
  # tags as being global options.
  #
  sub _exporter_expand_tag
  {
  	no strict qw(refs);

  	my $class = shift;
  	my ($name, $value, $globals) = @_;
  	my $tags  = \%{"$class\::EXPORT_TAGS"};

  	return $class->_exporter_merge_opts($value, $globals, $tags->{$name}->($class, @_))
  		if ref($tags->{$name}) eq q(CODE);

  	return $class->_exporter_merge_opts($value, $globals, @{$tags->{$name}})
  		if exists $tags->{$name};

  	return $class->_exporter_merge_opts($value, $globals, @{"$class\::EXPORT"}, @{"$class\::EXPORT_OK"})
  		if $name eq 'all';

  	return $class->_exporter_merge_opts($value, $globals, @{"$class\::EXPORT"})
  		if $name eq 'default';

  	$globals->{$name} = $value || 1;
  	return;
  }

  # Given a regexp-like string, looks it up in @EXPORT_OK and returns the
  # list of matching functions.
  #
  sub _exporter_expand_regexp
  {
  	no strict qw(refs);
  	our %TRACKED;

  	my $class = shift;
  	my ($name, $value, $globals) = @_;
  	my $compiled = eval("qr$name");

  	my @possible = $globals->{is_unimport}
  		? keys( %{$TRACKED{$class}{$globals->{into}}} )
  		: @{"$class\::EXPORT_OK"};

  	$class->_exporter_merge_opts($value, $globals, grep /$compiled/, @possible);
  }

  # Helper for _exporter_expand_sub. Returns a regexp matching all subs in
  # the exporter package which are available for export.
  #
  sub _exporter_permitted_regexp
  {
  	no strict qw(refs);
  	my $class = shift;
  	my $re = join "|", map quotemeta, sort {
  		length($b) <=> length($a) or $a cmp $b
  	} @{"$class\::EXPORT"}, @{"$class\::EXPORT_OK"};
  	qr{^(?:$re)$}ms;
  }

  # Given a sub name, returns a hash of subs to install (usually just one sub).
  # Keys are sub names, values are coderefs.
  #
  sub _exporter_expand_sub
  {
  	my $class = shift;
  	my ($name, $value, $globals, $permitted) = @_;
  	$permitted ||= $class->_exporter_permitted_regexp($globals);

  	no strict qw(refs);

  	if ($name =~ $permitted)
  	{
  		my $generator = $class->can("_generate_$name");
  		return $name => $class->$generator($name, $value, $globals) if $generator;

  		my $sub = $class->can($name);
  		return $name => $sub if $sub;
  	}

  	$class->_exporter_fail(@_);
  }

  # Called by _exporter_expand_sub if it is unable to generate a key-value
  # pair for a sub.
  #
  sub _exporter_fail
  {
  	my $class = shift;
  	my ($name, $value, $globals) = @_;
  	return if $globals->{is_unimport};
  	_croak("Could not find sub '%s' exported by %s", $name, $class);
  }

  # Actually performs the installation of the sub into the target package. This
  # also handles renaming the sub.
  #
  sub _exporter_install_sub
  {
  	my $class = shift;
  	my ($name, $value, $globals, $sym) = @_;

  	my $into      = $globals->{into};
  	my $installer = $globals->{installer} || $globals->{exporter};

  	$name = $value->{-as} || $name;
  	unless (ref($name) eq q(SCALAR))
  	{
  		my ($prefix) = grep defined, $value->{-prefix}, $globals->{prefix}, q();
  		my ($suffix) = grep defined, $value->{-suffix}, $globals->{suffix}, q();
  		$name = "$prefix$name$suffix";
  	}

  	return ($$name = $sym)                       if ref($name) eq q(SCALAR);
  	return ($into->{$name} = $sym)               if ref($into) eq q(HASH);

  	no strict qw(refs);

  	if (exists &{"$into\::$name"} and \&{"$into\::$name"} != $sym)
  	{
  		my ($level) = grep defined, $value->{-replace}, $globals->{replace}, q(0);
  		my $action = {
  			carp     => \&_carp,
  			0        => \&_carp,
  			''       => \&_carp,
  			warn     => \&_carp,
  			nonfatal => \&_carp,
  			croak    => \&_croak,
  			fatal    => \&_croak,
  			die      => \&_croak,
  		}->{$level} || sub {};

  		$action->(
  			$action == \&_croak
  				? "Refusing to overwrite existing sub '%s::%s' with sub '%s' exported by %s"
  				: "Overwriting existing sub '%s::%s' with sub '%s' exported by %s",
  			$into,
  			$name,
  			$_[0],
  			$class,
  		);
  	}

  	our %TRACKED;
  	$TRACKED{$class}{$into}{$name} = $sym;

  	no warnings qw(prototype);
  	$installer
  		? $installer->($globals, [$name, $sym])
  		: (*{"$into\::$name"} = $sym);
  }

  sub _exporter_uninstall_sub
  {
  	our %TRACKED;
  	my $class = shift;
  	my ($name, $value, $globals, $sym) = @_;
  	my $into = $globals->{into};
  	ref $into and return;

  	no strict qw(refs);

  	# Cowardly refuse to uninstall a sub that differs from the one
  	# we installed!
  	my $our_coderef = $TRACKED{$class}{$into}{$name};
  	my $cur_coderef = exists(&{"$into\::$name"}) ? \&{"$into\::$name"} : -1;
  	return unless $our_coderef == $cur_coderef;

  	my $stash     = \%{"$into\::"};
  	my $old       = delete $stash->{$name};
  	my $full_name = join('::', $into, $name);
  	foreach my $type (qw(SCALAR HASH ARRAY IO)) # everything but the CODE
  	{
  		next unless defined(*{$old}{$type});
  		*$full_name = *{$old}{$type};
  	}

  	delete $TRACKED{$class}{$into}{$name};
  }

  sub mkopt
  {
  	my $in = shift or return [];
  	my @out;

  	$in = [map(($_ => ref($in->{$_}) ? $in->{$_} : ()), sort keys %$in)]
  		if ref($in) eq q(HASH);

  	for (my $i = 0; $i < @$in; $i++)
  	{
  		my $k = $in->[$i];
  		my $v;

  		($i == $#$in)         ? ($v = undef) :
  		!defined($in->[$i+1]) ? (++$i, ($v = undef)) :
  		!ref($in->[$i+1])     ? ($v = undef) :
  		($v = $in->[++$i]);

  		push @out, [ $k => $v ];
  	}

  	\@out;
  }

  sub mkopt_hash
  {
  	my $in  = shift or return;
  	my %out = map +($_->[0] => $_->[1]), @{ mkopt($in) };
  	\%out;
  }

  1;

  __END__

  =pod

  =encoding utf-8

  =for stopwords frobnicate greps regexps

  =head1 NAME

  Exporter::Tiny - an exporter with the features of Sub::Exporter but only core dependencies

  =head1 SYNOPSIS

     package MyUtils;
     use base "Exporter::Tiny";
     our @EXPORT = qw(frobnicate);
     sub frobnicate { my $n = shift; ... }
     1;

     package MyScript;
     use MyUtils "frobnicate" => { -as => "frob" };
     print frob(42);
     exit;

  =head1 DESCRIPTION

  Exporter::Tiny supports many of Sub::Exporter's external-facing features
  including renaming imported functions with the C<< -as >>, C<< -prefix >> and
  C<< -suffix >> options; explicit destinations with the C<< into >> option;
  and alternative installers with the C<< installler >> option. But it's written
  in only about 40% as many lines of code and with zero non-core dependencies.

  Its internal-facing interface is closer to Exporter.pm, with configuration
  done through the C<< @EXPORT >>, C<< @EXPORT_OK >> and C<< %EXPORT_TAGS >>
  package variables.

  Exporter::Tiny performs most of its internal duties (including resolution
  of tag names to sub names, resolution of sub names to coderefs, and
  installation of coderefs into the target package) as method calls, which
  means they can be overridden to provide interesting behaviour.

  =head2 Utility Functions

  These are really for internal use, but can be exported if you need them.

  =over

  =item C<< mkopt(\@array) >>

  Similar to C<mkopt> from L<Data::OptList>. It doesn't support all the
  fancy options that Data::OptList does (C<moniker>, C<require_unique>,
  C<must_be> and C<name_test>) but runs about 50% faster.

  =item C<< mkopt_hash(\@array) >>

  Similar to C<mkopt_hash> from L<Data::OptList>. See also C<mkopt>.

  =back

  =head1 TIPS AND TRICKS IMPORTING FROM EXPORTER::TINY

  For the purposes of this discussion we'll assume we have a module called
  C<< MyUtils >> which exports one function, C<< frobnicate >>. C<< MyUtils >>
  inherits from Exporter::Tiny.

  Many of these tricks may seem familiar from L<Sub::Exporter>. That is
  intentional. Exporter::Tiny doesn't attempt to provide every feature of
  Sub::Exporter, but where it does it usually uses a fairly similar API.

  =head2 Basic importing

     # import "frobnicate" function
     use MyUtils "frobnicate";

     # import all functions that MyUtils offers
     use MyUtils -all;

  =head2 Renaming imported functions

     # call it "frob"
     use MyUtils "frobnicate" => { -as => "frob" };

     # call it "my_frobnicate"
     use MyUtils "frobnicate" => { -prefix => "my_" };

     # can set a prefix for *all* functions imported from MyUtils
     # by placing the options hashref *first*.
     use MyUtils { prefix => "my_" }, "frobnicate";
     # (note the lack of hyphen before `prefix`.)

     # call it "frobnicate_util"
     use MyUtils "frobnicate" => { -suffix => "_util" };
     use MyUtils { suffix => "_util" }, "frobnicate";

     # import it twice with two different names
     use MyUtils
        "frobnicate" => { -as => "frob" },
        "frobnicate" => { -as => "frbnct" };

  =head2 Lexical subs

     {
        use Sub::Exporter::Lexical lexical_installer => { -as => "lex" };
        use MyUtils { installer => lex }, "frobnicate";

        frobnicate(...);  # ok
     }

     frobnicate(...);  # not ok

  =head2 Import functions into another package

     use MyUtils { into => "OtherPkg" }, "frobnicate";

     OtherPkg::frobincate(...);

  =head2 Import functions into a scalar

     my $func;
     use MyUtils "frobnicate" => { -as => \$func };

     $func->(...);

  =head2 Import functions into a hash

  OK, Sub::Exporter doesn't do this...

     my %funcs;
     use MyUtils { into => \%funcs }, "frobnicate";

     $funcs{frobnicate}->(...);

  =head2 DO NOT WANT!

  This imports everything except "frobnicate":

     use MyUtils qw( -all !frobnicate );

  Negated imports always "win", so the following will not import
  "frobnicate", no matter how many times you repeat it...

     use MyUtils qw( !frobnicate frobnicate frobnicate frobnicate );

  =head2 Importing by regexp

  Here's how you could import all functions beginning with an "f":

     use MyUtils qw( /^F/i );

  Or import everything except functions beginning with a "z":

     use MyUtils qw( -all !/^Z/i );

  Note that regexps are always supplied as I<strings> starting with
  C<< "/" >>, and not as quoted regexp references (C<< qr/.../ >>).

  =head2 Unimporting

  You can unimport the functions that MyUtils added to your namespace:

     no MyUtils;

  Or just specific ones:

     no MyUtils qw(frobnicate);

  If you renamed a function when you imported it, you should unimport by
  the new name:

     use MyUtils frobnicate => { -as => "frob" };
     ...;
     no MyUtils "frob";

  Unimporting using tags and regexps should mostly do what you want.

  =head1 TIPS AND TRICKS EXPORTING USING EXPORTER::TINY

  Simple configuration works the same as L<Exporter>; inherit from this module,
  and use the C<< @EXPORT >>, C<< @EXPORT_OK >> and C<< %EXPORT_TAGS >>
  package variables to list subs to export.

  =head2 Generators

  Exporter::Tiny has always allowed exported subs to be generated (like
  L<Sub::Exporter>), but until version 0.025 did not have an especially nice
  API for it.

  Now, it's easy. If you want to generate a sub C<foo> to export, list it in
  C<< @EXPORT >> or C<< @EXPORT_OK >> as usual, and then simply give your
  exporter module a class method called C<< _generate_foo >>.

     push @EXPORT_OK, 'foo';

     sub _generate_foo {
        my $class = shift;
        my ($name, $args, $globals) = @_;

        return sub {
           ...;
        }
     }

  You can also generate tags:

     my %constants;
     BEGIN {
        %constants = (FOO => 1, BAR => 2);
     }
     use constant \%constants;

     $EXPORT_TAGS{constants} = sub {
        my $class = shift;
        my ($name, $args, $globals) = @_;

        return keys(%constants);
     };

  =head2 Overriding Internals

  An important difference between L<Exporter> and Exporter::Tiny is that
  the latter calls all its internal functions as I<< class methods >>. This
  means that your subclass can I<< override them >> to alter their behaviour.

  The following methods are available to be overridden. Despite being named
  with a leading underscore, they are considered public methods. (The underscore
  is there to avoid accidentally colliding with any of your own function names.)

  =over

  =item C<< _exporter_validate_opts($globals) >>

  This method is called once each time C<import> is called. It is passed a
  reference to the global options hash. (That is, the optional leading hashref
  in the C<use> statement, where the C<into> and C<installer> options can be
  provided.)

  You may use this method to munge the global options, or validate them,
  throwing an exception or printing a warning.

  The default implementation does nothing interesting.

  =item C<< _exporter_validate_unimport_opts($globals) >>

  Like C<_exporter_validate_opts>, but called for C<unimport>.

  =item C<< _exporter_merge_opts($tag_opts, $globals, @exports) >>

  Called to merge options which have been provided for a tag into the
  options provided for the exports that the tag expanded to.

  =item C<< _exporter_expand_tag($name, $args, $globals) >>

  This method is called to expand an import tag (e.g. C<< ":constants" >>).
  It is passed the tag name (minus the leading ":"), an optional hashref
  of options (like C<< { -prefix => "foo_" } >>), and the global options
  hashref.

  It is expected to return a list of ($name, $args) arrayref pairs. These
  names can be sub names to export, or further tag names (which must have
  their ":"). If returning tag names, be careful to avoid creating a tag
  expansion loop!

  The default implementation uses C<< %EXPORT_TAGS >> to expand tags, and
  provides fallbacks for the C<< :default >> and C<< :all >> tags.

  =item C<< _exporter_expand_regexp($regexp, $args, $globals) >>

  Like C<_exporter_expand_regexp>, but given a regexp-like string instead
  of a tag name.

  The default implementation greps through C<< @EXPORT_OK >> for imports,
  and the list of already-imported functions for exports.

  =item C<< _exporter_expand_sub($name, $args, $globals) >>

  This method is called to translate a sub name to a hash of name => coderef
  pairs for exporting to the caller. In general, this would just be a hash with
  one key and one value, but, for example, L<Type::Library> overrides this
  method so that C<< "+Foo" >> gets expanded to:

     (
        Foo         => sub { $type },
        is_Foo      => sub { $type->check(@_) },
        to_Foo      => sub { $type->assert_coerce(@_) },
        assert_Foo  => sub { $type->assert_return(@_) },
     )

  The default implementation checks that the name is allowed to be exported
  (using the C<_exporter_permitted_regexp> method), gets the coderef using
  the generator if there is one (or by calling C<< can >> on your exporter
  otherwise) and calls C<_exporter_fail> if it's unable to generate or
  retrieve a coderef.

  =item C<< _exporter_permitted_regexp($globals) >>

  This method is called to retrieve a regexp for validating the names of
  exportable subs. If a sub doesn't match the regexp, then the default
  implementation of C<_exporter_expand_sub> will refuse to export it. (Of
  course, you may override the default C<_exporter_expand_sub>.)

  The default implementation of this method assembles the regexp from
  C<< @EXPORT >> and C<< @EXPORT_OK >>.

  =item C<< _exporter_fail($name, $args, $globals) >>

  Called by C<_exporter_expand_sub> if it can't find a coderef to export.

  The default implementation just throws an exception. But you could emit
  a warning instead, or just ignore the failed export.

  If you don't throw an exception then you should be aware that this
  method is called in list context, and any list it returns will be treated
  as an C<_exporter_expand_sub>-style hash of names and coderefs for
  export.

  =item C<< _exporter_install_sub($name, $args, $globals, $coderef) >>

  This method actually installs the exported sub into its new destination.
  Its return value is ignored.

  The default implementation handles sub renaming (i.e. the C<< -as >>,
  C<< -prefix >> and C<< -suffix >> functions. This method does a lot of
  stuff; if you need to override it, it's probably a good idea to just
  pre-process the arguments and then call the super method rather than
  trying to handle all of it yourself.

  =item C<< _exporter_uninstall_sub($name, $args, $globals) >>

  The opposite of C<_exporter_install_sub>.

  =back

  =head1 DIAGNOSTICS

  =over

  =item B<< Overwriting existing sub '%s::%s' with sub '%s' exported by %s >>

  A warning issued if Exporter::Tiny is asked to export a symbol which
  will result in an existing sub being overwritten. This warning can be
  suppressed using either of the following:

     use MyUtils { replace => 1 }, "frobnicate";
     use MyUtils "frobnicate" => { -replace => 1 };

  Or can be upgraded to a fatal error:

     use MyUtils { replace => "die" }, "frobnicate";
     use MyUtils "frobnicate" => { -replace => "die" };

  =item B<< Refusing to overwrite existing sub '%s::%s' with sub '%s' exported by %s >>

  The fatal version of the above warning.

  =item B<< Could not find sub '%s' exported by %s >>

  You requested to import a sub which the package does not provide.

  =item B<< Cannot provide an -as option for tags >>

  Because a tag may provide more than one function, it does not make sense
  to request a single name for it. Instead use C<< -prefix >> or C<< -suffix >>.

  =item B<< Passing options to unimport '%s' makes no sense >>

  When you import a sub, it occasionally makes sense to pass some options
  for it. However, when unimporting, options do nothing, so this warning
  is issued.

  =back

  =head1 HISTORY

  L<Type::Library> had a bunch of custom exporting code which poked coderefs
  into its caller's stash. It needed this to be something more powerful than
  most exporters so that it could switch between exporting Moose, Mouse and
  Moo-compatible objects on request. L<Sub::Exporter> would have been capable,
  but had too many dependencies for the Type::Tiny project.

  Meanwhile L<Type::Utils>, L<Types::TypeTiny> and L<Test::TypeTiny> each
  used the venerable L<Exporter.pm|Exporter>. However, this meant they were
  unable to use the features like L<Sub::Exporter>-style function renaming
  which I'd built into Type::Library:

     ## import "Str" but rename it to "String".
     use Types::Standard "Str" => { -as => "String" };

  And so I decided to factor out code that could be shared by all Type-Tiny's
  exporters into a single place: Exporter::TypeTiny.

  As of version 0.026, Exporter::TypeTiny was also made available as
  L<Exporter::Tiny>, distributed independently on CPAN. CHOCOLATEBOY had
  convinced me that it was mature enough to live a life of its own.

  As of version 0.030, Type-Tiny depends on Exporter::Tiny and
  Exporter::TypeTiny is being phased out.

  =head1 OBLIGATORY EXPORTER COMPARISON

  Exporting is unlikely to be your application's performance bottleneck, but
  nonetheless here are some comparisons.

  B<< Comparative sizes according to L<Devel::SizeMe>: >>

     Exporter                     217.1Kb
     Sub::Exporter::Progressive   263.2Kb
     Exporter::Tiny               267.7Kb
     Exporter + Exporter::Heavy   281.5Kb
     Exporter::Renaming           406.2Kb
     Sub::Exporter                701.0Kb

  B<< Performance exporting a single sub: >>

                Rate     SubExp    ExpTiny SubExpProg      ExpPM
  SubExp      2489/s         --       -56%       -85%       -88%
  ExpTiny     5635/s       126%         --       -67%       -72%
  SubExpProg 16905/s       579%       200%         --       -16%
  ExpPM      20097/s       707%       257%        19%         --

  (Exporter::Renaming globally changes the behaviour of Exporter.pm, so could
  not be included in the same benchmarks.)

  B<< (Non-Core) Dependencies: >>

     Exporter                    -1
     Exporter::Renaming           0
     Exporter::Tiny               0
     Sub::Exporter::Progressive   0
     Sub::Exporter                3

  B<< Features: >>

                                        ExpPM   ExpTiny SubExp  SubExpProg
   Can export code symbols............. Yes     Yes     Yes     Yes
   Can export non-code symbols......... Yes
   Groups/tags......................... Yes     Yes     Yes     Yes
   Export by regexp.................... Yes     Yes
   Bang prefix......................... Yes     Yes
   Allows renaming of subs.............         Yes     Yes     Maybe
   Install code into scalar refs.......         Yes     Yes     Maybe
   Can be passed an "into" parameter...         Yes     Yes     Maybe
   Can be passed an "installer" sub....         Yes     Yes     Maybe
   Config avoids package variables.....                 Yes
   Supports generators.................         Yes     Yes
   Sane API for generators.............         Yes     Yes
   Unimport............................         Yes

  (Certain Sub::Exporter::Progressive features are only available if
  Sub::Exporter is installed.)

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Exporter-Tiny>.

  =head1 SUPPORT

  B<< IRC: >> support is available through in the I<< #moops >> channel
  on L<irc.perl.org|http://www.irc.perl.org/channels.html>.

  =head1 SEE ALSO

  L<Exporter::Shiny>,
  L<Sub::Exporter>,
  L<Exporter>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

EXPORTER_TINY

$fatpacked{"MRO/Compat.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MRO_COMPAT';
  package MRO::Compat;
  use strict;
  use warnings;
  require 5.006_000;

  # Keep this < 1.00, so people can tell the fake
  #  mro.pm from the real one
  our $VERSION = '0.13';

  BEGIN {
      # Alias our private functions over to
      # the mro:: namespace and load
      # Class::C3 if Perl < 5.9.5
      if($] < 5.009_005) {
          $mro::VERSION # to fool Module::Install when generating META.yml
              = $VERSION;
          $INC{'mro.pm'} = __FILE__;
          *mro::import            = \&__import;
          *mro::get_linear_isa    = \&__get_linear_isa;
          *mro::set_mro           = \&__set_mro;
          *mro::get_mro           = \&__get_mro;
          *mro::get_isarev        = \&__get_isarev;
          *mro::is_universal      = \&__is_universal;
          *mro::method_changed_in = \&__method_changed_in;
          *mro::invalidate_all_method_caches
                                  = \&__invalidate_all_method_caches;
          require Class::C3;
          if($Class::C3::XS::VERSION && $Class::C3::XS::VERSION > 0.03) {
              *mro::get_pkg_gen   = \&__get_pkg_gen_c3xs;
          }
          else {
              *mro::get_pkg_gen   = \&__get_pkg_gen_pp;
          }
      }

      # Load mro.pm and provide no-op Class::C3::.*initialize() funcs for 5.9.5+
      else {
          require mro;
          no warnings 'redefine';
          *Class::C3::initialize = sub { 1 };
          *Class::C3::reinitialize = sub { 1 };
          *Class::C3::uninitialize = sub { 1 };
      }
  }

  =head1 NAME

  MRO::Compat - mro::* interface compatibility for Perls < 5.9.5

  =head1 SYNOPSIS

     package PPP;      use base qw/Exporter/;
     package X;        use base qw/PPP/;
     package Y;        use base qw/PPP/;
     package Z;        use base qw/PPP/;

     package FooClass; use base qw/X Y Z/;

     package main;
     use MRO::Compat;
     my $linear = mro::get_linear_isa('FooClass');
     print join(q{, }, @$linear);

     # Prints: FooClass, X, PPP, Exporter, Y, Z

  =head1 DESCRIPTION

  The "mro" namespace provides several utilities for dealing
  with method resolution order and method caching in general
  in Perl 5.9.5 and higher.

  This module provides those interfaces for
  earlier versions of Perl (back to 5.6.0 anyways).

  It is a harmless no-op to use this module on 5.9.5+.  That
  is to say, code which properly uses L<MRO::Compat> will work
  unmodified on both older Perls and 5.9.5+.

  If you're writing a piece of software that would like to use
  the parts of 5.9.5+'s mro:: interfaces that are supported
  here, and you want compatibility with older Perls, this
  is the module for you.

  Some parts of this code will work better and/or faster with
  L<Class::C3::XS> installed (which is an optional prereq
  of L<Class::C3>, which is in turn a prereq of this
  package), but it's not a requirement.

  This module never exports any functions.  All calls must
  be fully qualified with the C<mro::> prefix.

  The interface documentation here serves only as a quick
  reference of what the function basically does, and what
  differences between L<MRO::Compat> and 5.9.5+ one should
  look out for.  The main docs in 5.9.5's L<mro> are the real
  interface docs, and contain a lot of other useful information.

  =head1 Functions

  =head2 mro::get_linear_isa($classname[, $type])

  Returns an arrayref which is the linearized "ISA" of the given class.
  Uses whichever MRO is currently in effect for that class by default,
  or the given MRO (either C<c3> or C<dfs> if specified as C<$type>).

  The linearized ISA of a class is a single ordered list of all of the
  classes that would be visited in the process of resolving a method
  on the given class, starting with itself.  It does not include any
  duplicate entries.

  Note that C<UNIVERSAL> (and any members of C<UNIVERSAL>'s MRO) are not
  part of the MRO of a class, even though all classes implicitly inherit
  methods from C<UNIVERSAL> and its parents.

  =cut

  sub __get_linear_isa_dfs {
      no strict 'refs';

      my $classname = shift;

      my @lin = ($classname);
      my %stored;
      foreach my $parent (@{"$classname\::ISA"}) {
          my $plin = __get_linear_isa_dfs($parent);
          foreach (@$plin) {
              next if exists $stored{$_};
              push(@lin, $_);
              $stored{$_} = 1;
          }
      }
      return \@lin;
  }

  sub __get_linear_isa {
      my ($classname, $type) = @_;
      die "mro::get_mro requires a classname" if !defined $classname;

      $type ||= __get_mro($classname);
      if($type eq 'dfs') {
          return __get_linear_isa_dfs($classname);
      }
      elsif($type eq 'c3') {
          return [Class::C3::calculateMRO($classname)];
      }
      die "type argument must be 'dfs' or 'c3'";
  }

  =head2 mro::import

  This allows the C<use mro 'dfs'> and
  C<use mro 'c3'> syntaxes, providing you
  L<use MRO::Compat> first.  Please see the
  L</USING C3> section for additional details.

  =cut

  sub __import {
      if($_[1]) {
          goto &Class::C3::import if $_[1] eq 'c3';
          __set_mro(scalar(caller), $_[1]);
      }
  }

  =head2 mro::set_mro($classname, $type)

  Sets the mro of C<$classname> to one of the types
  C<dfs> or C<c3>.  Please see the L</USING C3>
  section for additional details.

  =cut

  sub __set_mro {
      my ($classname, $type) = @_;

      if(!defined $classname || !$type) {
          die q{Usage: mro::set_mro($classname, $type)};
      }

      if($type eq 'c3') {
          eval "package $classname; use Class::C3";
          die $@ if $@;
      }
      elsif($type eq 'dfs') {
          # In the dfs case, check whether we need to undo C3
          if(defined $Class::C3::MRO{$classname}) {
              Class::C3::_remove_method_dispatch_table($classname);
          }
          delete $Class::C3::MRO{$classname};
      }
      else {
          die qq{Invalid mro type "$type"};
      }

      return;
  }

  =head2 mro::get_mro($classname)

  Returns the MRO of the given class (either C<c3> or C<dfs>).

  It considers any Class::C3-using class to have C3 MRO
  even before L<Class::C3::initialize()> is called.

  =cut

  sub __get_mro {
      my $classname = shift;
      die "mro::get_mro requires a classname" if !defined $classname;
      return 'c3' if exists $Class::C3::MRO{$classname};
      return 'dfs';
  }

  =head2 mro::get_isarev($classname)

  Returns an arrayref of classes who are subclasses of the
  given classname.  In other words, classes in whose @ISA
  hierarchy we appear, no matter how indirectly.

  This is much slower on pre-5.9.5 Perls with MRO::Compat
  than it is on 5.9.5+, as it has to search the entire
  package namespace.

  =cut

  sub __get_all_pkgs_with_isas {
      no strict 'refs';
      no warnings 'recursion';

      my @retval;

      my $search = shift;
      my $pfx;
      my $isa;
      if(defined $search) {
          $isa = \@{"$search\::ISA"};
          $pfx = "$search\::";
      }
      else {
          $search = 'main';
          $isa = \@main::ISA;
          $pfx = '';
      }

      push(@retval, $search) if scalar(@$isa);

      foreach my $cand (keys %{"$search\::"}) {
          if($cand =~ s/::$//) {
              next if $cand eq $search; # skip self-reference (main?)
              push(@retval, @{__get_all_pkgs_with_isas($pfx . $cand)});
          }
      }

      return \@retval;
  }

  sub __get_isarev_recurse {
      no strict 'refs';

      my ($class, $all_isas, $level) = @_;

      die "Recursive inheritance detected" if $level > 100;

      my %retval;

      foreach my $cand (@$all_isas) {
          my $found_me;
          foreach (@{"$cand\::ISA"}) {
              if($_ eq $class) {
                  $found_me = 1;
                  last;
              }
          }
          if($found_me) {
              $retval{$cand} = 1;
              map { $retval{$_} = 1 }
                  @{__get_isarev_recurse($cand, $all_isas, $level+1)};
          }
      }
      return [keys %retval];
  }

  sub __get_isarev {
      my $classname = shift;
      die "mro::get_isarev requires a classname" if !defined $classname;

      __get_isarev_recurse($classname, __get_all_pkgs_with_isas(), 0);
  }

  =head2 mro::is_universal($classname)

  Returns a boolean status indicating whether or not
  the given classname is either C<UNIVERSAL> itself,
  or one of C<UNIVERSAL>'s parents by C<@ISA> inheritance.

  Any class for which this function returns true is
  "universal" in the sense that all classes potentially
  inherit methods from it.

  =cut

  sub __is_universal {
      my $classname = shift;
      die "mro::is_universal requires a classname" if !defined $classname;

      my $lin = __get_linear_isa('UNIVERSAL');
      foreach (@$lin) {
          return 1 if $classname eq $_;
      }

      return 0;
  }

  =head2 mro::invalidate_all_method_caches

  Increments C<PL_sub_generation>, which invalidates method
  caching in all packages.

  Please note that this is rarely necessary, unless you are
  dealing with a situation which is known to confuse Perl's
  method caching.

  =cut

  sub __invalidate_all_method_caches {
      # Super secret mystery code :)
      @f845a9c1ac41be33::ISA = @f845a9c1ac41be33::ISA;
      return;
  }

  =head2 mro::method_changed_in($classname)

  Invalidates the method cache of any classes dependent on the
  given class.  In L<MRO::Compat> on pre-5.9.5 Perls, this is
  an alias for C<mro::invalidate_all_method_caches> above, as
  pre-5.9.5 Perls have no other way to do this.  It will still
  enforce the requirement that you pass it a classname, for
  compatibility.

  Please note that this is rarely necessary, unless you are
  dealing with a situation which is known to confuse Perl's
  method caching.

  =cut

  sub __method_changed_in {
      my $classname = shift;
      die "mro::method_changed_in requires a classname" if !defined $classname;

      __invalidate_all_method_caches();
  }

  =head2 mro::get_pkg_gen($classname)

  Returns an integer which is incremented every time a local
  method of or the C<@ISA> of the given package changes on
  Perl 5.9.5+.  On earlier Perls with this L<MRO::Compat> module,
  it will probably increment a lot more often than necessary.

  =cut

  {
      my $__pkg_gen = 2;
      sub __get_pkg_gen_pp {
          my $classname = shift;
          die "mro::get_pkg_gen requires a classname" if !defined $classname;
          return $__pkg_gen++;
      }
  }

  sub __get_pkg_gen_c3xs {
      my $classname = shift;
      die "mro::get_pkg_gen requires a classname" if !defined $classname;

      return Class::C3::XS::_plsubgen();
  }

  =head1 USING C3

  While this module makes the 5.9.5+ syntaxes
  C<use mro 'c3'> and C<mro::set_mro("Foo", 'c3')> available
  on older Perls, it does so merely by passing off the work
  to L<Class::C3>.

  It does not remove the need for you to call
  C<Class::C3::initialize()>, C<Class::C3::reinitialize()>, and/or
  C<Class::C3::uninitialize()> at the appropriate times
  as documented in the L<Class::C3> docs.  These three functions
  are always provided by L<MRO::Compat>, either via L<Class::C3>
  itself on older Perls, or directly as no-ops on 5.9.5+.

  =head1 SEE ALSO

  L<Class::C3>

  L<mro>

  =head1 AUTHOR

  Brandon L. Black, E<lt>blblack@gmail.comE<gt>

  =head1 COPYRIGHT AND LICENSE

  Copyright 2007-2008 Brandon L. Black E<lt>blblack@gmail.comE<gt>

  This library is free software; you can redistribute it and/or modify
  it under the same terms as Perl itself.

  =cut

  1;
MRO_COMPAT

$fatpacked{"Method/Generate/Accessor.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'METHOD_GENERATE_ACCESSOR';
  package Method::Generate::Accessor;

  use Moo::_strictures;
  use Moo::_Utils qw(_load_module _maybe_load_module _install_coderef);
  use Moo::Object ();
  BEGIN { our @ISA = qw(Moo::Object) }
  use Sub::Quote qw(quote_sub quoted_from_sub quotify sanitize_identifier);
  use Scalar::Util 'blessed';
  use Carp qw(croak);
  BEGIN { our @CARP_NOT = qw(Moo::_Utils) }
  BEGIN {
    *_CAN_WEAKEN_READONLY = (
      "$]" < 5.008_003 or $ENV{MOO_TEST_PRE_583}
    ) ? sub(){0} : sub(){1};
    our $CAN_HAZ_XS =
      !$ENV{MOO_XS_DISABLE}
        &&
      _maybe_load_module('Class::XSAccessor')
        &&
      (eval { Class::XSAccessor->VERSION('1.07') })
    ;
    our $CAN_HAZ_XS_PRED =
      $CAN_HAZ_XS &&
      (eval { Class::XSAccessor->VERSION('1.17') })
    ;
  }
  BEGIN {
    package
      Method::Generate::Accessor::_Generated;
    $Carp::Internal{+__PACKAGE__} = 1;
  }

  my $module_name_only = qr/\A$Module::Runtime::module_name_rx\z/;

  sub _die_overwrite
  {
    my ($pkg, $method, $type) = @_;
    croak "You cannot overwrite a locally defined method ($method) with "
      . ( $type || 'an accessor' );
  }

  sub generate_method {
    my ($self, $into, $name, $spec, $quote_opts) = @_;
    $quote_opts = {
      no_defer => 1,
      package => 'Method::Generate::Accessor::_Generated',
      %{ $quote_opts||{} },
    };
    $spec->{allow_overwrite}++ if $name =~ s/^\+//;
    croak "Must have an is" unless my $is = $spec->{is};
    if ($is eq 'ro') {
      $spec->{reader} = $name unless exists $spec->{reader};
    } elsif ($is eq 'rw') {
      $spec->{accessor} = $name unless exists $spec->{accessor}
        or ( $spec->{reader} and $spec->{writer} );
    } elsif ($is eq 'lazy') {
      $spec->{reader} = $name unless exists $spec->{reader};
      $spec->{lazy} = 1;
      $spec->{builder} ||= '_build_'.$name unless exists $spec->{default};
    } elsif ($is eq 'rwp') {
      $spec->{reader} = $name unless exists $spec->{reader};
      $spec->{writer} = "_set_${name}" unless exists $spec->{writer};
    } elsif ($is ne 'bare') {
      croak "Unknown is ${is}";
    }
    if (exists $spec->{builder}) {
      if(ref $spec->{builder}) {
        $self->_validate_codulatable('builder', $spec->{builder},
          "$into->$name", 'or a method name');
        $spec->{builder_sub} = $spec->{builder};
        $spec->{builder} = 1;
      }
      $spec->{builder} = '_build_'.$name if ($spec->{builder}||0) eq 1;
      croak "Invalid builder for $into->$name - not a valid method name"
        if $spec->{builder} !~ $module_name_only;
    }
    if (($spec->{predicate}||0) eq 1) {
      $spec->{predicate} = $name =~ /^_/ ? "_has${name}" : "has_${name}";
    }
    if (($spec->{clearer}||0) eq 1) {
      $spec->{clearer} = $name =~ /^_/ ? "_clear${name}" : "clear_${name}";
    }
    if (($spec->{trigger}||0) eq 1) {
      $spec->{trigger} = quote_sub('shift->_trigger_'.$name.'(@_)');
    }
    if (($spec->{coerce}||0) eq 1) {
      my $isa = $spec->{isa};
      if (blessed $isa and $isa->can('coercion')) {
        $spec->{coerce} = $isa->coercion;
      } elsif (blessed $isa and $isa->can('coerce')) {
        $spec->{coerce} = sub { $isa->coerce(@_) };
      } else {
        croak "Invalid coercion for $into->$name - no appropriate type constraint";
      }
    }

    foreach my $setting (qw( isa coerce )) {
      next if !exists $spec->{$setting};
      $self->_validate_codulatable($setting, $spec->{$setting}, "$into->$name");
    }

    if (exists $spec->{default}) {
      if (ref $spec->{default}) {
        $self->_validate_codulatable('default', $spec->{default}, "$into->$name",
          'or a non-ref');
      }
    }

    if (exists $spec->{moosify}) {
      if (ref $spec->{moosify} ne 'ARRAY') {
        $spec->{moosify} = [$spec->{moosify}];
      }

      foreach my $spec (@{$spec->{moosify}}) {
        $self->_validate_codulatable('moosify', $spec, "$into->$name");
      }
    }

    my %methods;
    if (my $reader = $spec->{reader}) {
      _die_overwrite($into, $reader, 'a reader')
        if !$spec->{allow_overwrite} && defined &{"${into}::${reader}"};
      if (our $CAN_HAZ_XS && $self->is_simple_get($name, $spec)) {
        $methods{$reader} = $self->_generate_xs(
          getters => $into, $reader, $name, $spec
        );
      } else {
        $self->{captures} = {};
        $methods{$reader} =
          quote_sub "${into}::${reader}"
            => '    Carp::croak("'.$reader.' is a read-only accessor") if @_ > 1;'."\n"
               .$self->_generate_get($name, $spec)
            => delete $self->{captures}
            => $quote_opts
          ;
      }
    }
    if (my $accessor = $spec->{accessor}) {
      _die_overwrite($into, $accessor, 'an accessor')
        if !$spec->{allow_overwrite} && defined &{"${into}::${accessor}"};
      if (
        our $CAN_HAZ_XS
        && $self->is_simple_get($name, $spec)
        && $self->is_simple_set($name, $spec)
      ) {
        $methods{$accessor} = $self->_generate_xs(
          accessors => $into, $accessor, $name, $spec
        );
      } else {
        $self->{captures} = {};
        $methods{$accessor} =
          quote_sub "${into}::${accessor}"
            => $self->_generate_getset($name, $spec)
            => delete $self->{captures}
            => $quote_opts
          ;
      }
    }
    if (my $writer = $spec->{writer}) {
      _die_overwrite($into, $writer, 'a writer')
        if !$spec->{allow_overwrite} && defined &{"${into}::${writer}"};
      if (
        our $CAN_HAZ_XS
        && $self->is_simple_set($name, $spec)
      ) {
        $methods{$writer} = $self->_generate_xs(
          setters => $into, $writer, $name, $spec
        );
      } else {
        $self->{captures} = {};
        $methods{$writer} =
          quote_sub "${into}::${writer}"
            => $self->_generate_set($name, $spec)
            => delete $self->{captures}
            => $quote_opts
          ;
      }
    }
    if (my $pred = $spec->{predicate}) {
      _die_overwrite($into, $pred, 'a predicate')
        if !$spec->{allow_overwrite} && defined &{"${into}::${pred}"};
      if (our $CAN_HAZ_XS && our $CAN_HAZ_XS_PRED) {
        $methods{$pred} = $self->_generate_xs(
          exists_predicates => $into, $pred, $name, $spec
        );
      } else {
        $self->{captures} = {};
        $methods{$pred} =
          quote_sub "${into}::${pred}"
            => $self->_generate_simple_has('$_[0]', $name, $spec)."\n"
            => delete $self->{captures}
            => $quote_opts
          ;
      }
    }
    if (my $builder = delete $spec->{builder_sub}) {
      _install_coderef( "${into}::$spec->{builder}" => $builder );
    }
    if (my $cl = $spec->{clearer}) {
      _die_overwrite($into, $cl, 'a clearer')
        if !$spec->{allow_overwrite} && defined &{"${into}::${cl}"};
      $self->{captures} = {};
      $methods{$cl} =
        quote_sub "${into}::${cl}"
          => $self->_generate_simple_clear('$_[0]', $name, $spec)."\n"
          => delete $self->{captures}
          => $quote_opts
        ;
    }
    if (my $hspec = $spec->{handles}) {
      my $asserter = $spec->{asserter} ||= '_assert_'.$name;
      my @specs = do {
        if (ref($hspec) eq 'ARRAY') {
          map [ $_ => $_ ], @$hspec;
        } elsif (ref($hspec) eq 'HASH') {
          map [ $_ => ref($hspec->{$_}) ? @{$hspec->{$_}} : $hspec->{$_} ],
            keys %$hspec;
        } elsif (!ref($hspec)) {
          require Moo::Role;
          _load_module $hspec;
          map [ $_ => $_ ], Moo::Role->methods_provided_by($hspec)
        } else {
          croak "You gave me a handles of ${hspec} and I have no idea why";
        }
      };
      foreach my $delegation_spec (@specs) {
        my ($proxy, $target, @args) = @$delegation_spec;
        _die_overwrite($into, $proxy, 'a delegation')
          if !$spec->{allow_overwrite} && defined &{"${into}::${proxy}"};
        $self->{captures} = {};
        $methods{$proxy} =
          quote_sub "${into}::${proxy}"
            => $self->_generate_delegation($asserter, $target, \@args)
            => delete $self->{captures}
            => $quote_opts
          ;
      }
    }
    if (my $asserter = $spec->{asserter}) {
      _die_overwrite($into, $asserter, 'an asserter')
        if !$spec->{allow_overwrite} && defined &{"${into}::${asserter}"};
      local $self->{captures} = {};
      $methods{$asserter} =
        quote_sub "${into}::${asserter}"
          => $self->_generate_asserter($name, $spec)
          => delete $self->{captures}
          => $quote_opts
        ;
    }
    \%methods;
  }

  sub merge_specs {
    my ($self, @specs) = @_;
    my $spec = shift @specs;
    for my $old_spec (@specs) {
      foreach my $key (keys %$old_spec) {
        if ($key eq 'handles') {
        }
        elsif ($key eq 'moosify') {
          $spec->{$key} = [
            map { ref $_ eq 'ARRAY' ? @$_ : $_ }
            grep defined,
            ($old_spec->{$key}, $spec->{$key})
          ];
        }
        elsif (!exists $spec->{$key}) {
          $spec->{$key} = $old_spec->{$key};
        }
      }
    }
    $spec;
  }

  sub is_simple_attribute {
    my ($self, $name, $spec) = @_;
    # clearer doesn't have to be listed because it doesn't
    # affect whether defined/exists makes a difference
    !grep $spec->{$_},
      qw(lazy default builder coerce isa trigger predicate weak_ref);
  }

  sub is_simple_get {
    my ($self, $name, $spec) = @_;
    !($spec->{lazy} and (exists $spec->{default} or $spec->{builder}));
  }

  sub is_simple_set {
    my ($self, $name, $spec) = @_;
    !grep $spec->{$_}, qw(coerce isa trigger weak_ref);
  }

  sub has_default {
    my ($self, $name, $spec) = @_;
    $spec->{builder} or exists $spec->{default} or (($spec->{is}||'') eq 'lazy');
  }

  sub has_eager_default {
    my ($self, $name, $spec) = @_;
    (!$spec->{lazy} and (exists $spec->{default} or $spec->{builder}));
  }

  sub _generate_get {
    my ($self, $name, $spec) = @_;
    my $simple = $self->_generate_simple_get('$_[0]', $name, $spec);
    if ($self->is_simple_get($name, $spec)) {
      $simple;
    } else {
      $self->_generate_use_default(
        '$_[0]', $name, $spec,
        $self->_generate_simple_has('$_[0]', $name, $spec),
      );
    }
  }

  sub generate_simple_has {
    my $self = shift;
    $self->{captures} = {};
    my $code = $self->_generate_simple_has(@_);
    ($code, delete $self->{captures});
  }

  sub _generate_simple_has {
    my ($self, $me, $name) = @_;
    "exists ${me}->{${\quotify $name}}";
  }

  sub _generate_simple_clear {
    my ($self, $me, $name) = @_;
    "    delete ${me}->{${\quotify $name}}\n"
  }

  sub generate_get_default {
    my $self = shift;
    $self->{captures} = {};
    my $code = $self->_generate_get_default(@_);
    ($code, delete $self->{captures});
  }

  sub generate_use_default {
    my $self = shift;
    $self->{captures} = {};
    my $code = $self->_generate_use_default(@_);
    ($code, delete $self->{captures});
  }

  sub _generate_use_default {
    my ($self, $me, $name, $spec, $test) = @_;
    my $get_value = $self->_generate_get_default($me, $name, $spec);
    if ($spec->{coerce}) {
      $get_value = $self->_generate_coerce(
        $name, $get_value,
        $spec->{coerce}
      )
    }
    $test." ? \n"
    .$self->_generate_simple_get($me, $name, $spec)."\n:"
    .($spec->{isa} ?
         "    do {\n      my \$value = ".$get_value.";\n"
        ."      ".$self->_generate_isa_check($name, '$value', $spec->{isa}).";\n"
        ."      ".$self->_generate_simple_set($me, $name, $spec, '$value')."\n"
        ."    }\n"
      : '    ('.$self->_generate_simple_set($me, $name, $spec, $get_value).")\n"
    );
  }

  sub _generate_get_default {
    my ($self, $me, $name, $spec) = @_;
    if (exists $spec->{default}) {
      ref $spec->{default}
        ? $self->_generate_call_code($name, 'default', $me, $spec->{default})
      : quotify $spec->{default};
    }
    else {
      "${me}->${\$spec->{builder}}"
    }
  }

  sub generate_simple_get {
    my ($self, @args) = @_;
    $self->{captures} = {};
    my $code = $self->_generate_simple_get(@args);
    ($code, delete $self->{captures});
  }

  sub _generate_simple_get {
    my ($self, $me, $name) = @_;
    my $name_str = quotify $name;
    "${me}->{${name_str}}";
  }

  sub _generate_set {
    my ($self, $name, $spec) = @_;
    my ($me, $source) = ('$_[0]', '$_[1]');
    if ($self->is_simple_set($name, $spec)) {
      return $self->_generate_simple_set($me, $name, $spec, $source);
    }

    my ($coerce, $trigger, $isa_check) = @{$spec}{qw(coerce trigger isa)};
    if ($coerce) {
      $source = $self->_generate_coerce($name, $source, $coerce);
    }
    if ($isa_check) {
      'scalar do { my $value = '.$source.";\n"
      .'  ('.$self->_generate_isa_check($name, '$value', $isa_check)."),\n"
      .'  ('.$self->_generate_simple_set($me, $name, $spec, '$value')."),\n"
      .($trigger
        ? '('.$self->_generate_trigger($name, $me, '$value', $trigger)."),\n"
        : '')
      .'  ('.$self->_generate_simple_get($me, $name, $spec)."),\n"
      ."}";
    }
    elsif ($trigger) {
      my $set = $self->_generate_simple_set($me, $name, $spec, $source);
      "scalar (\n"
      . '  ('.$self->_generate_trigger($name, $me, "($set)", $trigger)."),\n"
      . '  ('.$self->_generate_simple_get($me, $name, $spec)."),\n"
      . ")";
    }
    else {
      '('.$self->_generate_simple_set($me, $name, $spec, $source).')';
    }
  }

  sub generate_coerce {
    my $self = shift;
    $self->{captures} = {};
    my $code = $self->_generate_coerce(@_);
    ($code, delete $self->{captures});
  }

  sub _attr_desc {
    my ($name, $init_arg) = @_;
    return quotify($name) if !defined($init_arg) or $init_arg eq $name;
    return quotify($name).' (constructor argument: '.quotify($init_arg).')';
  }

  sub _generate_coerce {
    my ($self, $name, $value, $coerce, $init_arg) = @_;
    $self->_wrap_attr_exception(
      $name,
      "coercion",
      $init_arg,
      $self->_generate_call_code($name, 'coerce', "${value}", $coerce),
      1,
    );
  }

  sub generate_trigger {
    my $self = shift;
    $self->{captures} = {};
    my $code = $self->_generate_trigger(@_);
    ($code, delete $self->{captures});
  }

  sub _generate_trigger {
    my ($self, $name, $obj, $value, $trigger) = @_;
    $self->_generate_call_code($name, 'trigger', "${obj}, ${value}", $trigger);
  }

  sub generate_isa_check {
    my ($self, @args) = @_;
    $self->{captures} = {};
    my $code = $self->_generate_isa_check(@args);
    ($code, delete $self->{captures});
  }

  sub _wrap_attr_exception {
    my ($self, $name, $step, $arg, $code, $want_return) = @_;
    my $prefix = quotify("${step} for "._attr_desc($name, $arg).' failed: ');
    "do {\n"
    .'  local $Method::Generate::Accessor::CurrentAttribute = {'."\n"
    .'    init_arg => '.quotify($arg).",\n"
    .'    name     => '.quotify($name).",\n"
    .'    step     => '.quotify($step).",\n"
    ."  };\n"
    .($want_return ? '  (my $_return),'."\n" : '')
    .'  (my $_error), (my $_old_error = $@);'."\n"
    ."  (eval {\n"
    .'    ($@ = $_old_error),'."\n"
    .'    ('
    .($want_return ? '$_return ='."\n" : '')
    .$code."),\n"
    ."    1\n"
    ."  } or\n"
    .'    $_error = CORE::ref $@ ? $@ : '.$prefix.'.$@);'."\n"
    .'  ($@ = $_old_error),'."\n"
    .'  (defined $_error and CORE::die $_error);'."\n"
    .($want_return ? '  $_return;'."\n" : '')
    ."}\n"
  }

  sub _generate_isa_check {
    my ($self, $name, $value, $check, $init_arg) = @_;
    $self->_wrap_attr_exception(
      $name,
      "isa check",
      $init_arg,
      $self->_generate_call_code($name, 'isa_check', $value, $check)
    );
  }

  sub _generate_call_code {
    my ($self, $name, $type, $values, $sub) = @_;
    $sub = \&{$sub} if blessed($sub);  # coderef if blessed
    if (my $quoted = quoted_from_sub($sub)) {
      my $local = 1;
      if ($values eq '@_' || $values eq '$_[0]') {
        $local = 0;
        $values = '@_';
      }
      my $code = $quoted->[1];
      if (my $captures = $quoted->[2]) {
        my $cap_name = qq{\$${type}_captures_for_}.sanitize_identifier($name);
        $self->{captures}->{$cap_name} = \$captures;
        Sub::Quote::inlinify($code, $values,
          Sub::Quote::capture_unroll($cap_name, $captures, 6), $local);
      } else {
        Sub::Quote::inlinify($code, $values, undef, $local);
      }
    } else {
      my $cap_name = qq{\$${type}_for_}.sanitize_identifier($name);
      $self->{captures}->{$cap_name} = \$sub;
      "${cap_name}->(${values})";
    }
  }

  sub _sanitize_name { sanitize_identifier($_[1]) }

  sub generate_populate_set {
    my $self = shift;
    $self->{captures} = {};
    my $code = $self->_generate_populate_set(@_);
    ($code, delete $self->{captures});
  }

  sub _generate_populate_set {
    my ($self, $me, $name, $spec, $source, $test, $init_arg) = @_;

    my $has_default = $self->has_eager_default($name, $spec);
    if (!($has_default || $test)) {
      return '';
    }
    if ($has_default) {
      my $get_default = $self->_generate_get_default($me, $name, $spec);
      $source =
        $test
          ? "(\n  ${test}\n"
              ."   ? ${source}\n   : "
              .$get_default
              .")"
          : $get_default;
    }
    if ($spec->{coerce}) {
      $source = $self->_generate_coerce(
        $name, $source,
        $spec->{coerce}, $init_arg
      )
    }
    if ($spec->{isa}) {
      $source = 'scalar do { my $value = '.$source.";\n"
      .'  ('.$self->_generate_isa_check(
          $name, '$value', $spec->{isa}, $init_arg
        )."),\n"
      ."  \$value\n"
      ."}\n";
    }
    my $set = $self->_generate_simple_set($me, $name, $spec, $source);
    my $trigger = $spec->{trigger} ? $self->_generate_trigger(
      $name, $me, $self->_generate_simple_get($me, $name, $spec),
      $spec->{trigger}
    ) : undef;
    if ($has_default) {
      "($set)," . ($trigger && $test ? "($test and $trigger)," : '') . "\n";
    }
    else {
      "($test and ($set)" . ($trigger ? ", ($trigger)" : '') . "),\n";
    }
  }

  sub _generate_core_set {
    my ($self, $me, $name, $spec, $value) = @_;
    my $name_str = quotify $name;
    "${me}->{${name_str}} = ${value}";
  }

  sub _generate_simple_set {
    my ($self, $me, $name, $spec, $value) = @_;
    my $name_str = quotify $name;
    my $simple = $self->_generate_core_set($me, $name, $spec, $value);

    if ($spec->{weak_ref}) {
      require Scalar::Util;
      my $get = $self->_generate_simple_get($me, $name, $spec);

      # Perl < 5.8.3 can't weaken refs to readonly vars
      # (e.g. string constants). This *can* be solved by:
      #
      # &Internals::SvREADONLY($foo, 0);
      # Scalar::Util::weaken($foo);
      # &Internals::SvREADONLY($foo, 1);
      #
      # but requires Internal functions and is just too damn crazy
      # so simply throw a better exception
      my $weak_simple = _CAN_WEAKEN_READONLY
        ? "do { Scalar::Util::weaken(${simple}); no warnings 'void'; $get }"
        : <<"EOC"
          ( eval { Scalar::Util::weaken($simple); 1 }
            ? do { no warnings 'void'; $get }
            : do {
              if( \$@ =~ /Modification of a read-only value attempted/) {
                require Carp;
                Carp::croak( sprintf (
                  'Reference to readonly value in "%s" can not be weakened on Perl < 5.8.3',
                  $name_str,
                ) );
              } else {
                die \$@;
              }
            }
          )
  EOC
    } else {
      $simple;
    }
  }

  sub _generate_getset {
    my ($self, $name, $spec) = @_;
    q{(@_ > 1}."\n      ? ".$self->_generate_set($name, $spec)
      ."\n      : ".$self->_generate_get($name, $spec)."\n    )";
  }

  sub _generate_asserter {
    my ($self, $name, $spec) = @_;
    my $name_str = quotify($name);
    "do {\n"
     ."  my \$val = ".$self->_generate_get($name, $spec).";\n"
     ."  ".$self->_generate_simple_has('$_[0]', $name, $spec)."\n"
     ."    or Carp::croak(q{Attempted to access '}.${name_str}.q{' but it is not set});\n"
     ."  \$val;\n"
     ."}\n";
  }
  sub _generate_delegation {
    my ($self, $asserter, $target, $args) = @_;
    my $arg_string = do {
      if (@$args) {
        # I could, I reckon, linearise out non-refs here using quotify
        # plus something to check for numbers but I'm unsure if it's worth it
        $self->{captures}{'@curries'} = $args;
        '@curries, @_';
      } else {
        '@_';
      }
    };
    "shift->${asserter}->${target}(${arg_string});";
  }

  sub _generate_xs {
    my ($self, $type, $into, $name, $slot) = @_;
    Class::XSAccessor->import(
      class => $into,
      $type => { $name => $slot },
      replace => 1,
    );
    $into->can($name);
  }

  sub default_construction_string { '{}' }

  sub _validate_codulatable {
    my ($self, $setting, $value, $into, $appended) = @_;

    my $error;

    if (blessed $value) {
      local $@;
      no warnings 'void';
      eval { \&$value; 1 }
        and return 1;
      $error = "could not be converted to a coderef: $@";
    }
    elsif (ref $value eq 'CODE') {
      return 1;
    }
    else {
      $error = 'is not a coderef or code-convertible object';
    }

    croak "Invalid $setting '"
      . ($INC{'overload.pm'} ? overload::StrVal($value) : $value)
      . "' for $into " . $error
      . ($appended ? " $appended" : '');
  }

  1;
METHOD_GENERATE_ACCESSOR

$fatpacked{"Method/Generate/BuildAll.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'METHOD_GENERATE_BUILDALL';
  package Method::Generate::BuildAll;

  use Moo::_strictures;
  use Moo::Object ();
  BEGIN { our @ISA = qw(Moo::Object) }
  use Sub::Quote qw(quote_sub quotify);
  use Moo::_Utils qw(_getglob);
  use Moo::_mro;

  sub generate_method {
    my ($self, $into) = @_;
    quote_sub "${into}::BUILDALL"
      => join('',
        $self->_handle_subbuild($into),
        qq{    my \$self = shift;\n},
        $self->buildall_body_for($into, '$self', '@_'),
        qq{    return \$self\n},
      )
      => {}
      => { no_defer => 1 }
    ;
  }

  sub _handle_subbuild {
    my ($self, $into) = @_;
    '    if (ref($_[0]) ne '.quotify($into).') {'."\n".
    '      return shift->Moo::Object::BUILDALL(@_)'.";\n".
    '    }'."\n";
  }

  sub buildall_body_for {
    my ($self, $into, $me, $args) = @_;
    my @builds =
      grep *{_getglob($_)}{CODE},
      map "${_}::BUILD",
      reverse @{mro::get_linear_isa($into)};
    '    (('.$args.')[0]->{__no_BUILD__} or ('."\n"
    .join('', map qq{      ${me}->${_}(${args}),\n}, @builds)
    ."    )),\n";
  }

  1;
METHOD_GENERATE_BUILDALL

$fatpacked{"Method/Generate/Constructor.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'METHOD_GENERATE_CONSTRUCTOR';
  package Method::Generate::Constructor;

  use Moo::_strictures;
  use Sub::Quote qw(quote_sub quotify);
  use Sub::Defer;
  use Moo::_Utils qw(_getstash _getglob);
  use Moo::_mro;
  use Scalar::Util qw(weaken);
  use Carp qw(croak);
  use Carp::Heavy ();
  BEGIN { our @CARP_NOT = qw(Sub::Defer) }
  BEGIN {
    local $Moo::sification::disabled = 1;
    require Moo;
    Moo->import;
  }

  sub register_attribute_specs {
    my ($self, @new_specs) = @_;
    $self->assert_constructor;
    my $specs = $self->{attribute_specs}||={};
    my $ag = $self->accessor_generator;
    while (my ($name, $new_spec) = splice @new_specs, 0, 2) {
      if ($name =~ s/^\+//) {
        croak "has '+${name}' given but no ${name} attribute already exists"
          unless my $old_spec = $specs->{$name};
        $ag->merge_specs($new_spec, $old_spec);
      }
      if ($new_spec->{required}
        && !(
          $ag->has_default($name, $new_spec)
          || !exists $new_spec->{init_arg}
          || defined $new_spec->{init_arg}
        )
      ) {
        croak "You cannot have a required attribute (${name})"
          . " without a default, builder, or an init_arg";
      }
      $new_spec->{index} = scalar keys %$specs
        unless defined $new_spec->{index};
      $specs->{$name} = $new_spec;
    }
    $self;
  }

  sub all_attribute_specs {
    $_[0]->{attribute_specs}
  }

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

  sub construction_string {
    my ($self) = @_;
    $self->{construction_string}
      ||= $self->_build_construction_string;
  }

  sub buildall_generator {
    require Method::Generate::BuildAll;
    Method::Generate::BuildAll->new;
  }

  sub _build_construction_string {
    my ($self) = @_;
    my $builder = $self->{construction_builder};
    $builder ? $self->$builder
      : 'bless('
      .$self->accessor_generator->default_construction_string
      .', $class);'
  }

  sub install_delayed {
    my ($self) = @_;
    $self->assert_constructor;
    my $package = $self->{package};
    my (undef, @isa) = @{mro::get_linear_isa($package)};
    my $isa = join ',', @isa;
    my (undef, $from_file, $from_line) = caller(Carp::short_error_loc());
    my $constructor = defer_sub "${package}::new" => sub {
      my (undef, @new_isa) = @{mro::get_linear_isa($package)};
      if (join(',', @new_isa) ne $isa) {
        my ($expected_new) = grep { *{_getglob($_.'::new')}{CODE} } @isa;
        my ($found_new) = grep { *{_getglob($_.'::new')}{CODE} } @new_isa;
        if (($found_new||'') ne ($expected_new||'')) {
          $found_new ||= 'none';
          $expected_new ||= 'none';
          croak "Expected parent constructor of $package to be"
          . " $expected_new, but found $found_new: changing the inheritance"
          . " chain (\@ISA) at runtime (after $from_file line $from_line) is unsupported";
        }
      }

      my $constructor = $self->generate_method(
        $package, 'new', $self->{attribute_specs}, { no_install => 1, no_defer => 1 }
      );
      $self->{inlined} = 1;
      weaken($self->{constructor} = $constructor);
      $constructor;
    };
    $self->{inlined} = 0;
    weaken($self->{constructor} = $constructor);
    $self;
  }

  sub current_constructor {
    my ($self, $package) = @_;
    return *{_getglob("${package}::new")}{CODE};
  }

  sub assert_constructor {
    my ($self) = @_;
    my $package = $self->{package} or return 1;
    my $current = $self->current_constructor($package)
      or return 1;
    my $constructor = $self->{constructor}
      or croak "Unknown constructor for $package already exists";
    croak "Constructor for $package has been replaced with an unknown sub"
      if $constructor != $current;
    croak "Constructor for $package has been inlined and cannot be updated"
      if $self->{inlined};
  }

  sub generate_method {
    my ($self, $into, $name, $spec, $quote_opts) = @_;
    $quote_opts = {
      %{$quote_opts||{}},
      package => $into,
    };
    foreach my $no_init (grep !exists($spec->{$_}{init_arg}), keys %$spec) {
      $spec->{$no_init}{init_arg} = $no_init;
    }
    local $self->{captures} = {};

    my $into_buildargs = $into->can('BUILDARGS');

    my $body
      = '    my $invoker = CORE::shift();'."\n"
      . '    my $class = CORE::ref($invoker) ? CORE::ref($invoker) : $invoker;'."\n"
      . $self->_handle_subconstructor($into, $name)
      . ( $into_buildargs && $into_buildargs != \&Moo::Object::BUILDARGS
        ? $self->_generate_args_via_buildargs
        : $self->_generate_args
      )
      . $self->_check_required($spec)
      . '    my $new = '.$self->construction_string.";\n"
      . $self->_assign_new($spec)
      . ( $into->can('BUILD')
        ? $self->buildall_generator->buildall_body_for( $into, '$new', '$args' )
        : ''
      )
      . '    return $new;'."\n";

    if ($into->can('DEMOLISH')) {
      require Method::Generate::DemolishAll;
      Method::Generate::DemolishAll->new->generate_method($into);
    }
    quote_sub
      "${into}::${name}" => $body,
      $self->{captures}, $quote_opts||{}
    ;
  }

  sub _handle_subconstructor {
    my ($self, $into, $name) = @_;
    if (my $gen = $self->{subconstructor_handler}) {
      '    if ($class ne '.quotify($into).') {'."\n".
      $gen.
      '    }'."\n";
    } else {
      ''
    }
  }

  sub _cap_call {
    my ($self, $code, $captures) = @_;
    @{$self->{captures}}{keys %$captures} = values %$captures if $captures;
    $code;
  }

  sub _generate_args_via_buildargs {
    my ($self) = @_;
    q{    my $args = $class->BUILDARGS(@_);}."\n"
    .q{    Carp::croak("BUILDARGS did not return a hashref") unless CORE::ref($args) eq 'HASH';}
    ."\n";
  }

  # inlined from Moo::Object - update that first.
  sub _generate_args {
    my ($self) = @_;
    return <<'_EOA';
      my $args = scalar @_ == 1
        ? CORE::ref $_[0] eq 'HASH'
          ? { %{ $_[0] } }
          : Carp::croak("Single parameters to new() must be a HASH ref"
              . " data => ". $_[0])
        : @_ % 2
          ? Carp::croak("The new() method for $class expects a hash reference or a"
              . " key/value list. You passed an odd number of arguments")
          : {@_}
      ;
  _EOA

  }

  sub _assign_new {
    my ($self, $spec) = @_;
    my $ag = $self->accessor_generator;
    my %test;
    NAME: foreach my $name (sort keys %$spec) {
      my $attr_spec = $spec->{$name};
      next NAME unless defined($attr_spec->{init_arg})
                         or $ag->has_eager_default($name, $attr_spec);
      $test{$name} = $attr_spec->{init_arg};
    }
    join '', map {
      my $arg = $test{$_};
      my $arg_key = quotify($arg);
      my $test = defined $arg ? "exists \$args->{$arg_key}" : undef;
      my $source = defined $arg ? "\$args->{$arg_key}" : undef;
      my $attr_spec = $spec->{$_};
      $self->_cap_call($ag->generate_populate_set(
        '$new', $_, $attr_spec, $source, $test, $arg,
      ));
    } sort keys %test;
  }

  sub _check_required {
    my ($self, $spec) = @_;
    my @required_init =
      map $spec->{$_}{init_arg},
        grep {
          my $s = $spec->{$_}; # ignore required if default or builder set
          $s->{required} and not($s->{builder} or exists $s->{default})
        } sort keys %$spec;
    return '' unless @required_init;
    '    if (my @missing = grep !exists $args->{$_}, '
      .join(', ', map quotify($_), @required_init).') {'."\n"
      .q{      Carp::croak("Missing required arguments: ".CORE::join(', ', sort @missing));}."\n"
      ."    }\n";
  }

  # bootstrap our own constructor
  sub new {
    my $class = shift;
    delete _getstash(__PACKAGE__)->{new};
    bless $class->BUILDARGS(@_), $class;
  }
  Moo->_constructor_maker_for(__PACKAGE__)
  ->register_attribute_specs(
    attribute_specs => {
      is => 'ro',
      reader => 'all_attribute_specs',
    },
    accessor_generator => { is => 'ro' },
    construction_string => { is => 'lazy' },
    construction_builder => { is => 'bare' },
    subconstructor_handler => { is => 'ro' },
    package => { is => 'bare' },
  );
  if ($INC{'Moo/HandleMoose.pm'} && !$Moo::sification::disabled) {
    Moo::HandleMoose::inject_fake_metaclass_for(__PACKAGE__);
  }

  1;
METHOD_GENERATE_CONSTRUCTOR

$fatpacked{"Method/Generate/DemolishAll.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'METHOD_GENERATE_DEMOLISHALL';
  package Method::Generate::DemolishAll;

  use Moo::_strictures;
  use Moo::Object ();
  BEGIN { our @ISA = qw(Moo::Object) }
  use Sub::Quote qw(quote_sub quotify);
  use Moo::_Utils qw(_getglob);
  use Moo::_mro;

  sub generate_method {
    my ($self, $into) = @_;
    quote_sub "${into}::DEMOLISHALL", join '',
      $self->_handle_subdemolish($into),
      qq{    my \$self = shift;\n},
      $self->demolishall_body_for($into, '$self', '@_'),
      qq{    return \$self\n};
    quote_sub "${into}::DESTROY", join '',
      q!    my $self = shift;
      my $e = do {
        local $?;
        local $@;
        require Devel::GlobalDestruction;
        eval {
          $self->DEMOLISHALL(Devel::GlobalDestruction::in_global_destruction);
        };
        $@;
      };

      # fatal warnings+die in DESTROY = bad times (perl rt#123398)
      no warnings FATAL => 'all';
      use warnings 'all';
      die $e if $e; # rethrow
    !;
  }

  sub demolishall_body_for {
    my ($self, $into, $me, $args) = @_;
    my @demolishers =
      grep *{_getglob($_)}{CODE},
      map "${_}::DEMOLISH",
      @{mro::get_linear_isa($into)};
    join '', map qq{    ${me}->${_}(${args});\n}, @demolishers;
  }

  sub _handle_subdemolish {
    my ($self, $into) = @_;
    '    if (ref($_[0]) ne '.quotify($into).') {'."\n".
    '      return shift->Moo::Object::DEMOLISHALL(@_)'.";\n".
    '    }'."\n";
  }

  1;
METHOD_GENERATE_DEMOLISHALL

$fatpacked{"Module/Implementation.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_IMPLEMENTATION';
  package Module::Implementation;
  # git description: v0.08-2-gd599347
  $Module::Implementation::VERSION = '0.09';

  use strict;
  use warnings;

  use Module::Runtime 0.012 qw( require_module );
  use Try::Tiny;

  # This is needed for the benefit of Test::CleanNamespaces, which in turn loads
  # Package::Stash, which in turn loads this module and expects a minimum
  # version.
  unless ( exists $Module::Implementation::{VERSION}
      && ${ $Module::Implementation::{VERSION} } ) {

      $Module::Implementation::{VERSION} = \42;
  }

  my %Implementation;

  sub build_loader_sub {
      my $caller = caller();

      return _build_loader( $caller, @_ );
  }

  sub _build_loader {
      my $package = shift;
      my %args    = @_;

      my @implementations = @{ $args{implementations} };
      my @symbols = @{ $args{symbols} || [] };

      my $implementation;
      my $env_var = uc $package;
      $env_var =~ s/::/_/g;
      $env_var .= '_IMPLEMENTATION';

      return sub {
          my ( $implementation, $loaded ) = _load_implementation(
              $package,
              $ENV{$env_var},
              \@implementations,
          );

          $Implementation{$package} = $implementation;

          _copy_symbols( $loaded, $package, \@symbols );

          return $loaded;
      };
  }

  sub implementation_for {
      my $package = shift;

      return $Implementation{$package};
  }

  sub _load_implementation {
      my $package         = shift;
      my $env_value       = shift;
      my $implementations = shift;

      if ($env_value) {
          die "$env_value is not a valid implementation for $package"
              unless grep { $_ eq $env_value } @{$implementations};

          my $requested = "${package}::$env_value";

          # Values from the %ENV hash are tainted. We know it's safe to untaint
          # this value because the value was one of our known implementations.
          ($requested) = $requested =~ /^(.+)$/;

          try {
              require_module($requested);
          }
          catch {
              require Carp;
              Carp::croak("Could not load $requested: $_");
          };

          return ( $env_value, $requested );
      }
      else {
          my $err;
          for my $possible ( @{$implementations} ) {
              my $try = "${package}::$possible";

              my $ok;
              try {
                  require_module($try);
                  $ok = 1;
              }
              catch {
                  $err .= $_ if defined $_;
              };

              return ( $possible, $try ) if $ok;
          }

          require Carp;
          if ( defined $err && length $err ) {
              Carp::croak(
                  "Could not find a suitable $package implementation: $err");
          }
          else {
              Carp::croak(
                  'Module::Runtime failed to load a module but did not throw a real error. This should never happen. Something is very broken'
              );
          }
      }
  }

  sub _copy_symbols {
      my $from_package = shift;
      my $to_package   = shift;
      my $symbols      = shift;

      for my $sym ( @{$symbols} ) {
          my $type = $sym =~ s/^([\$\@\%\&\*])// ? $1 : '&';

          my $from = "${from_package}::$sym";
          my $to   = "${to_package}::$sym";

          {
              no strict 'refs';
              no warnings 'once';

              # Copied from Exporter
              *{$to}
                  = $type eq '&' ? \&{$from}
                  : $type eq '$' ? \${$from}
                  : $type eq '@' ? \@{$from}
                  : $type eq '%' ? \%{$from}
                  : $type eq '*' ? *{$from}
                  : die
                  "Can't copy symbol from $from_package to $to_package: $type$sym";
          }
      }
  }

  1;

  # ABSTRACT: Loads one of several alternate underlying implementations for a module

  __END__

  =pod

  =encoding UTF-8

  =head1 NAME

  Module::Implementation - Loads one of several alternate underlying implementations for a module

  =head1 VERSION

  version 0.09

  =head1 SYNOPSIS

    package Foo::Bar;

    use Module::Implementation;

    BEGIN {
        my $loader = Module::Implementation::build_loader_sub(
            implementations => [ 'XS',  'PurePerl' ],
            symbols         => [ 'run', 'check' ],
        );

        $loader->();
    }

    package Consumer;

    # loads the first viable implementation
    use Foo::Bar;

  =head1 DESCRIPTION

  This module abstracts out the process of choosing one of several underlying
  implementations for a module. This can be used to provide XS and pure Perl
  implementations of a module, or it could be used to load an implementation for
  a given OS or any other case of needing to provide multiple implementations.

  This module is only useful when you know all the implementations ahead of
  time. If you want to load arbitrary implementations then you probably want
  something like a plugin system, not this module.

  =head1 API

  This module provides two subroutines, neither of which are exported.

  =head2 Module::Implementation::build_loader_sub(...)

  This subroutine takes the following arguments.

  =over 4

  =item * implementations

  This should be an array reference of implementation names. Each name should
  correspond to a module in the caller's namespace.

  In other words, using the example in the L</SYNOPSIS>, this module will look
  for the C<Foo::Bar::XS> and C<Foo::Bar::PurePerl> modules.

  This argument is required.

  =item * symbols

  A list of symbols to copy from the implementation package to the calling
  package.

  These can be prefixed with a variable type: C<$>, C<@>, C<%>, C<&>, or
  C<*)>. If no prefix is given, the symbol is assumed to be a subroutine.

  This argument is optional.

  =back

  This subroutine I<returns> the implementation loader as a sub reference.

  It is up to you to call this loader sub in your code.

  I recommend that you I<do not> call this loader in an C<import()> sub. If a
  caller explicitly requests no imports, your C<import()> sub will not be run at
  all, which can cause weird breakage.

  =head2 Module::Implementation::implementation_for($package)

  Given a package name, this subroutine returns the implementation that was
  loaded for the package. This is not a full package name, just the suffix that
  identifies the implementation. For the L</SYNOPSIS> example, this subroutine
  would be called as C<Module::Implementation::implementation_for('Foo::Bar')>,
  and it would return "XS" or "PurePerl".

  =head1 HOW THE IMPLEMENTATION LOADER WORKS

  The implementation loader works like this ...

  First, it checks for an C<%ENV> var specifying the implementation to load. The
  env var is based on the package name which loads the implementations. The
  C<::> package separator is replaced with C<_>, and made entirely
  upper-case. Finally, we append "_IMPLEMENTATION" to this name.

  So in our L</SYNOPSIS> example, the corresponding C<%ENV> key would be
  C<FOO_BAR_IMPLEMENTATION>.

  If this is set, then the loader will B<only> try to load this one
  implementation.

  If the env var requests an implementation which doesn't match one of the
  implementations specified when the loader was created, an error is thrown.

  If this one implementation fails to load then loader throws an error. This is
  useful for testing. You can request a specific implementation in a test file
  by writing something like this:

    BEGIN { $ENV{FOO_BAR_IMPLEMENTATION} = 'XS' }
    use Foo::Bar;

  If the environment variable is I<not> set, then the loader simply tries the
  implementations originally passed to C<Module::Implementation>. The
  implementations are tried in the order in which they were originally passed.

  The loader will use the first implementation that loads without an error. It
  will copy any requested symbols from this implementation.

  If none of the implementations can be loaded, then the loader throws an
  exception.

  The loader returns the name of the package it loaded.

  =head1 AUTHOR

  Dave Rolsky <autarch@urth.org>

  =head1 COPYRIGHT AND LICENSE

  This software is Copyright (c) 2014 by Dave Rolsky.

  This is free software, licensed under:

    The Artistic License 2.0 (GPL Compatible)

  =cut
MODULE_IMPLEMENTATION

$fatpacked{"Module/Runtime.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_RUNTIME';
  =head1 NAME

  Module::Runtime - runtime module handling

  =head1 SYNOPSIS

      use Module::Runtime qw(
  	$module_name_rx is_module_name check_module_name
  	module_notional_filename require_module);

      if($module_name =~ /\A$module_name_rx\z/o) { ...
      if(is_module_name($module_name)) { ...
      check_module_name($module_name);

      $notional_filename = module_notional_filename($module_name);
      require_module($module_name);

      use Module::Runtime qw(use_module use_package_optimistically);

      $bi = use_module("Math::BigInt", 1.31)->new("1_234");
      $widget = use_package_optimistically("Local::Widget")->new;

      use Module::Runtime qw(
  	$top_module_spec_rx $sub_module_spec_rx
  	is_module_spec check_module_spec
  	compose_module_name);

      if($spec =~ /\A$top_module_spec_rx\z/o) { ...
      if($spec =~ /\A$sub_module_spec_rx\z/o) { ...
      if(is_module_spec("Standard::Prefix", $spec)) { ...
      check_module_spec("Standard::Prefix", $spec);

      $module_name = compose_module_name("Standard::Prefix", $spec);

  =head1 DESCRIPTION

  The functions exported by this module deal with runtime handling of
  Perl modules, which are normally handled at compile time.  This module
  avoids using any other modules, so that it can be used in low-level
  infrastructure.

  The parts of this module that work with module names apply the same syntax
  that is used for barewords in Perl source.  In principle this syntax
  can vary between versions of Perl, and this module applies the syntax of
  the Perl on which it is running.  In practice the usable syntax hasn't
  changed yet.  There's some intent for Unicode module names to be supported
  in the future, but this hasn't yet amounted to any consistent facility.

  The functions of this module whose purpose is to load modules include
  workarounds for three old Perl core bugs regarding C<require>.  These
  workarounds are applied on any Perl version where the bugs exist, except
  for a case where one of the bugs cannot be adequately worked around in
  pure Perl.

  =head2 Module name syntax

  The usable module name syntax has not changed from Perl 5.000 up to
  Perl 5.19.8.  The syntax is composed entirely of ASCII characters.
  From Perl 5.6 onwards there has been some attempt to allow the use of
  non-ASCII Unicode characters in Perl source, but it was fundamentally
  broken (like the entirety of Perl 5.6's Unicode handling) and remained
  pretty much entirely unusable until it got some attention in the Perl
  5.15 series.  Although Unicode is now consistently accepted by the
  parser in some places, it remains broken for module names.  Furthermore,
  there has not yet been any work on how to map Unicode module names into
  filenames, so in that respect also Unicode module names are unusable.

  The module name syntax is, precisely: the string must consist of one or
  more segments separated by C<::>; each segment must consist of one or more
  identifier characters (ASCII alphanumerics plus "_"); the first character
  of the string must not be a digit.  Thus "C<IO::File>", "C<warnings>",
  and "C<foo::123::x_0>" are all valid module names, whereas "C<IO::>"
  and "C<1foo::bar>" are not.  C<'> separators are not permitted by this
  module, though they remain usable in Perl source, being translated to
  C<::> in the parser.

  =head2 Core bugs worked around

  The first bug worked around is core bug [perl #68590], which causes
  lexical state in one file to leak into another that is C<require>d/C<use>d
  from it.  This bug is present from Perl 5.6 up to Perl 5.10, and is
  fixed in Perl 5.11.0.  From Perl 5.9.4 up to Perl 5.10.0 no satisfactory
  workaround is possible in pure Perl.  The workaround means that modules
  loaded via this module don't suffer this pollution of their lexical
  state.  Modules loaded in other ways, or via this module on the Perl
  versions where the pure Perl workaround is impossible, remain vulnerable.
  The module L<Lexical::SealRequireHints> provides a complete workaround
  for this bug.

  The second bug worked around causes some kinds of failure in module
  loading, principally compilation errors in the loaded module, to be
  recorded in C<%INC> as if they were successful, so later attempts to load
  the same module immediately indicate success.  This bug is present up
  to Perl 5.8.9, and is fixed in Perl 5.9.0.  The workaround means that a
  compilation error in a module loaded via this module won't be cached as
  a success.  Modules loaded in other ways remain liable to produce bogus
  C<%INC> entries, and if a bogus entry exists then it will mislead this
  module if it is used to re-attempt loading.

  The third bug worked around causes the wrong context to be seen at
  file scope of a loaded module, if C<require> is invoked in a location
  that inherits context from a higher scope.  This bug is present up to
  Perl 5.11.2, and is fixed in Perl 5.11.3.  The workaround means that
  a module loaded via this module will always see the correct context.
  Modules loaded in other ways remain vulnerable.

  =cut

  package Module::Runtime;

  # Don't "use 5.006" here, because Perl 5.15.6 will load feature.pm if
  # the version check is done that way.
  BEGIN { require 5.006; }
  # Don't "use warnings" here, to avoid dependencies.  Do standardise the
  # warning status by lexical override; unfortunately the only safe bitset
  # to build in is the empty set, equivalent to "no warnings".
  BEGIN { ${^WARNING_BITS} = ""; }
  # Don't "use strict" here, to avoid dependencies.

  our $VERSION = "0.016";

  # Don't use Exporter here, to avoid dependencies.
  our @EXPORT_OK = qw(
  	$module_name_rx is_module_name is_valid_module_name check_module_name
  	module_notional_filename require_module
  	use_module use_package_optimistically
  	$top_module_spec_rx $sub_module_spec_rx
  	is_module_spec is_valid_module_spec check_module_spec
  	compose_module_name
  );
  my %export_ok = map { ($_ => undef) } @EXPORT_OK;
  sub import {
  	my $me = shift;
  	my $callpkg = caller(0);
  	my $errs = "";
  	foreach(@_) {
  		if(exists $export_ok{$_}) {
  			# We would need to do "no strict 'refs'" here
  			# if we had enabled strict at file scope.
  			if(/\A\$(.*)\z/s) {
  				*{$callpkg."::".$1} = \$$1;
  			} else {
  				*{$callpkg."::".$_} = \&$_;
  			}
  		} else {
  			$errs .= "\"$_\" is not exported by the $me module\n";
  		}
  	}
  	if($errs ne "") {
  		die "${errs}Can't continue after import errors ".
  			"at @{[(caller(0))[1]]} line @{[(caller(0))[2]]}.\n";
  	}
  }

  # Logic duplicated from Params::Classify.  Duplicating it here avoids
  # an extensive and potentially circular dependency graph.
  sub _is_string($) {
  	my($arg) = @_;
  	return defined($arg) && ref(\$arg) eq "SCALAR";
  }

  =head1 REGULAR EXPRESSIONS

  These regular expressions do not include any anchors, so to check
  whether an entire string matches a syntax item you must supply the
  anchors yourself.

  =over

  =item $module_name_rx

  Matches a valid Perl module name in bareword syntax.

  =cut

  our $module_name_rx = qr/[A-Z_a-z][0-9A-Z_a-z]*(?:::[0-9A-Z_a-z]+)*/;

  =item $top_module_spec_rx

  Matches a module specification for use with L</compose_module_name>,
  where no prefix is being used.

  =cut

  my $qual_module_spec_rx =
  	qr#(?:/|::)[A-Z_a-z][0-9A-Z_a-z]*(?:(?:/|::)[0-9A-Z_a-z]+)*#;

  my $unqual_top_module_spec_rx =
  	qr#[A-Z_a-z][0-9A-Z_a-z]*(?:(?:/|::)[0-9A-Z_a-z]+)*#;

  our $top_module_spec_rx = qr/$qual_module_spec_rx|$unqual_top_module_spec_rx/o;

  =item $sub_module_spec_rx

  Matches a module specification for use with L</compose_module_name>,
  where a prefix is being used.

  =cut

  my $unqual_sub_module_spec_rx = qr#[0-9A-Z_a-z]+(?:(?:/|::)[0-9A-Z_a-z]+)*#;

  our $sub_module_spec_rx = qr/$qual_module_spec_rx|$unqual_sub_module_spec_rx/o;

  =back

  =head1 FUNCTIONS

  =head2 Basic module handling

  =over

  =item is_module_name(ARG)

  Returns a truth value indicating whether I<ARG> is a plain string
  satisfying Perl module name syntax as described for L</$module_name_rx>.

  =cut

  sub is_module_name($) { _is_string($_[0]) && $_[0] =~ /\A$module_name_rx\z/o }

  =item is_valid_module_name(ARG)

  Deprecated alias for L</is_module_name>.

  =cut

  *is_valid_module_name = \&is_module_name;

  =item check_module_name(ARG)

  Check whether I<ARG> is a plain string
  satisfying Perl module name syntax as described for L</$module_name_rx>.
  Return normally if it is, or C<die> if it is not.

  =cut

  sub check_module_name($) {
  	unless(&is_module_name) {
  		die +(_is_string($_[0]) ? "`$_[0]'" : "argument").
  			" is not a module name\n";
  	}
  }

  =item module_notional_filename(NAME)

  Generates a notional relative filename for a module, which is used in
  some Perl core interfaces.
  The I<NAME> is a string, which should be a valid module name (one or
  more C<::>-separated segments).  If it is not a valid name, the function
  C<die>s.

  The notional filename for the named module is generated and returned.
  This filename is always in Unix style, with C</> directory separators
  and a C<.pm> suffix.  This kind of filename can be used as an argument to
  C<require>, and is the key that appears in C<%INC> to identify a module,
  regardless of actual local filename syntax.

  =cut

  sub module_notional_filename($) {
  	&check_module_name;
  	my($name) = @_;
  	$name =~ s!::!/!g;
  	return $name.".pm";
  }

  =item require_module(NAME)

  This is essentially the bareword form of C<require>, in runtime form.
  The I<NAME> is a string, which should be a valid module name (one or
  more C<::>-separated segments).  If it is not a valid name, the function
  C<die>s.

  The module specified by I<NAME> is loaded, if it hasn't been already,
  in the manner of the bareword form of C<require>.  That means that a
  search through C<@INC> is performed, and a byte-compiled form of the
  module will be used if available.

  The return value is as for C<require>.  That is, it is the value returned
  by the module itself if the module is loaded anew, or C<1> if the module
  was already loaded.

  =cut

  # Don't "use constant" here, to avoid dependencies.
  BEGIN {
  	*_WORK_AROUND_HINT_LEAKAGE =
  		"$]" < 5.011 && !("$]" >= 5.009004 && "$]" < 5.010001)
  			? sub(){1} : sub(){0};
  	*_WORK_AROUND_BROKEN_MODULE_STATE = "$]" < 5.009 ? sub(){1} : sub(){0};
  }

  BEGIN { if(_WORK_AROUND_BROKEN_MODULE_STATE) { eval q{
  	sub Module::Runtime::__GUARD__::DESTROY {
  		delete $INC{$_[0]->[0]} if @{$_[0]};
  	}
  	1;
  }; die $@ if $@ ne ""; } }

  sub require_module($) {
  	# Localise %^H to work around [perl #68590], where the bug exists
  	# and this is a satisfactory workaround.  The bug consists of
  	# %^H state leaking into each required module, polluting the
  	# module's lexical state.
  	local %^H if _WORK_AROUND_HINT_LEAKAGE;
  	if(_WORK_AROUND_BROKEN_MODULE_STATE) {
  		my $notional_filename = &module_notional_filename;
  		my $guard = bless([ $notional_filename ],
  				"Module::Runtime::__GUARD__");
  		my $result = CORE::require($notional_filename);
  		pop @$guard;
  		return $result;
  	} else {
  		return scalar(CORE::require(&module_notional_filename));
  	}
  }

  =back

  =head2 Structured module use

  =over

  =item use_module(NAME[, VERSION])

  This is essentially C<use> in runtime form, but without the importing
  feature (which is fundamentally a compile-time thing).  The I<NAME> is
  handled just like in C<require_module> above: it must be a module name,
  and the named module is loaded as if by the bareword form of C<require>.

  If a I<VERSION> is specified, the C<VERSION> method of the loaded module is
  called with the specified I<VERSION> as an argument.  This normally serves to
  ensure that the version loaded is at least the version required.  This is
  the same functionality provided by the I<VERSION> parameter of C<use>.

  On success, the name of the module is returned.  This is unlike
  L</require_module>, and is done so that the entire call to L</use_module>
  can be used as a class name to call a constructor, as in the example in
  the synopsis.

  =cut

  sub use_module($;$) {
  	my($name, $version) = @_;
  	require_module($name);
  	$name->VERSION($version) if @_ >= 2;
  	return $name;
  }

  =item use_package_optimistically(NAME[, VERSION])

  This is an analogue of L</use_module> for the situation where there is
  uncertainty as to whether a package/class is defined in its own module
  or by some other means.  It attempts to arrange for the named package to
  be available, either by loading a module or by doing nothing and hoping.

  An attempt is made to load the named module (as if by the bareword form
  of C<require>).  If the module cannot be found then it is assumed that
  the package was actually already loaded by other means, and no error
  is signalled.  That's the optimistic bit.

  I<Warning:> this optional module loading is liable to cause unreliable
  behaviour, including security problems.  It interacts especially badly
  with having C<.> in C<@INC>, which was the default state of affairs in
  Perls prior to 5.25.11.  If a package is actually defined by some means
  other than a module, then applying this function to it causes a spurious
  attempt to load a module that is expected to be non-existent.  If a
  module actually exists under that name then it will be unintentionally
  loaded.  If C<.> is in C<@INC> and this code is ever run with the current
  directory being one writable by a malicious user (such as F</tmp>), then
  the malicious user can easily cause the victim to run arbitrary code, by
  creating a module file under the predictable spuriously-loaded name in the
  writable directory.  Generally, optional module loading should be avoided.

  This is mostly the same operation that is performed by the L<base> pragma
  to ensure that the specified base classes are available.  The behaviour
  of L<base> was simplified in version 2.18, and later improved in version
  2.20, and on both occasions this function changed to match.

  If a I<VERSION> is specified, the C<VERSION> method of the loaded package is
  called with the specified I<VERSION> as an argument.  This normally serves
  to ensure that the version loaded is at least the version required.
  On success, the name of the package is returned.  These aspects of the
  function work just like L</use_module>.

  =cut

  sub use_package_optimistically($;$) {
  	my($name, $version) = @_;
  	my $fn = module_notional_filename($name);
  	eval { local $SIG{__DIE__}; require_module($name); };
  	die $@ if $@ ne "" &&
  		($@ !~ /\ACan't locate \Q$fn\E .+ at \Q@{[__FILE__]}\E line/s ||
  		 $@ =~ /^Compilation\ failed\ in\ require
  			 \ at\ \Q@{[__FILE__]}\E\ line/xm);
  	$name->VERSION($version) if @_ >= 2;
  	return $name;
  }

  =back

  =head2 Module name composition

  =over

  =item is_module_spec(PREFIX, SPEC)

  Returns a truth value indicating
  whether I<SPEC> is valid input for L</compose_module_name>.
  See below for what that entails.  Whether a I<PREFIX> is supplied affects
  the validity of I<SPEC>, but the exact value of the prefix is unimportant,
  so this function treats I<PREFIX> as a truth value.

  =cut

  sub is_module_spec($$) {
  	my($prefix, $spec) = @_;
  	return _is_string($spec) &&
  		$spec =~ ($prefix ? qr/\A$sub_module_spec_rx\z/o :
  				    qr/\A$top_module_spec_rx\z/o);
  }

  =item is_valid_module_spec(PREFIX, SPEC)

  Deprecated alias for L</is_module_spec>.

  =cut

  *is_valid_module_spec = \&is_module_spec;

  =item check_module_spec(PREFIX, SPEC)

  Check whether I<SPEC> is valid input for L</compose_module_name>.
  Return normally if it is, or C<die> if it is not.

  =cut

  sub check_module_spec($$) {
  	unless(&is_module_spec) {
  		die +(_is_string($_[1]) ? "`$_[1]'" : "argument").
  			" is not a module specification\n";
  	}
  }

  =item compose_module_name(PREFIX, SPEC)

  This function is intended to make it more convenient for a user to specify
  a Perl module name at runtime.  Users have greater need for abbreviations
  and context-sensitivity than programmers, and Perl module names get a
  little unwieldy.  I<SPEC> is what the user specifies, and this function
  translates it into a module name in standard form, which it returns.

  I<SPEC> has syntax approximately that of a standard module name: it
  should consist of one or more name segments, each of which consists
  of one or more identifier characters.  However, C</> is permitted as a
  separator, in addition to the standard C<::>.  The two separators are
  entirely interchangeable.

  Additionally, if I<PREFIX> is not C<undef> then it must be a module
  name in standard form, and it is prefixed to the user-specified name.
  The user can inhibit the prefix addition by starting I<SPEC> with a
  separator (either C</> or C<::>).

  =cut

  sub compose_module_name($$) {
  	my($prefix, $spec) = @_;
  	check_module_name($prefix) if defined $prefix;
  	&check_module_spec;
  	if($spec =~ s#\A(?:/|::)##) {
  		# OK
  	} else {
  		$spec = $prefix."::".$spec if defined $prefix;
  	}
  	$spec =~ s#/#::#g;
  	return $spec;
  }

  =back

  =head1 BUGS

  On Perl versions 5.7.2 to 5.8.8, if C<require> is overridden by the
  C<CORE::GLOBAL> mechanism, it is likely to break the heuristics used by
  L</use_package_optimistically>, making it signal an error for a missing
  module rather than assume that it was already loaded.  From Perl 5.8.9
  onwards, and on 5.7.1 and earlier, this module can avoid being confused
  by such an override.  On the affected versions, a C<require> override
  might be installed by L<Lexical::SealRequireHints>, if something requires
  its bugfix but for some reason its XS implementation isn't available.

  =head1 SEE ALSO

  L<Lexical::SealRequireHints>,
  L<base>,
  L<perlfunc/require>,
  L<perlfunc/use>

  =head1 AUTHOR

  Andrew Main (Zefram) <zefram@fysh.org>

  =head1 COPYRIGHT

  Copyright (C) 2004, 2006, 2007, 2009, 2010, 2011, 2012, 2014, 2017
  Andrew Main (Zefram) <zefram@fysh.org>

  =head1 LICENSE

  This module is free software; you can redistribute it and/or modify it
  under the same terms as Perl itself.

  =cut

  1;
MODULE_RUNTIME

$fatpacked{"Moo.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MOO';
  package Moo;

  use Moo::_strictures;
  use Moo::_mro;
  use Moo::_Utils qw(
    _getglob
    _getstash
    _install_coderef
    _install_modifier
    _load_module
    _set_loaded
    _unimport_coderefs
  );
  use Scalar::Util qw(reftype);
  use Carp qw(croak);
  BEGIN {
    our @CARP_NOT = qw(
      Method::Generate::Constructor
      Method::Generate::Accessor
      Moo::sification
      Moo::_Utils
      Moo::Role
    );
  }

  our $VERSION = '2.003004';
  $VERSION =~ tr/_//d;

  require Moo::sification;
  Moo::sification->import;

  our %MAKERS;

  sub _install_tracked {
    my ($target, $name, $code) = @_;
    $MAKERS{$target}{exports}{$name} = $code;
    _install_coderef "${target}::${name}" => "Moo::${name}" => $code;
  }

  sub import {
    my $target = caller;
    my $class = shift;
    _set_loaded(caller);

    strict->import;
    warnings->import;

    if ($INC{'Role/Tiny.pm'} and Role::Tiny->is_role($target)) {
      croak "Cannot import Moo into a role";
    }
    $MAKERS{$target} ||= {};
    _install_tracked $target => extends => sub {
      $class->_set_superclasses($target, @_);
      $class->_maybe_reset_handlemoose($target);
      return;
    };
    _install_tracked $target => with => sub {
      require Moo::Role;
      Moo::Role->apply_roles_to_package($target, @_);
      $class->_maybe_reset_handlemoose($target);
    };
    _install_tracked $target => has => sub {
      my $name_proto = shift;
      my @name_proto = ref $name_proto eq 'ARRAY' ? @$name_proto : $name_proto;
      if (@_ % 2 != 0) {
        croak "Invalid options for " . join(', ', map "'$_'", @name_proto)
          . " attribute(s): even number of arguments expected, got " . scalar @_;
      }
      my %spec = @_;
      foreach my $name (@name_proto) {
        # Note that when multiple attributes specified, each attribute
        # needs a separate \%specs hashref
        my $spec_ref = @name_proto > 1 ? +{%spec} : \%spec;
        $class->_constructor_maker_for($target)
              ->register_attribute_specs($name, $spec_ref);
        $class->_accessor_maker_for($target)
              ->generate_method($target, $name, $spec_ref);
        $class->_maybe_reset_handlemoose($target);
      }
      return;
    };
    foreach my $type (qw(before after around)) {
      _install_tracked $target => $type => sub {
        _install_modifier($target, $type, @_);
        return;
      };
    }
    return if $MAKERS{$target}{is_class}; # already exported into this package
    my $stash = _getstash($target);
    my @not_methods = map +(
      !ref($_) ? *$_{CODE}||() : reftype($_) eq 'CODE' ? $_ : ()
    ), values %$stash;
    @{$MAKERS{$target}{not_methods}={}}{@not_methods} = @not_methods;
    $MAKERS{$target}{is_class} = 1;
    {
      no strict 'refs';
      @{"${target}::ISA"} = do {
        require Moo::Object; ('Moo::Object');
      } unless @{"${target}::ISA"};
    }
    if ($INC{'Moo/HandleMoose.pm'} && !$Moo::sification::disabled) {
      Moo::HandleMoose::inject_fake_metaclass_for($target);
    }
  }

  sub unimport {
    my $target = caller;
    _unimport_coderefs($target, $MAKERS{$target});
  }

  sub _set_superclasses {
    my $class = shift;
    my $target = shift;
    foreach my $superclass (@_) {
      _load_module($superclass);
      if ($INC{'Role/Tiny.pm'} && Role::Tiny->is_role($superclass)) {
        croak "Can't extend role '$superclass'";
      }
    }
    # Can't do *{...} = \@_ or 5.10.0's mro.pm stops seeing @ISA
    @{*{_getglob("${target}::ISA")}{ARRAY}} = @_;
    if (my $old = delete $Moo::MAKERS{$target}{constructor}) {
      $old->assert_constructor;
      delete _getstash($target)->{new};
      Moo->_constructor_maker_for($target)
         ->register_attribute_specs(%{$old->all_attribute_specs});
    }
    elsif (!$target->isa('Moo::Object')) {
      Moo->_constructor_maker_for($target);
    }
    $Moo::HandleMoose::MOUSE{$target} = [
      grep defined, map Mouse::Util::find_meta($_), @_
    ] if Mouse::Util->can('find_meta');
  }

  sub _maybe_reset_handlemoose {
    my ($class, $target) = @_;
    if ($INC{'Moo/HandleMoose.pm'} && !$Moo::sification::disabled) {
      Moo::HandleMoose::maybe_reinject_fake_metaclass_for($target);
    }
  }

  sub _accessor_maker_for {
    my ($class, $target) = @_;
    return unless $MAKERS{$target};
    $MAKERS{$target}{accessor} ||= do {
      my $maker_class = do {
        if (my $m = do {
              require Sub::Defer;
              if (my $defer_target =
                    (Sub::Defer::defer_info($target->can('new'))||[])->[0]
                ) {
                my ($pkg) = ($defer_target =~ /^(.*)::[^:]+$/);
                $MAKERS{$pkg} && $MAKERS{$pkg}{accessor};
              } else {
                undef;
              }
            }) {
          ref($m);
        } else {
          require Method::Generate::Accessor;
          'Method::Generate::Accessor'
        }
      };
      $maker_class->new;
    }
  }

  sub _constructor_maker_for {
    my ($class, $target) = @_;
    return unless $MAKERS{$target};
    $MAKERS{$target}{constructor} ||= do {
      require Method::Generate::Constructor;

      my %construct_opts = (
        package => $target,
        accessor_generator => $class->_accessor_maker_for($target),
        subconstructor_handler => (
          '      if ($Moo::MAKERS{$class}) {'."\n"
          .'        if ($Moo::MAKERS{$class}{constructor}) {'."\n"
          .'          package '.$target.';'."\n"
          .'          return $invoker->SUPER::new(@_);'."\n"
          .'        }'."\n"
          .'        '.$class.'->_constructor_maker_for($class);'."\n"
          .'        return $invoker->new(@_)'.";\n"
          .'      } elsif ($INC{"Moose.pm"} and my $meta = Class::MOP::get_metaclass_by_name($class)) {'."\n"
          .'        return $meta->new_object('."\n"
          .'          $class->can("BUILDARGS") ? $class->BUILDARGS(@_)'."\n"
          .'                      : $class->Moo::Object::BUILDARGS(@_)'."\n"
          .'        );'."\n"
          .'      }'."\n"
        ),
      );

      my $con;
      my @isa = @{mro::get_linear_isa($target)};
      shift @isa;
      no strict 'refs';
      if (my ($parent_new) = grep +(defined &{$_.'::new'}), @isa) {
        if ($parent_new eq 'Moo::Object') {
          # no special constructor needed
        }
        elsif (my $makers = $MAKERS{$parent_new}) {
          $con = $makers->{constructor};
          $construct_opts{construction_string} = $con->construction_string
            if $con;
        }
        elsif ($parent_new->can('BUILDALL')) {
          $construct_opts{construction_builder} = sub {
            my $inv = $target->can('BUILDARGS') ? '' : 'Moo::Object::';
            'do {'
            .'  my $args = $class->'.$inv.'BUILDARGS(@_);'
            .'  $args->{__no_BUILD__} = 1;'
            .'  $invoker->'.$target.'::SUPER::new($args);'
            .'}'
          };
        }
        else {
          $construct_opts{construction_builder} = sub {
            '$invoker->'.$target.'::SUPER::new('
              .($target->can('FOREIGNBUILDARGS') ?
                '$class->FOREIGNBUILDARGS(@_)' : '@_')
              .')'
          };
        }
      }
      ($con ? ref($con) : 'Method::Generate::Constructor')
        ->new(%construct_opts)
        ->install_delayed
        ->register_attribute_specs(%{$con?$con->all_attribute_specs:{}})
    }
  }

  sub _concrete_methods_of {
    my ($me, $class) = @_;
    my $makers = $MAKERS{$class};
    # grab class symbol table
    my $stash = _getstash($class);
    # reverse so our keys become the values (captured coderefs) in case
    # they got copied or re-used since
    my $not_methods = { reverse %{$makers->{not_methods}||{}} };
    +{
      # grab all code entries that aren't in the not_methods list
      map {;
        no strict 'refs';
        my $code = exists &{"${class}::$_"} ? \&{"${class}::$_"} : undef;
        ( ! $code or exists $not_methods->{$code} ) ? () : ($_ => $code)
      } grep +(!ref($stash->{$_}) || reftype($stash->{$_}) eq 'CODE'), keys %$stash
    };
  }

  1;
  __END__

  =pod

  =encoding utf-8

  =head1 NAME

  Moo - Minimalist Object Orientation (with Moose compatibility)

  =head1 SYNOPSIS

    package Cat::Food;

    use Moo;
    use strictures 2;
    use namespace::clean;

    sub feed_lion {
      my $self = shift;
      my $amount = shift || 1;

      $self->pounds( $self->pounds - $amount );
    }

    has taste => (
      is => 'ro',
    );

    has brand => (
      is  => 'ro',
      isa => sub {
        die "Only SWEET-TREATZ supported!" unless $_[0] eq 'SWEET-TREATZ'
      },
    );

    has pounds => (
      is  => 'rw',
      isa => sub { die "$_[0] is too much cat food!" unless $_[0] < 15 },
    );

    1;

  And elsewhere:

    my $full = Cat::Food->new(
        taste  => 'DELICIOUS.',
        brand  => 'SWEET-TREATZ',
        pounds => 10,
    );

    $full->feed_lion;

    say $full->pounds;

  =head1 DESCRIPTION

  C<Moo> is an extremely light-weight Object Orientation system. It allows one to
  concisely define objects and roles with a convenient syntax that avoids the
  details of Perl's object system.  C<Moo> contains a subset of L<Moose> and is
  optimised for rapid startup.

  C<Moo> avoids depending on any XS modules to allow for simple deployments.  The
  name C<Moo> is based on the idea that it provides almost -- but not quite --
  two thirds of L<Moose>.

  Unlike L<Mouse> this module does not aim at full compatibility with
  L<Moose>'s surface syntax, preferring instead to provide full interoperability
  via the metaclass inflation capabilities described in L</MOO AND MOOSE>.

  For a full list of the minor differences between L<Moose> and L<Moo>'s surface
  syntax, see L</INCOMPATIBILITIES WITH MOOSE>.

  =head1 WHY MOO EXISTS

  If you want a full object system with a rich Metaprotocol, L<Moose> is
  already wonderful.

  But if you don't want to use L<Moose>, you may not want "less metaprotocol"
  like L<Mouse> offers, but you probably want "no metaprotocol", which is what
  Moo provides. C<Moo> is ideal for some situations where deployment or startup
  time precludes using L<Moose> and L<Mouse>:

  =over 2

  =item a command line or CGI script where fast startup is essential

  =item code designed to be deployed as a single file via L<App::FatPacker>

  =item a CPAN module that may be used by others in the above situations

  =back

  C<Moo> maintains transparent compatibility with L<Moose> so if you install and
  load L<Moose> you can use Moo classes and roles in L<Moose> code without
  modification.

  Moo -- Minimal Object Orientation -- aims to make it smooth to upgrade to
  L<Moose> when you need more than the minimal features offered by Moo.

  =head1 MOO AND MOOSE

  If L<Moo> detects L<Moose> being loaded, it will automatically register
  metaclasses for your L<Moo> and L<Moo::Role> packages, so you should be able
  to use them in L<Moose> code without modification.

  L<Moo> will also create L<Moose type constraints|Moose::Manual::Types> for
  L<Moo> classes and roles, so that in Moose classes C<< isa => 'MyMooClass' >>
  and C<< isa => 'MyMooRole' >> work the same as for L<Moose> classes and roles.

  Extending a L<Moose> class or consuming a L<Moose::Role> will also work.

  Extending a L<Mouse> class or consuming a L<Mouse::Role> will also work. But
  note that we don't provide L<Mouse> metaclasses or metaroles so the other way
  around doesn't work. This feature exists for L<Any::Moose> users porting to
  L<Moo>; enabling L<Mouse> users to use L<Moo> classes is not a priority for us.

  This means that there is no need for anything like L<Any::Moose> for Moo
  code - Moo and Moose code should simply interoperate without problem. To
  handle L<Mouse> code, you'll likely need an empty Moo role or class consuming
  or extending the L<Mouse> stuff since it doesn't register true L<Moose>
  metaclasses like L<Moo> does.

  If you need to disable the metaclass creation, add:

    no Moo::sification;

  to your code before Moose is loaded, but bear in mind that this switch is
  global and turns the mechanism off entirely so don't put this in library code.

  =head1 MOO AND CLASS::XSACCESSOR

  If a new enough version of L<Class::XSAccessor> is available, it will be used
  to generate simple accessors, readers, and writers for better performance.
  Simple accessors are those without lazy defaults, type checks/coercions, or
  triggers.  Simple readers are those without lazy defaults. Readers and writers
  generated by L<Class::XSAccessor> will behave slightly differently: they will
  reject attempts to call them with the incorrect number of parameters.

  =head1 MOO VERSUS ANY::MOOSE

  L<Any::Moose> will load L<Mouse> normally, and L<Moose> in a program using
  L<Moose> - which theoretically allows you to get the startup time of L<Mouse>
  without disadvantaging L<Moose> users.

  Sadly, this doesn't entirely work, since the selection is load order dependent
  - L<Moo>'s metaclass inflation system explained above in L</MOO AND MOOSE> is
  significantly more reliable.

  So if you want to write a CPAN module that loads fast or has only pure perl
  dependencies but is also fully usable by L<Moose> users, you should be using
  L<Moo>.

  For a full explanation, see the article
  L<http://shadow.cat/blog/matt-s-trout/moo-versus-any-moose> which explains
  the differing strategies in more detail and provides a direct example of
  where L<Moo> succeeds and L<Any::Moose> fails.

  =head1 PUBLIC METHODS

  Moo provides several methods to any class using it.

  =head2 new

    Foo::Bar->new( attr1 => 3 );

  or

    Foo::Bar->new({ attr1 => 3 });

  The constructor for the class.  By default it will accept attributes either as a
  hashref, or a list of key value pairs.  This can be customized with the
  L</BUILDARGS> method.

  =head2 does

    if ($foo->does('Some::Role1')) {
      ...
    }

  Returns true if the object composes in the passed role.

  =head2 DOES

    if ($foo->DOES('Some::Role1') || $foo->DOES('Some::Class1')) {
      ...
    }

  Similar to L</does>, but will also return true for both composed roles and
  superclasses.

  =head2 meta

    my $meta = Foo::Bar->meta;
    my @methods = $meta->get_method_list;

  Returns an object that will behave as if it is a
  L<Moose metaclass|Moose::Meta::Class> object for the class. If you call
  anything other than C<make_immutable> on it, the object will be transparently
  upgraded to a genuine L<Moose::Meta::Class> instance, loading Moose in the
  process if required. C<make_immutable> itself is a no-op, since we generate
  metaclasses that are already immutable, and users converting from Moose had
  an unfortunate tendency to accidentally load Moose by calling it.

  =head1 LIFECYCLE METHODS

  There are several methods that you can define in your class to control
  construction and destruction of objects.  They should be used rather than trying
  to modify C<new> or C<DESTROY> yourself.

  =head2 BUILDARGS

    around BUILDARGS => sub {
      my ( $orig, $class, @args ) = @_;

      return { attr1 => $args[0] }
        if @args == 1 && !ref $args[0];

      return $class->$orig(@args);
    };

    Foo::Bar->new( 3 );

  This class method is used to transform the arguments to C<new> into a hash
  reference of attribute values.

  The default implementation accepts a hash or hash reference of named parameters.
  If it receives a single argument that isn't a hash reference it will throw an
  error.

  You can override this method in your class to handle other types of options
  passed to the constructor.

  This method should always return a hash reference of named options.

  =head2 FOREIGNBUILDARGS

    sub FOREIGNBUILDARGS {
      my ( $class, $options ) = @_;
      return $options->{foo};
    }

  If you are inheriting from a non-Moo class, the arguments passed to the parent
  class constructor can be manipulated by defining a C<FOREIGNBUILDARGS> method.
  It will receive the same arguments as L</BUILDARGS>, and should return a list
  of arguments to pass to the parent class constructor.

  =head2 BUILD

    sub BUILD {
      my ($self, $args) = @_;
      die "foo and bar cannot be used at the same time"
        if exists $args->{foo} && exists $args->{bar};
    }

  On object creation, any C<BUILD> methods in the class's inheritance hierarchy
  will be called on the object and given the results of L</BUILDARGS>.  They each
  will be called in order from the parent classes down to the child, and thus
  should not themselves call the parent's method.  Typically this is used for
  object validation or possibly logging.

  =head2 DEMOLISH

    sub DEMOLISH {
      my ($self, $in_global_destruction) = @_;
      ...
    }

  When an object is destroyed, any C<DEMOLISH> methods in the inheritance
  hierarchy will be called on the object.  They are given boolean to inform them
  if global destruction is in progress, and are called from the child class upwards
  to the parent.  This is similar to L</BUILD> methods but in the opposite order.

  Note that this is implemented by a C<DESTROY> method, which is only created on
  on the first construction of an object of your class.  This saves on overhead for
  classes that are never instantiated or those without C<DEMOLISH> methods.  If you
  try to define your own C<DESTROY>, this will cause undefined results.

  =head1 IMPORTED SUBROUTINES

  =head2 extends

    extends 'Parent::Class';

  Declares a base class. Multiple superclasses can be passed for multiple
  inheritance but please consider using L<roles|Moo::Role> instead.  The class
  will be loaded but no errors will be triggered if the class can't be found and
  there are already subs in the class.

  Calling extends more than once will REPLACE your superclasses, not add to
  them like 'use base' would.

  =head2 with

    with 'Some::Role1';

  or

    with 'Some::Role1', 'Some::Role2';

  Composes one or more L<Moo::Role> (or L<Role::Tiny>) roles into the current
  class.  An error will be raised if these roles cannot be composed because they
  have conflicting method definitions.  The roles will be loaded using the same
  mechanism as C<extends> uses.

  =head2 has

    has attr => (
      is => 'ro',
    );

  Declares an attribute for the class.

    package Foo;
    use Moo;
    has 'attr' => (
      is => 'ro'
    );

    package Bar;
    use Moo;
    extends 'Foo';
    has '+attr' => (
      default => sub { "blah" },
    );

  Using the C<+> notation, it's possible to override an attribute.

    has [qw(attr1 attr2 attr3)] => (
      is => 'ro',
    );

  Using an arrayref with multiple attribute names, it's possible to declare
  multiple attributes with the same options.

  The options for C<has> are as follows:

  =over 2

  =item C<is>

  B<required>, may be C<ro>, C<lazy>, C<rwp> or C<rw>.

  C<ro> stands for "read-only" and generates an accessor that dies if you attempt
  to write to it - i.e.  a getter only - by defaulting C<reader> to the name of
  the attribute.

  C<lazy> generates a reader like C<ro>, but also sets C<lazy> to 1 and
  C<builder> to C<_build_${attribute_name}> to allow on-demand generated
  attributes.  This feature was my attempt to fix my incompetence when
  originally designing C<lazy_build>, and is also implemented by
  L<MooseX::AttributeShortcuts>. There is, however, nothing to stop you
  using C<lazy> and C<builder> yourself with C<rwp> or C<rw> - it's just that
  this isn't generally a good idea so we don't provide a shortcut for it.

  C<rwp> stands for "read-write protected" and generates a reader like C<ro>, but
  also sets C<writer> to C<_set_${attribute_name}> for attributes that are
  designed to be written from inside of the class, but read-only from outside.
  This feature comes from L<MooseX::AttributeShortcuts>.

  C<rw> stands for "read-write" and generates a normal getter/setter by
  defaulting the C<accessor> to the name of the attribute specified.

  =item C<isa>

  Takes a coderef which is used to validate the attribute.  Unlike L<Moose>, Moo
  does not include a basic type system, so instead of doing C<< isa => 'Num' >>,
  one should do

    use Scalar::Util qw(looks_like_number);
    ...
    isa => sub {
      die "$_[0] is not a number!" unless looks_like_number $_[0]
    },

  Note that the return value for C<isa> is discarded. Only if the sub dies does
  type validation fail.

  L<Sub::Quote aware|/SUB QUOTE AWARE>

  Since L<Moo> does B<not> run the C<isa> check before C<coerce> if a coercion
  subroutine has been supplied, C<isa> checks are not structural to your code
  and can, if desired, be omitted on non-debug builds (although if this results
  in an uncaught bug causing your program to break, the L<Moo> authors guarantee
  nothing except that you get to keep both halves).

  If you want L<Moose> compatible or L<MooseX::Types> style named types, look at
  L<Type::Tiny>.

  To cause your C<isa> entries to be automatically mapped to named
  L<Moose::Meta::TypeConstraint> objects (rather than the default behaviour
  of creating an anonymous type), set:

    $Moo::HandleMoose::TYPE_MAP{$isa_coderef} = sub {
      require MooseX::Types::Something;
      return MooseX::Types::Something::TypeName();
    };

  Note that this example is purely illustrative; anything that returns a
  L<Moose::Meta::TypeConstraint> object or something similar enough to it to
  make L<Moose> happy is fine.

  =item C<coerce>

  Takes a coderef which is meant to coerce the attribute.  The basic idea is to
  do something like the following:

   coerce => sub {
     $_[0] % 2 ? $_[0] : $_[0] + 1
   },

  Note that L<Moo> will always execute your coercion: this is to permit
  C<isa> entries to be used purely for bug trapping, whereas coercions are
  always structural to your code. We do, however, apply any supplied C<isa>
  check after the coercion has run to ensure that it returned a valid value.

  L<Sub::Quote aware|/SUB QUOTE AWARE>

  If the C<isa> option is a blessed object providing a C<coerce> or
  C<coercion> method, then the C<coerce> option may be set to just C<1>.

  =item C<handles>

  Takes a string

    handles => 'RobotRole'

  Where C<RobotRole> is a L<role|Moo::Role> that defines an interface which
  becomes the list of methods to handle.

  Takes a list of methods

    handles => [ qw( one two ) ]

  Takes a hashref

    handles => {
      un => 'one',
    }

  =item C<trigger>

  Takes a coderef which will get called any time the attribute is set. This
  includes the constructor, but not default or built values. The coderef will be
  invoked against the object with the new value as an argument.

  If you set this to just C<1>, it generates a trigger which calls the
  C<_trigger_${attr_name}> method on C<$self>. This feature comes from
  L<MooseX::AttributeShortcuts>.

  Note that Moose also passes the old value, if any; this feature is not yet
  supported.

  L<Sub::Quote aware|/SUB QUOTE AWARE>

  =item C<default>

  Takes a coderef which will get called with $self as its only argument to
  populate an attribute if no value for that attribute was supplied to the
  constructor. Alternatively, if the attribute is lazy, C<default> executes when
  the attribute is first retrieved if no value has yet been provided.

  If a simple scalar is provided, it will be inlined as a string. Any non-code
  reference (hash, array) will result in an error - for that case instead use
  a code reference that returns the desired value.

  Note that if your default is fired during new() there is no guarantee that
  other attributes have been populated yet so you should not rely on their
  existence.

  L<Sub::Quote aware|/SUB QUOTE AWARE>

  =item C<predicate>

  Takes a method name which will return true if an attribute has a value.

  If you set this to just C<1>, the predicate is automatically named
  C<has_${attr_name}> if your attribute's name does not start with an
  underscore, or C<_has_${attr_name_without_the_underscore}> if it does.
  This feature comes from L<MooseX::AttributeShortcuts>.

  =item C<builder>

  Takes a method name which will be called to create the attribute - functions
  exactly like default except that instead of calling

    $default->($self);

  Moo will call

    $self->$builder;

  The following features come from L<MooseX::AttributeShortcuts>:

  If you set this to just C<1>, the builder is automatically named
  C<_build_${attr_name}>.

  If you set this to a coderef or code-convertible object, that variable will be
  installed under C<$class::_build_${attr_name}> and the builder set to the same
  name.

  =item C<clearer>

  Takes a method name which will clear the attribute.

  If you set this to just C<1>, the clearer is automatically named
  C<clear_${attr_name}> if your attribute's name does not start with an
  underscore, or C<_clear_${attr_name_without_the_underscore}> if it does.
  This feature comes from L<MooseX::AttributeShortcuts>.

  B<NOTE:> If the attribute is C<lazy>, it will be regenerated from C<default> or
  C<builder> the next time it is accessed. If it is not lazy, it will be C<undef>.

  =item C<lazy>

  B<Boolean>.  Set this if you want values for the attribute to be grabbed
  lazily.  This is usually a good idea if you have a L</builder> which requires
  another attribute to be set.

  =item C<required>

  B<Boolean>.  Set this if the attribute must be passed on object instantiation.

  =item C<reader>

  The name of the method that returns the value of the attribute.  If you like
  Java style methods, you might set this to C<get_foo>

  =item C<writer>

  The value of this attribute will be the name of the method to set the value of
  the attribute.  If you like Java style methods, you might set this to
  C<set_foo>.

  =item C<weak_ref>

  B<Boolean>.  Set this if you want the reference that the attribute contains to
  be weakened. Use this when circular references, which cause memory leaks, are
  possible.

  =item C<init_arg>

  Takes the name of the key to look for at instantiation time of the object.  A
  common use of this is to make an underscored attribute have a non-underscored
  initialization name. C<undef> means that passing the value in on instantiation
  is ignored.

  =item C<moosify>

  Takes either a coderef or array of coderefs which is meant to transform the
  given attributes specifications if necessary when upgrading to a Moose role or
  class. You shouldn't need this by default, but is provided as a means of
  possible extensibility.

  =back

  =head2 before

    before foo => sub { ... };

  See L<< Class::Method::Modifiers/before method(s) => sub { ... }; >> for full
  documentation.

  =head2 around

    around foo => sub { ... };

  See L<< Class::Method::Modifiers/around method(s) => sub { ... }; >> for full
  documentation.

  =head2 after

    after foo => sub { ... };

  See L<< Class::Method::Modifiers/after method(s) => sub { ... }; >> for full
  documentation.

  =head1 SUB QUOTE AWARE

  L<Sub::Quote/quote_sub> allows us to create coderefs that are "inlineable,"
  giving us a handy, XS-free speed boost.  Any option that is L<Sub::Quote>
  aware can take advantage of this.

  To do this, you can write

    use Sub::Quote;

    use Moo;
    use namespace::clean;

    has foo => (
      is => 'ro',
      isa => quote_sub(q{ die "Not <3" unless $_[0] < 3 })
    );

  which will be inlined as

    do {
      local @_ = ($_[0]->{foo});
      die "Not <3" unless $_[0] < 3;
    }

  or to avoid localizing @_,

    has foo => (
      is => 'ro',
      isa => quote_sub(q{ my ($val) = @_; die "Not <3" unless $val < 3 })
    );

  which will be inlined as

    do {
      my ($val) = ($_[0]->{foo});
      die "Not <3" unless $val < 3;
    }

  See L<Sub::Quote> for more information, including how to pass lexical
  captures that will also be compiled into the subroutine.

  =head1 CLEANING UP IMPORTS

  L<Moo> will not clean up imported subroutines for you; you will have
  to do that manually. The recommended way to do this is to declare your
  imports first, then C<use Moo>, then C<use namespace::clean>.
  Anything imported before L<namespace::clean> will be scrubbed.
  Anything imported or declared after will be still be available.

    package Record;

    use Digest::MD5 qw(md5_hex);

    use Moo;
    use namespace::clean;

    has name => (is => 'ro', required => 1);
    has id => (is => 'lazy');
    sub _build_id {
      my ($self) = @_;
      return md5_hex($self->name);
    }

    1;

  If you were to import C<md5_hex> after L<namespace::clean> you would
  be able to call C<< ->md5_hex() >> on your C<Record> instances (and it
  probably wouldn't do what you expect!).

  L<Moo::Role>s behave slightly differently.  Since their methods are
  composed into the consuming class, they can do a little more for you
  automatically.  As long as you declare your imports before calling
  C<use Moo::Role>, those imports and the ones L<Moo::Role> itself
  provides will not be composed into consuming classes so there's usually
  no need to use L<namespace::clean>.

  B<On L<namespace::autoclean>:> Older versions of L<namespace::autoclean> would
  inflate Moo classes to full L<Moose> classes, losing the benefits of Moo.  If
  you want to use L<namespace::autoclean> with a Moo class, make sure you are
  using version 0.16 or newer.

  =head1 INCOMPATIBILITIES WITH MOOSE

  There is no built-in type system.  C<isa> is verified with a coderef; if you
  need complex types, L<Type::Tiny> can provide types, type libraries, and
  will work seamlessly with both L<Moo> and L<Moose>.  L<Type::Tiny> can be
  considered the successor to L<MooseX::Types> and provides a similar API, so
  that you can write

    use Types::Standard qw(Int);
    has days_to_live => (is => 'ro', isa => Int);

  C<initializer> is not supported in core since the author considers it to be a
  bad idea and Moose best practices recommend avoiding it. Meanwhile C<trigger> or
  C<coerce> are more likely to be able to fulfill your needs.

  There is no meta object.  If you need this level of complexity you need
  L<Moose> - Moo is small because it explicitly does not provide a metaprotocol.
  However, if you load L<Moose>, then

    Class::MOP::class_of($moo_class_or_role)

  will return an appropriate metaclass pre-populated by L<Moo>.

  No support for C<super>, C<override>, C<inner>, or C<augment> - the author
  considers augment to be a bad idea, and override can be translated:

    override foo => sub {
      ...
      super();
      ...
    };

    around foo => sub {
      my ($orig, $self) = (shift, shift);
      ...
      $self->$orig(@_);
      ...
    };

  The C<dump> method is not provided by default. The author suggests loading
  L<Devel::Dwarn> into C<main::> (via C<perl -MDevel::Dwarn ...> for example) and
  using C<$obj-E<gt>$::Dwarn()> instead.

  L</default> only supports coderefs and plain scalars, because passing a hash
  or array reference as a default is almost always incorrect since the value is
  then shared between all objects using that default.

  C<lazy_build> is not supported; you are instead encouraged to use the
  C<< is => 'lazy' >> option supported by L<Moo> and
  L<MooseX::AttributeShortcuts>.

  C<auto_deref> is not supported since the author considers it a bad idea and
  it has been considered best practice to avoid it for some time.

  C<documentation> will show up in a L<Moose> metaclass created from your class
  but is otherwise ignored. Then again, L<Moose> ignores it as well, so this
  is arguably not an incompatibility.

  Since C<coerce> does not require C<isa> to be defined but L<Moose> does
  require it, the metaclass inflation for coerce alone is a trifle insane
  and if you attempt to subtype the result will almost certainly break.

  Handling of warnings: when you C<use Moo> we enable strict and warnings, in a
  similar way to Moose. The authors recommend the use of C<strictures>, which
  enables FATAL warnings, and several extra pragmas when used in development:
  L<indirect>, L<multidimensional>, and L<bareword::filehandles>.

  Additionally, L<Moo> supports a set of attribute option shortcuts intended to
  reduce common boilerplate.  The set of shortcuts is the same as in the L<Moose>
  module L<MooseX::AttributeShortcuts> as of its version 0.009+.  So if you:

    package MyClass;
    use Moo;
    use strictures 2;

  The nearest L<Moose> invocation would be:

    package MyClass;

    use Moose;
    use warnings FATAL => "all";
    use MooseX::AttributeShortcuts;

  or, if you're inheriting from a non-Moose class,

    package MyClass;

    use Moose;
    use MooseX::NonMoose;
    use warnings FATAL => "all";
    use MooseX::AttributeShortcuts;

  Finally, Moose requires you to call

    __PACKAGE__->meta->make_immutable;

  at the end of your class to get an inlined (i.e. not horribly slow)
  constructor. Moo does it automatically the first time ->new is called
  on your class. (C<make_immutable> is a no-op in Moo to ease migration.)

  An extension L<MooX::late> exists to ease translating Moose packages
  to Moo by providing a more Moose-like interface.

  =head1 SUPPORT

  Users' IRC: #moose on irc.perl.org

  =for :html
  L<(click for instant chatroom login)|http://chat.mibbit.com/#moose@irc.perl.org>

  Development and contribution IRC: #web-simple on irc.perl.org

  =for :html
  L<(click for instant chatroom login)|http://chat.mibbit.com/#web-simple@irc.perl.org>

  Bugtracker: L<https://rt.cpan.org/Public/Dist/Display.html?Name=Moo>

  Git repository: L<git://github.com/moose/Moo.git>

  Git browser: L<https://github.com/moose/Moo>

  =head1 AUTHOR

  mst - Matt S. Trout (cpan:MSTROUT) <mst@shadowcat.co.uk>

  =head1 CONTRIBUTORS

  dg - David Leadbeater (cpan:DGL) <dgl@dgl.cx>

  frew - Arthur Axel "fREW" Schmidt (cpan:FREW) <frioux@gmail.com>

  hobbs - Andrew Rodland (cpan:ARODLAND) <arodland@cpan.org>

  jnap - John Napiorkowski (cpan:JJNAPIORK) <jjn1056@yahoo.com>

  ribasushi - Peter Rabbitson (cpan:RIBASUSHI) <ribasushi@cpan.org>

  chip - Chip Salzenberg (cpan:CHIPS) <chip@pobox.com>

  ajgb - Alex J. G. Burzyński (cpan:AJGB) <ajgb@cpan.org>

  doy - Jesse Luehrs (cpan:DOY) <doy at tozt dot net>

  perigrin - Chris Prather (cpan:PERIGRIN) <chris@prather.org>

  Mithaldu - Christian Walde (cpan:MITHALDU) <walde.christian@googlemail.com>

  ilmari - Dagfinn Ilmari Mannsåker (cpan:ILMARI) <ilmari@ilmari.org>

  tobyink - Toby Inkster (cpan:TOBYINK) <tobyink@cpan.org>

  haarg - Graham Knop (cpan:HAARG) <haarg@cpan.org>

  mattp - Matt Phillips (cpan:MATTP) <mattp@cpan.org>

  bluefeet - Aran Deltac (cpan:BLUEFEET) <bluefeet@gmail.com>

  bubaflub - Bob Kuo (cpan:BUBAFLUB) <bubaflub@cpan.org>

  ether = Karen Etheridge (cpan:ETHER) <ether@cpan.org>

  =head1 COPYRIGHT

  Copyright (c) 2010-2015 the Moo L</AUTHOR> and L</CONTRIBUTORS>
  as listed above.

  =head1 LICENSE

  This library is free software and may be distributed under the same terms
  as perl itself. See L<http://dev.perl.org/licenses/>.

  =cut
MOO

$fatpacked{"Moo/HandleMoose.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MOO_HANDLEMOOSE';
  package Moo::HandleMoose;
  use Moo::_strictures;
  use Moo::_Utils qw(_getstash);
  use Sub::Quote qw(quotify);
  use Carp qw(croak);

  our %TYPE_MAP;

  our $SETUP_DONE;

  sub import { return if $SETUP_DONE; inject_all(); $SETUP_DONE = 1; }

  sub inject_all {
    croak "Can't inflate Moose metaclass with Moo::sification disabled"
      if $Moo::sification::disabled;
    require Class::MOP;
    inject_fake_metaclass_for($_)
      for grep $_ ne 'Moo::Object', keys %Moo::MAKERS;
    inject_fake_metaclass_for($_) for keys %Moo::Role::INFO;
    require Moose::Meta::Method::Constructor;
    @Moo::HandleMoose::FakeConstructor::ISA = 'Moose::Meta::Method::Constructor';
    @Moo::HandleMoose::FakeMeta::ISA = 'Moose::Meta::Method::Meta';
  }

  sub maybe_reinject_fake_metaclass_for {
    my ($name) = @_;
    our %DID_INJECT;
    if (delete $DID_INJECT{$name}) {
      unless ($Moo::Role::INFO{$name}) {
        Moo->_constructor_maker_for($name)->install_delayed;
      }
      inject_fake_metaclass_for($name);
    }
  }

  sub inject_fake_metaclass_for {
    my ($name) = @_;
    require Class::MOP;
    require Moo::HandleMoose::FakeMetaClass;
    Class::MOP::store_metaclass_by_name(
      $name, bless({ name => $name }, 'Moo::HandleMoose::FakeMetaClass')
    );
    require Moose::Util::TypeConstraints;
    if ($Moo::Role::INFO{$name}) {
      Moose::Util::TypeConstraints::find_or_create_does_type_constraint($name);
    } else {
      Moose::Util::TypeConstraints::find_or_create_isa_type_constraint($name);
    }
  }

  {
    package Moo::HandleMoose::FakeConstructor;

    sub _uninlined_body { \&Moose::Object::new }
  }

  sub inject_real_metaclass_for {
    my ($name) = @_;
    our %DID_INJECT;
    return Class::MOP::get_metaclass_by_name($name) if $DID_INJECT{$name};
    require Moose; require Moo; require Moo::Role; require Scalar::Util;
    require Sub::Defer;
    Class::MOP::remove_metaclass_by_name($name);
    my ($am_role, $am_class, $meta, $attr_specs, $attr_order) = do {
      if (my $info = $Moo::Role::INFO{$name}) {
        my @attr_info = @{$info->{attributes}||[]};
        (1, 0, Moose::Meta::Role->initialize($name),
         { @attr_info },
         [ @attr_info[grep !($_ % 2), 0..$#attr_info] ]
        )
      } elsif ( my $cmaker = Moo->_constructor_maker_for($name) ) {
        my $specs = $cmaker->all_attribute_specs;
        (0, 1, Moose::Meta::Class->initialize($name), $specs,
         [ sort { $specs->{$a}{index} <=> $specs->{$b}{index} } keys %$specs ]
        );
      } else {
         # This codepath is used if $name does not exist in $Moo::MAKERS
         (0, 0, Moose::Meta::Class->initialize($name), {}, [] )
      }
    };

    {
      local $DID_INJECT{$name} = 1;
      foreach my $spec (values %$attr_specs) {
        if (my $inflators = delete $spec->{moosify}) {
          $_->($spec) for @$inflators;
        }
      }

      my %methods
        = %{($am_role ? 'Moo::Role' : 'Moo')->_concrete_methods_of($name)};

      # if stuff gets added afterwards, _maybe_reset_handlemoose should
      # trigger the recreation of the metaclass but we need to ensure the
      # Moo::Role cache is cleared so we don't confuse Moo itself.
      if (my $info = $Moo::Role::INFO{$name}) {
        delete $info->{methods};
      }

      # needed to ensure the method body is stable and get things named
      $methods{$_} = Sub::Defer::undefer_sub($methods{$_})
        for
          grep $_ ne 'new',
          keys %methods;
      my @attrs;
      {
        # This local is completely not required for roles but harmless
        local @{_getstash($name)}{keys %methods};
        my %seen_name;
        foreach my $attr_name (@$attr_order) {
          $seen_name{$attr_name} = 1;
          my %spec = %{$attr_specs->{$attr_name}};
          my %spec_map = (
            map { $_->name => $_->init_arg||$_->name }
            (
              (grep { $_->has_init_arg }
                $meta->attribute_metaclass->meta->get_all_attributes),
              grep { exists($_->{init_arg}) ? defined($_->init_arg) : 1 }
              map {
                my $meta = Moose::Util::resolve_metatrait_alias('Attribute', $_)
                            ->meta;
                map $meta->get_attribute($_), $meta->get_attribute_list
              }  @{$spec{traits}||[]}
            )
          );
          # have to hard code this because Moose's role meta-model is lacking
          $spec_map{traits} ||= 'traits';

          $spec{is} = 'ro' if $spec{is} eq 'lazy' or $spec{is} eq 'rwp';
          my $coerce = $spec{coerce};
          if (my $isa = $spec{isa}) {
            my $tc = $spec{isa} = do {
              if (my $mapped = $TYPE_MAP{$isa}) {
                my $type = $mapped->();
                unless ( Scalar::Util::blessed($type)
                    && $type->isa("Moose::Meta::TypeConstraint") ) {
                  croak "error inflating attribute '$attr_name' for package '$name': "
                    ."\$TYPE_MAP{$isa} did not return a valid type constraint'";
                }
                $coerce ? $type->create_child_type(name => $type->name) : $type;
              } else {
                Moose::Meta::TypeConstraint->new(
                  constraint => sub { eval { &$isa; 1 } }
                );
              }
            };
            if ($coerce) {
              $tc->coercion(Moose::Meta::TypeCoercion->new)
                ->_compiled_type_coercion($coerce);
              $spec{coerce} = 1;
            }
          } elsif ($coerce) {
            my $attr = quotify($attr_name);
            my $tc = Moose::Meta::TypeConstraint->new(
                      constraint => sub { die "This is not going to work" },
                      inlined => sub {
                          'my $r = $_[42]{'.$attr.'}; $_[42]{'.$attr.'} = 1; $r'
                      },
                    );
            $tc->coercion(Moose::Meta::TypeCoercion->new)
              ->_compiled_type_coercion($coerce);
            $spec{isa} = $tc;
            $spec{coerce} = 1;
          }
          %spec =
            map { $spec_map{$_} => $spec{$_} }
            grep { exists $spec_map{$_} }
            keys %spec;
          push @attrs, $meta->add_attribute($attr_name => %spec);
        }
        foreach my $mouse (do { our %MOUSE; @{$MOUSE{$name}||[]} }) {
          foreach my $attr ($mouse->get_all_attributes) {
            my %spec = %{$attr};
            delete @spec{qw(
              associated_class associated_methods __METACLASS__
              provides curries
            )};
            my $attr_name = delete $spec{name};
            next if $seen_name{$attr_name}++;
            push @attrs, $meta->add_attribute($attr_name => %spec);
          }
        }
      }
      foreach my $meth_name (keys %methods) {
        my $meth_code = $methods{$meth_name};
        $meta->add_method($meth_name, $meth_code);
      }

      if ($am_role) {
        my $info = $Moo::Role::INFO{$name};
        $meta->add_required_methods(@{$info->{requires}});
        foreach my $modifier (@{$info->{modifiers}}) {
          my ($type, @args) = @$modifier;
          my $code = pop @args;
          $meta->${\"add_${type}_method_modifier"}($_, $code) for @args;
        }
      }
      elsif ($am_class) {
        foreach my $attr (@attrs) {
          foreach my $method (@{$attr->associated_methods}) {
            $method->{body} = $name->can($method->name);
          }
        }
        bless(
          $meta->find_method_by_name('new'),
          'Moo::HandleMoose::FakeConstructor',
        );
        my $meta_meth;
        if (
          $meta_meth = $meta->find_method_by_name('meta')
          and $meta_meth->body == \&Moo::Object::meta
        ) {
          bless($meta_meth, 'Moo::HandleMoose::FakeMeta');
        }
        # a combination of Moo and Moose may bypass a Moo constructor but still
        # use a Moo DEMOLISHALL.  We need to make sure this is loaded before
        # global destruction.
        require Method::Generate::DemolishAll;
      }
      $meta->add_role(Class::MOP::class_of($_))
        for grep !/\|/ && $_ ne $name, # reject Foo|Bar and same-role-as-self
          keys %{$Moo::Role::APPLIED_TO{$name}}
    }
    $DID_INJECT{$name} = 1;
    $meta;
  }

  1;
MOO_HANDLEMOOSE

$fatpacked{"Moo/HandleMoose/FakeMetaClass.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MOO_HANDLEMOOSE_FAKEMETACLASS';
  package Moo::HandleMoose::FakeMetaClass;
  use Moo::_strictures;
  use Carp ();
  BEGIN { our @CARP_NOT = qw(Moo::HandleMoose) }

  sub DESTROY { }

  sub AUTOLOAD {
    my ($meth) = (our $AUTOLOAD =~ /([^:]+)$/);
    my $self = shift;
    Carp::croak "Can't call $meth without object instance"
      if !ref $self;
    Carp::croak "Can't inflate Moose metaclass with Moo::sification disabled"
      if $Moo::sification::disabled;
    require Moo::HandleMoose;
    Moo::HandleMoose::inject_real_metaclass_for($self->{name})->$meth(@_)
  }
  sub can {
    my $self = shift;
    return $self->SUPER::can(@_)
      if !ref $self or $Moo::sification::disabled;
    require Moo::HandleMoose;
    Moo::HandleMoose::inject_real_metaclass_for($self->{name})->can(@_)
  }
  sub isa {
    my $self = shift;
    return $self->SUPER::isa(@_)
      if !ref $self or $Moo::sification::disabled;
    require Moo::HandleMoose;
    Moo::HandleMoose::inject_real_metaclass_for($self->{name})->isa(@_)
  }
  sub make_immutable { $_[0] }

  1;
MOO_HANDLEMOOSE_FAKEMETACLASS

$fatpacked{"Moo/HandleMoose/_TypeMap.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MOO_HANDLEMOOSE__TYPEMAP';
  package Moo::HandleMoose::_TypeMap;
  use Moo::_strictures;

  package
    Moo::HandleMoose;
  our %TYPE_MAP;

  package Moo::HandleMoose::_TypeMap;

  use Scalar::Util ();
  use Config;

  our %WEAK_TYPES;

  sub _str_to_ref {
    my $in = shift;
    return $in
      if ref $in;

    if ($in =~ /(?:^|=)([A-Z]+)\(0x([0-9a-zA-Z]+)\)$/) {
      my $type = $1;
      my $id = do { no warnings 'portable'; hex "$2" };
      require B;
      my $sv = bless \$id, 'B::SV';
      my $ref = eval { $sv->object_2svref };
      if (!defined $ref or Scalar::Util::reftype($ref) ne $type) {
        die <<'END_ERROR';
  Moo initialization encountered types defined in a parent thread - ensure that
  Moo is require()d before any further thread spawns following a type definition.
  END_ERROR
      }
      return $ref;
    }
    return $in;
  }

  sub TIEHASH  { bless {}, $_[0] }

  sub STORE {
    my ($self, $key, $value) = @_;
    my $type = _str_to_ref($key);
    $WEAK_TYPES{$type} = $type;
    Scalar::Util::weaken($WEAK_TYPES{$type})
      if ref $type;
    $self->{$key} = $value;
  }

  sub FETCH    { $_[0]->{$_[1]} }
  sub FIRSTKEY { my $a = scalar keys %{$_[0]}; each %{$_[0]} }
  sub NEXTKEY  { each %{$_[0]} }
  sub EXISTS   { exists $_[0]->{$_[1]} }
  sub DELETE   { delete $_[0]->{$_[1]} }
  sub CLEAR    { %{$_[0]} = () }
  sub SCALAR   { scalar %{$_[0]} }

  sub CLONE {
    my @types = map {
      defined $WEAK_TYPES{$_} ? ($WEAK_TYPES{$_} => $TYPE_MAP{$_}) : ()
    } keys %TYPE_MAP;
    %WEAK_TYPES = ();
    %TYPE_MAP = @types;
  }

  sub DESTROY {
    my %types = %{$_[0]};
    untie %TYPE_MAP;
    %TYPE_MAP = %types;
  }

  if ($Config{useithreads}) {
    my @types = %TYPE_MAP;
    tie %TYPE_MAP, __PACKAGE__;
    %TYPE_MAP = @types;
  }

  1;
MOO_HANDLEMOOSE__TYPEMAP

$fatpacked{"Moo/Object.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MOO_OBJECT';
  package Moo::Object;

  use Moo::_strictures;
  use Carp ();

  our %NO_BUILD;
  our %NO_DEMOLISH;
  our $BUILD_MAKER;
  our $DEMOLISH_MAKER;

  sub new {
    my $class = shift;
    unless (exists $NO_DEMOLISH{$class}) {
      unless ($NO_DEMOLISH{$class} = !$class->can('DEMOLISH')) {
        ($DEMOLISH_MAKER ||= do {
          require Method::Generate::DemolishAll;
          Method::Generate::DemolishAll->new
        })->generate_method($class);
      }
    }
    my $proto = $class->BUILDARGS(@_);
    $NO_BUILD{$class} and
      return bless({}, $class);
    $NO_BUILD{$class} = !$class->can('BUILD') unless exists $NO_BUILD{$class};
    $NO_BUILD{$class}
      ? bless({}, $class)
      : bless({}, $class)->BUILDALL($proto);
  }

  # Inlined into Method::Generate::Constructor::_generate_args() - keep in sync
  sub BUILDARGS {
    my $class = shift;
    scalar @_ == 1
      ? ref $_[0] eq 'HASH'
        ? { %{ $_[0] } }
        : Carp::croak("Single parameters to new() must be a HASH ref"
            . " data => ". $_[0])
      : @_ % 2
        ? Carp::croak("The new() method for $class expects a hash reference or a"
            . " key/value list. You passed an odd number of arguments")
        : {@_}
    ;
  }

  sub BUILDALL {
    my $self = shift;
    $self->${\(($BUILD_MAKER ||= do {
      require Method::Generate::BuildAll;
      Method::Generate::BuildAll->new
    })->generate_method(ref($self)))}(@_);
  }

  sub DEMOLISHALL {
    my $self = shift;
    $self->${\(($DEMOLISH_MAKER ||= do {
      require Method::Generate::DemolishAll;
      Method::Generate::DemolishAll->new
    })->generate_method(ref($self)))}(@_);
  }

  sub does {
    return !!0
      unless ($INC{'Moose/Role.pm'} || $INC{'Role/Tiny.pm'});
    require Moo::Role;
    my $does = Moo::Role->can("does_role");
    { no warnings 'redefine'; *does = $does }
    goto &$does;
  }

  # duplicated in Moo::Role
  sub meta {
    require Moo::HandleMoose::FakeMetaClass;
    my $class = ref($_[0])||$_[0];
    bless({ name => $class }, 'Moo::HandleMoose::FakeMetaClass');
  }

  1;
MOO_OBJECT

$fatpacked{"Moo/Role.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MOO_ROLE';
  package Moo::Role;

  use Moo::_strictures;
  use Moo::_Utils qw(
    _getglob
    _getstash
    _install_coderef
    _install_modifier
    _load_module
    _name_coderef
    _set_loaded
    _unimport_coderefs
  );
  use Carp qw(croak);
  use Role::Tiny ();
  BEGIN { our @ISA = qw(Role::Tiny) }
  BEGIN {
    our @CARP_NOT = qw(
      Method::Generate::Accessor
      Method::Generate::Constructor
      Moo::sification
      Moo::_Utils
    );
  }

  our $VERSION = '2.003004';
  $VERSION =~ tr/_//d;

  require Moo::sification;
  Moo::sification->import;

  BEGIN {
      *INFO = \%Role::Tiny::INFO;
      *APPLIED_TO = \%Role::Tiny::APPLIED_TO;
      *COMPOSED = \%Role::Tiny::COMPOSED;
      *ON_ROLE_CREATE = \@Role::Tiny::ON_ROLE_CREATE;
  }

  our %INFO;
  our %APPLIED_TO;
  our %APPLY_DEFAULTS;
  our %COMPOSED;
  our @ON_ROLE_CREATE;

  sub _install_tracked {
    my ($target, $name, $code) = @_;
    $INFO{$target}{exports}{$name} = $code;
    _install_coderef "${target}::${name}" => "Moo::Role::${name}" => $code;
  }

  sub import {
    my $target = caller;
    if ($Moo::MAKERS{$target} and $Moo::MAKERS{$target}{is_class}) {
      croak "Cannot import Moo::Role into a Moo class";
    }
    _set_loaded(caller);
    goto &Role::Tiny::import;
  }

  sub _install_subs {
    my ($me, $target) = @_;
    _install_tracked $target => has => sub {
      my $name_proto = shift;
      my @name_proto = ref $name_proto eq 'ARRAY' ? @$name_proto : $name_proto;
      if (@_ % 2 != 0) {
        croak("Invalid options for " . join(', ', map "'$_'", @name_proto)
          . " attribute(s): even number of arguments expected, got " . scalar @_)
      }
      my %spec = @_;
      foreach my $name (@name_proto) {
        my $spec_ref = @name_proto > 1 ? +{%spec} : \%spec;
        ($INFO{$target}{accessor_maker} ||= do {
          require Method::Generate::Accessor;
          Method::Generate::Accessor->new
        })->generate_method($target, $name, $spec_ref);
        push @{$INFO{$target}{attributes}||=[]}, $name, $spec_ref;
        $me->_maybe_reset_handlemoose($target);
      }
    };
    # install before/after/around subs
    foreach my $type (qw(before after around)) {
      _install_tracked $target => $type => sub {
        push @{$INFO{$target}{modifiers}||=[]}, [ $type => @_ ];
        $me->_maybe_reset_handlemoose($target);
      };
    }
    _install_tracked $target => requires => sub {
      push @{$INFO{$target}{requires}||=[]}, @_;
      $me->_maybe_reset_handlemoose($target);
    };
    _install_tracked $target => with => sub {
      $me->apply_roles_to_package($target, @_);
      $me->_maybe_reset_handlemoose($target);
    };
    *{_getglob("${target}::meta")} = $me->can('meta');
  }

  push @ON_ROLE_CREATE, sub {
    my $target = shift;
    if ($INC{'Moo/HandleMoose.pm'} && !$Moo::sification::disabled) {
      Moo::HandleMoose::inject_fake_metaclass_for($target);
    }
  };

  # duplicate from Moo::Object
  sub meta {
    require Moo::HandleMoose::FakeMetaClass;
    my $class = ref($_[0])||$_[0];
    bless({ name => $class }, 'Moo::HandleMoose::FakeMetaClass');
  }

  sub unimport {
    my $target = caller;
    _unimport_coderefs($target, $INFO{$target});
  }

  sub _maybe_reset_handlemoose {
    my ($class, $target) = @_;
    if ($INC{'Moo/HandleMoose.pm'} && !$Moo::sification::disabled) {
      Moo::HandleMoose::maybe_reinject_fake_metaclass_for($target);
    }
  }

  sub methods_provided_by {
    my ($self, $role) = @_;
    _load_module($role);
    $self->_inhale_if_moose($role);
    croak "${role} is not a Moo::Role" unless $self->is_role($role);
    return $self->SUPER::methods_provided_by($role);
  }

  sub is_role {
    my ($self, $role) = @_;
    $self->_inhale_if_moose($role);
    $self->SUPER::is_role($role);
  }

  sub _inhale_if_moose {
    my ($self, $role) = @_;
    my $meta;
    if (!$self->SUPER::is_role($role)
        and (
          $INC{"Moose.pm"}
          and $meta = Class::MOP::class_of($role)
          and ref $meta ne 'Moo::HandleMoose::FakeMetaClass'
          and $meta->isa('Moose::Meta::Role')
        )
        or (
          Mouse::Util->can('find_meta')
          and $meta = Mouse::Util::find_meta($role)
          and $meta->isa('Mouse::Meta::Role')
       )
    ) {
      my $is_mouse = $meta->isa('Mouse::Meta::Role');
      $INFO{$role}{methods} = {
        map +($_ => $role->can($_)),
          grep $role->can($_),
          grep !($is_mouse && $_ eq 'meta'),
          grep !$meta->get_method($_)->isa('Class::MOP::Method::Meta'),
            $meta->get_method_list
      };
      $APPLIED_TO{$role} = {
        map +($_->name => 1), $meta->calculate_all_roles
      };
      $INFO{$role}{requires} = [ $meta->get_required_method_list ];
      $INFO{$role}{attributes} = [
        map +($_ => do {
          my $attr = $meta->get_attribute($_);
          my $spec = { %{ $is_mouse ? $attr : $attr->original_options } };

          if ($spec->{isa}) {
            require Sub::Quote;

            my $get_constraint = do {
              my $pkg = $is_mouse
                          ? 'Mouse::Util::TypeConstraints'
                          : 'Moose::Util::TypeConstraints';
              _load_module($pkg);
              $pkg->can('find_or_create_isa_type_constraint');
            };

            my $tc = $get_constraint->($spec->{isa});
            my $check = $tc->_compiled_type_constraint;
            my $tc_var = '$_check_for_'.Sub::Quote::sanitize_identifier($tc->name);

            $spec->{isa} = Sub::Quote::quote_sub(
              qq{
                &${tc_var} or Carp::croak "Type constraint failed for \$_[0]"
              },
              { $tc_var => \$check },
              {
                package => $role,
              },
            );

            if ($spec->{coerce}) {

               # Mouse has _compiled_type_coercion straight on the TC object
               $spec->{coerce} = $tc->${\(
                 $tc->can('coercion')||sub { $_[0] }
               )}->_compiled_type_coercion;
            }
          }
          $spec;
        }), $meta->get_attribute_list
      ];
      my $mods = $INFO{$role}{modifiers} = [];
      foreach my $type (qw(before after around)) {
        # Mouse pokes its own internals so we have to fall back to doing
        # the same thing in the absence of the Moose API method
        my $map = $meta->${\(
          $meta->can("get_${type}_method_modifiers_map")
          or sub { shift->{"${type}_method_modifiers"} }
        )};
        foreach my $method (keys %$map) {
          foreach my $mod (@{$map->{$method}}) {
            push @$mods, [ $type => $method => $mod ];
          }
        }
      }
      $INFO{$role}{inhaled_from_moose} = 1;
      $INFO{$role}{is_role} = 1;
    }
  }

  sub _maybe_make_accessors {
    my ($self, $target, $role) = @_;
    my $m;
    if ($INFO{$role} && $INFO{$role}{inhaled_from_moose}
        or $INC{"Moo.pm"}
        and $m = Moo->_accessor_maker_for($target)
        and ref($m) ne 'Method::Generate::Accessor') {
      $self->_make_accessors($target, $role);
    }
  }

  sub _make_accessors_if_moose {
    my ($self, $target, $role) = @_;
    if ($INFO{$role} && $INFO{$role}{inhaled_from_moose}) {
      $self->_make_accessors($target, $role);
    }
  }

  sub _make_accessors {
    my ($self, $target, $role) = @_;
    my $acc_gen = ($Moo::MAKERS{$target}{accessor} ||= do {
      require Method::Generate::Accessor;
      Method::Generate::Accessor->new
    });
    my $con_gen = $Moo::MAKERS{$target}{constructor};
    my @attrs = @{$INFO{$role}{attributes}||[]};
    while (my ($name, $spec) = splice @attrs, 0, 2) {
      # needed to ensure we got an index for an arrayref based generator
      if ($con_gen) {
        $spec = $con_gen->all_attribute_specs->{$name};
      }
      $acc_gen->generate_method($target, $name, $spec);
    }
  }

  sub _undefer_subs {
    my ($self, $target, $role) = @_;
    if ($INC{'Sub/Defer.pm'}) {
      Sub::Defer::undefer_package($role);
    }
  }

  sub role_application_steps {
    qw(_handle_constructor _undefer_subs _maybe_make_accessors),
      $_[0]->SUPER::role_application_steps;
  }

  sub apply_roles_to_package {
    my ($me, $to, @roles) = @_;
    foreach my $role (@roles) {
      _load_module($role);
      $me->_inhale_if_moose($role);
      croak "${role} is not a Moo::Role" unless $me->is_role($role);
    }
    $me->SUPER::apply_roles_to_package($to, @roles);
  }

  sub apply_single_role_to_package {
    my ($me, $to, $role) = @_;
    _load_module($role);
    $me->_inhale_if_moose($role);
    croak "${role} is not a Moo::Role" unless $me->is_role($role);
    $me->SUPER::apply_single_role_to_package($to, $role);
  }

  sub create_class_with_roles {
    my ($me, $superclass, @roles) = @_;

    my ($new_name, $compose_name) = $me->_composite_name($superclass, @roles);

    return $new_name if $COMPOSED{class}{$new_name};

    foreach my $role (@roles) {
      _load_module($role);
      $me->_inhale_if_moose($role);
      croak "${role} is not a Moo::Role" unless $me->is_role($role);
    }

    my $m;
    if ($INC{"Moo.pm"}
        and $m = Moo->_accessor_maker_for($superclass)
        and ref($m) ne 'Method::Generate::Accessor') {
      # old fashioned way time.
      @{*{_getglob("${new_name}::ISA")}{ARRAY}} = ($superclass);
      $Moo::MAKERS{$new_name} = {is_class => 1};
      $me->apply_roles_to_package($new_name, @roles);
    }
    else {
      $me->SUPER::create_class_with_roles($superclass, @roles);
      $Moo::MAKERS{$new_name} = {is_class => 1};
      $me->_handle_constructor($new_name, $_) for @roles;
    }

    if ($INC{'Moo/HandleMoose.pm'} && !$Moo::sification::disabled) {
      Moo::HandleMoose::inject_fake_metaclass_for($new_name);
    }
    $COMPOSED{class}{$new_name} = 1;
    _set_loaded($new_name, (caller)[1]);
    return $new_name;
  }

  sub apply_roles_to_object {
    my ($me, $object, @roles) = @_;
    my $new = $me->SUPER::apply_roles_to_object($object, @roles);
    my $class = ref $new;
    _set_loaded($class, (caller)[1]);

    my $apply_defaults = exists $APPLY_DEFAULTS{$class} ? $APPLY_DEFAULTS{$class}
      : $APPLY_DEFAULTS{$class} = do {
      my %attrs = map { @{$INFO{$_}{attributes}||[]} } @roles;

      if ($INC{'Moo.pm'}
          and keys %attrs
          and my $con_gen = Moo->_constructor_maker_for($class)
          and my $m = Moo->_accessor_maker_for($class)) {

        my $specs = $con_gen->all_attribute_specs;

        my %captures;
        my $code = join('',
          ( map {
            my $name = $_;
            my $spec = $specs->{$name};
            if ($m->has_eager_default($name, $spec)) {
              my ($has, $has_cap)
                = $m->generate_simple_has('$_[0]', $name, $spec);
              my ($set, $pop_cap)
                = $m->generate_use_default('$_[0]', $name, $spec, $has);

              @captures{keys %$has_cap, keys %$pop_cap}
                = (values %$has_cap, values %$pop_cap);
              "($set),";
            }
            else {
              ();
            }
          } sort keys %attrs ),
        );
        if ($code) {
          require Sub::Quote;
          Sub::Quote::quote_sub(
            "${class}::_apply_defaults",
            "no warnings 'void';\n$code",
            \%captures,
            {
              package => $class,
              no_install => 1,
            }
          );
        }
        else {
          0;
        }
      }
      else {
        0;
      }
    };
    if ($apply_defaults) {
      local $Carp::Internal{+__PACKAGE__} = 1;
      local $Carp::Internal{$class} = 1;
      $new->$apply_defaults;
    }
    return $new;
  }

  sub _composable_package_for {
    my ($self, $role) = @_;
    my $composed_name = 'Role::Tiny::_COMPOSABLE::'.$role;
    return $composed_name if $COMPOSED{role}{$composed_name};
    $self->_make_accessors_if_moose($composed_name, $role);
    $self->SUPER::_composable_package_for($role);
  }

  sub _install_single_modifier {
    my ($me, @args) = @_;
    _install_modifier(@args);
  }

  sub _install_does {
      my ($me, $to) = @_;

      # If Role::Tiny actually installed the DOES, give it a name
      my $new = $me->SUPER::_install_does($to) or return;
      return _name_coderef("${to}::DOES", $new);
  }

  sub does_role {
    my ($proto, $role) = @_;
    return 1
      if Role::Tiny::does_role($proto, $role);
    my $meta;
    if ($INC{'Moose.pm'}
        and $meta = Class::MOP::class_of($proto)
        and ref $meta ne 'Moo::HandleMoose::FakeMetaClass'
        and $meta->can('does_role')
    ) {
      return $meta->does_role($role);
    }
    return 0;
  }

  sub _handle_constructor {
    my ($me, $to, $role) = @_;
    my $attr_info = $INFO{$role} && $INFO{$role}{attributes};
    return unless $attr_info && @$attr_info;
    my $info = $INFO{$to};
    my $con = $INC{"Moo.pm"} && Moo->_constructor_maker_for($to);
    my %existing
      = $info ? @{$info->{attributes} || []}
      : $con  ? %{$con->all_attribute_specs || {}}
      : ();

    my @attr_info =
      map { @{$attr_info}[$_, $_+1] }
      grep { ! $existing{$attr_info->[$_]} }
      map { 2 * $_ } 0..@$attr_info/2-1;

    if ($info) {
      push @{$info->{attributes}||=[]}, @attr_info;
    }
    elsif ($con) {
      # shallow copy of the specs since the constructor will assign an index
      $con->register_attribute_specs(map ref() ? { %$_ } : $_, @attr_info);
    }
  }

  1;
  __END__

  =head1 NAME

  Moo::Role - Minimal Object Orientation support for Roles

  =head1 SYNOPSIS

    package My::Role;

    use Moo::Role;
    use strictures 2;

    sub foo { ... }

    sub bar { ... }

    has baz => (
      is => 'ro',
    );

    1;

  And elsewhere:

    package Some::Class;

    use Moo;
    use strictures 2;

    # bar gets imported, but not foo
    with('My::Role');

    sub foo { ... }

    1;

  =head1 DESCRIPTION

  C<Moo::Role> builds upon L<Role::Tiny>, so look there for most of the
  documentation on how this works.  The main addition here is extra bits to make
  the roles more "Moosey;" which is to say, it adds L</has>.

  =head1 IMPORTED SUBROUTINES

  See L<Role::Tiny/IMPORTED SUBROUTINES> for all the other subroutines that are
  imported by this module.

  =head2 has

    has attr => (
      is => 'ro',
    );

  Declares an attribute for the class to be composed into.  See
  L<Moo/has> for all options.

  =head1 CLEANING UP IMPORTS

  L<Moo::Role> cleans up its own imported methods and any imports
  declared before the C<use Moo::Role> statement automatically.
  Anything imported after C<use Moo::Role> will be composed into
  consuming packages.  A package that consumes this role:

    package My::Role::ID;

    use Digest::MD5 qw(md5_hex);
    use Moo::Role;
    use Digest::SHA qw(sha1_hex);

    requires 'name';

    sub as_md5  { my ($self) = @_; return md5_hex($self->name);  }
    sub as_sha1 { my ($self) = @_; return sha1_hex($self->name); }

    1;

  ..will now have a C<< $self->sha1_hex() >> method available to it
  that probably does not do what you expect.  On the other hand, a call
  to C<< $self->md5_hex() >> will die with the helpful error message:
  C<Can't locate object method "md5_hex">.

  See L<Moo/"CLEANING UP IMPORTS"> for more details.

  =head1 SUPPORT

  See L<Moo> for support and contact information.

  =head1 AUTHORS

  See L<Moo> for authors.

  =head1 COPYRIGHT AND LICENSE

  See L<Moo> for the copyright and license.

  =cut
MOO_ROLE

$fatpacked{"Moo/_Utils.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MOO__UTILS';
  package Moo::_Utils;
  use Moo::_strictures;

  {
    no strict 'refs';
    sub _getglob { \*{$_[0]} }
    sub _getstash { \%{"$_[0]::"} }
  }

  BEGIN {
    my ($su, $sn);
    $su = $INC{'Sub/Util.pm'} && defined &Sub::Util::set_subname
      or $sn = $INC{'Sub/Name.pm'}
      or $su = eval { require Sub::Util; } && defined &Sub::Util::set_subname
      or $sn = eval { require Sub::Name; };

    *_subname = $su ? \&Sub::Util::set_subname
              : $sn ? \&Sub::Name::subname
              : sub { $_[1] };
    *_CAN_SUBNAME = ($su || $sn) ? sub(){1} : sub(){0};
  }

  use Module::Runtime qw(use_package_optimistically module_notional_filename);

  use Devel::GlobalDestruction ();
  use Exporter qw(import);
  use Config;
  use Carp qw(croak);

  our @EXPORT = qw(
      _getglob _install_modifier _load_module _maybe_load_module
      _getstash _install_coderef _name_coderef
      _unimport_coderefs _set_loaded
  );

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

    if ($INC{'Sub/Defer.pm'} and my $to_modify = $into->can($name)) { # CMM will throw for us if not
      Sub::Defer::undefer_sub($to_modify);
    }

    require Class::Method::Modifiers;
    Class::Method::Modifiers::install_modifier(@_);
  }

  sub _load_module {
    my $module = $_[0];
    my $file = eval { module_notional_filename($module) } or croak $@;
    use_package_optimistically($module);
    return 1
      if $INC{$file};
    my $error = $@ || "Can't locate $file";

    # can't just ->can('can') because a sub-package Foo::Bar::Baz
    # creates a 'Baz::' key in Foo::Bar's symbol table
    my $stash = _getstash($module)||{};
    return 1 if grep +(ref($_) || *$_{CODE}), values %$stash;
    return 1
      if $INC{"Moose.pm"} && Class::MOP::class_of($module)
      or Mouse::Util->can('find_meta') && Mouse::Util::find_meta($module);
    croak $error;
  }

  our %MAYBE_LOADED;
  sub _maybe_load_module {
    my $module = $_[0];
    return $MAYBE_LOADED{$module}
      if exists $MAYBE_LOADED{$module};
    if(! eval { use_package_optimistically($module) }) {
      warn "$module exists but failed to load with error: $@";
    }
    elsif ( $INC{module_notional_filename($module)} ) {
      return $MAYBE_LOADED{$module} = 1;
    }
    return $MAYBE_LOADED{$module} = 0;
  }

  sub _set_loaded {
    $INC{Module::Runtime::module_notional_filename($_[0])} ||= $_[1];
  }

  sub _install_coderef {
    my ($glob, $code) = (_getglob($_[0]), _name_coderef(@_));
    no warnings 'redefine';
    if (*{$glob}{CODE}) {
      *{$glob} = $code;
    }
    # perl will sometimes warn about mismatched prototypes coming from the
    # inheritance cache, so disable them if we aren't redefining a sub
    else {
      no warnings 'prototype';
      *{$glob} = $code;
    }
  }

  sub _name_coderef {
    shift if @_ > 2; # three args is (target, name, sub)
    _CAN_SUBNAME ? _subname(@_) : $_[1];
  }

  sub _unimport_coderefs {
    my ($target, $info) = @_;
    return unless $info and my $exports = $info->{exports};
    my %rev = reverse %$exports;
    my $stash = _getstash($target);
    foreach my $name (keys %$exports) {
      if ($stash->{$name} and defined(&{$stash->{$name}})) {
        if ($rev{$target->can($name)}) {
          my $old = delete $stash->{$name};
          my $full_name = join('::',$target,$name);
          # Copy everything except the code slot back into place (e.g. $has)
          foreach my $type (qw(SCALAR HASH ARRAY IO)) {
            next unless defined(*{$old}{$type});
            no strict 'refs';
            *$full_name = *{$old}{$type};
          }
        }
      }
    }
  }

  if ($Config{useithreads}) {
    require Moo::HandleMoose::_TypeMap;
  }

  1;
MOO__UTILS

$fatpacked{"Moo/_mro.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MOO__MRO';
  package Moo::_mro;
  use Moo::_strictures;

  if ("$]" >= 5.010_000) {
    require mro;
  } else {
    require MRO::Compat;
  }

  1;
MOO__MRO

$fatpacked{"Moo/_strictures.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MOO__STRICTURES';
  package Moo::_strictures;
  use strict;
  use warnings;

  sub import {
    if ($ENV{MOO_FATAL_WARNINGS}) {
      require strictures;
      strictures->VERSION(2);
      @_ = ('strictures');
      goto &strictures::import;
    }
    else {
      strict->import;
      warnings->import;
      warnings->unimport('once');
    }
  }

  1;
MOO__STRICTURES

$fatpacked{"Moo/sification.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MOO_SIFICATION';
  package Moo::sification;

  use Moo::_strictures;
  no warnings 'once';
  use Devel::GlobalDestruction qw(in_global_destruction);
  use Carp qw(croak);
  BEGIN { our @CARP_NOT = qw(Moo::HandleMoose) }

  sub unimport {
    croak "Can't disable Moo::sification after inflation has been done"
      if $Moo::HandleMoose::SETUP_DONE;
    our $disabled = 1;
  }

  sub Moo::HandleMoose::AuthorityHack::DESTROY {
    unless (our $disabled or in_global_destruction) {
      require Moo::HandleMoose;
      Moo::HandleMoose->import;
    }
  }

  sub import {
    return
      if our $setup_done;
    if ($INC{"Moose.pm"}) {
      require Moo::HandleMoose;
      Moo::HandleMoose->import;
    } else {
      $Moose::AUTHORITY = bless({}, 'Moo::HandleMoose::AuthorityHack');
    }
    $setup_done = 1;
  }

  1;
MOO_SIFICATION

$fatpacked{"Package/Stash.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'PACKAGE_STASH';
  package Package::Stash; # git description: 5468b00
  use strict;
  use warnings;
  use 5.008001;
  # ABSTRACT: routines for manipulating stashes

  our $VERSION = '0.38';
  our $IMPLEMENTATION;

  use Module::Implementation 0.06;

  BEGIN {
      local $ENV{PACKAGE_STASH_IMPLEMENTATION} = $IMPLEMENTATION
        if ( $IMPLEMENTATION and not $ENV{PACKAGE_STASH_IMPLEMENTATION} );

      Module::Implementation::build_loader_sub(
          implementations => [ 'XS', 'PP' ],
          symbols         => [qw(
              new
              name
              namespace
              add_symbol
              remove_glob
              has_symbol
              get_symbol
              get_or_add_symbol
              remove_symbol
              list_all_symbols
              get_all_symbols
          )],
      )->();
      $IMPLEMENTATION = Module::Implementation::implementation_for(__PACKAGE__);
  }


  1;

  __END__

  =pod

  =encoding UTF-8

  =head1 NAME

  Package::Stash - routines for manipulating stashes

  =head1 VERSION

  version 0.38

  =head1 SYNOPSIS

    my $stash = Package::Stash->new('Foo');
    $stash->add_symbol('%foo', {bar => 1});
    # $Foo::foo{bar} == 1
    $stash->has_symbol('$foo') # false
    my $namespace = $stash->namespace;
    *{ $namespace->{foo} }{HASH} # {bar => 1}

  =head1 DESCRIPTION

  Manipulating stashes (Perl's symbol tables) is occasionally necessary, but
  incredibly messy, and easy to get wrong. This module hides all of that behind a
  simple API.

  NOTE: Most methods in this class require a variable specification that includes
  a sigil. If this sigil is absent, it is assumed to represent the IO slot.

  Due to limitations in the typeglob API available to perl code, and to typeglob
  manipulation in perl being quite slow, this module provides two
  implementations - one in pure perl, and one using XS. The XS implementation is
  to be preferred for most usages; the pure perl one is provided for cases where
  XS modules are not a possibility. The current implementation in use can be set
  by setting C<$ENV{PACKAGE_STASH_IMPLEMENTATION}> or
  C<$Package::Stash::IMPLEMENTATION> before loading Package::Stash (with the
  environment variable taking precedence), otherwise, it will use the XS
  implementation if possible, falling back to the pure perl one.

  =head1 METHODS

  =head2 new $package_name

  Creates a new C<Package::Stash> object, for the package given as the only
  argument.

  =head2 name

  Returns the name of the package that this object represents.

  =head2 namespace

  Returns the raw stash itself.

  =head2 add_symbol $variable $value %opts

  Adds a new package symbol, for the symbol given as C<$variable>, and optionally
  gives it an initial value of C<$value>. C<$variable> should be the name of
  variable including the sigil, so

    Package::Stash->new('Foo')->add_symbol('%foo')

  will create C<%Foo::foo>.

  Valid options (all optional) are C<filename>, C<first_line_num>, and
  C<last_line_num>.

  C<$opts{filename}>, C<$opts{first_line_num}>, and C<$opts{last_line_num}> can
  be used to indicate where the symbol should be regarded as having been defined.
  Currently these values are only used if the symbol is a subroutine ('C<&>'
  sigil) and only if C<$^P & 0x10> is true, in which case the special C<%DB::sub>
  hash is updated to record the values of C<filename>, C<first_line_num>, and
  C<last_line_num> for the subroutine. If these are not passed, their values are
  inferred (as much as possible) from C<caller> information.

  This is especially useful for debuggers and profilers, which use C<%DB::sub> to
  determine where the source code for a subroutine can be found.  See
  L<http://perldoc.perl.org/perldebguts.html#Debugger-Internals> for more
  information about C<%DB::sub>.

  =head2 remove_glob $name

  Removes all package variables with the given name, regardless of sigil.

  =head2 has_symbol $variable

  Returns whether or not the given package variable (including sigil) exists.

  =head2 get_symbol $variable

  Returns the value of the given package variable (including sigil).

  =head2 get_or_add_symbol $variable

  Like C<get_symbol>, except that it will return an empty hashref or
  arrayref if the variable doesn't exist.

  =head2 remove_symbol $variable

  Removes the package variable described by C<$variable> (which includes the
  sigil); other variables with the same name but different sigils will be
  untouched.

  =head2 list_all_symbols $type_filter

  Returns a list of package variable names in the package, without sigils. If a
  C<type_filter> is passed, it is used to select package variables of a given
  type, where valid types are the slots of a typeglob ('SCALAR', 'CODE', 'HASH',
  etc). Note that if the package contained any C<BEGIN> blocks, perl will leave
  an empty typeglob in the C<BEGIN> slot, so this will show up if no filter is
  used (and similarly for C<INIT>, C<END>, etc).

  =head2 get_all_symbols $type_filter

  Returns a hashref, keyed by the variable names in the package. If
  C<$type_filter> is passed, the hash will contain every variable of that type in
  the package as values, otherwise, it will contain the typeglobs corresponding
  to the variable names (basically, a clone of the stash).

  =head1 WORKING WITH VARIABLES

  It is important to note, that when working with scalar variables, the default
  behavior is to B<copy> values.

    my $stash = Package::Stash->new('Some::Namespace');
    my $variable = 1;
    # $Some::Namespace::name is a copy of $variable
    $stash->add_symbol('$name', $variable);
    $variable++
    # $Some::Namespace::name == 1 , $variable == 2

  This will likely confuse people who expect it to work the same as typeglob
  assignment, which simply creates new references to existing variables.

    my $variable = 1;
    {
        no strict 'refs';
        # assign $Package::Stash::name = $variable
        *{'Package::Stash::name'} = \$variable;
    }
    $variable++ # affects both names

  If this behaviour is desired when working with Package::Stash, simply pass
  Package::Stash a scalar ref:

    my $stash = Package::Stash->new('Some::Namespace');
    my $variable = 1;
    # $Some::Namespace::name is now $variable
    $stash->add_symbol('$name', \$variable);
    $variable++
    # $Some::Namespace::name == 2 , $variable == 2

  This will be what you want as well if you're ever working with L<Readonly>
  variables:

    use Readonly;
    Readonly my $value, 'hello';

    $stash->add_symbol('$name', \$value); # reference
    print $Some::Namespace::name; # hello
    # Tries to modify the read-only 'hello' and dies.
    $Some::Namespace::name .= " world";

    $stash->add_symbol('$name', $value); # copy
    print $Some::Namespace::name; # hello
    # No problem, modifying a copy, not the original
    $Some::Namespace::name .= " world";

  =head1 SEE ALSO

  =over 4

  =item * L<Class::MOP::Package>

  This module is a factoring out of code that used to live here

  =back

  =head1 SUPPORT

  You can find this documentation for this module with the perldoc command.

      perldoc Package::Stash

  You can also look for information at:

  =over 4

  =item * MetaCPAN

  L<https://metacpan.org/release/Package-Stash>

  =item * Github

  L<https://github.com/moose/Package-Stash>

  =item * RT: CPAN's request tracker

  L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Package-Stash>

  =item * CPAN Ratings

  L<http://cpanratings.perl.org/d/Package-Stash>

  =back

  =head1 HISTORY

  Based on code from L<Class::MOP::Package>, by Stevan Little and the Moose
  Cabal.

  =head1 BUGS / CAVEATS

  =over 4

  =item * Prior to perl 5.10, scalar slots are only considered to exist if they are defined

  This is due to a shortcoming within perl itself. See
  L<perlref/Making References> point 7 for more information.

  =item * GLOB and FORMAT variables are not (yet) accessible through this module.

  =item * Also, see the BUGS section for the specific backends (L<Package::Stash::XS> and L<Package::Stash::PP>)

  =back

  Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=Package-Stash>
  (or L<bug-Package-Stash@rt.cpan.org|mailto:bug-Package-Stash@rt.cpan.org>).

  =head1 AUTHOR

  Jesse Luehrs <doy@tozt.net>

  =head1 CONTRIBUTORS

  =for stopwords Karen Etheridge Carlos Lima Kent Fredric Justin Hunter Christian Walde Dave Rolsky Niko Tyni Renee Tim Bunce

  =over 4

  =item *

  Karen Etheridge <ether@cpan.org>

  =item *

  Carlos Lima <carlos@multi>

  =item *

  Kent Fredric <kentfredric@gmail.com>

  =item *

  Justin Hunter <justin.d.hunter@gmail.com>

  =item *

  Christian Walde <walde.christian@googlemail.com>

  =item *

  Dave Rolsky <autarch@urth.org>

  =item *

  Niko Tyni <ntyni@debian.org>

  =item *

  Renee <reb@perl-services.de>

  =item *

  Tim Bunce <Tim.Bunce@pobox.com>

  =back

  =head1 COPYRIGHT AND LICENSE

  This software is copyright (c) 2018 by Jesse Luehrs.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =cut
PACKAGE_STASH

$fatpacked{"Package/Stash/Conflicts.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'PACKAGE_STASH_CONFLICTS';
  package # hide from PAUSE
      Package::Stash::Conflicts;

  use strict;
  use warnings;

  # this module was generated with Dist::Zilla::Plugin::Conflicts 0.19

  use Dist::CheckConflicts
      -dist      => 'Package::Stash',
      -conflicts => {
          'Class::MOP' => '1.08',
          'MooseX::Method::Signatures' => '0.36',
          'MooseX::Role::WithOverloading' => '0.08',
          'namespace::clean' => '0.18',
      },
      -also => [ qw(
          B
          Carp
          Dist::CheckConflicts
          Getopt::Long
          Module::Implementation
          Scalar::Util
          Symbol
          constant
          strict
          warnings
      ) ],

  ;

  1;

  # ABSTRACT: Provide information on conflicts for Package::Stash
  # Dist::Zilla: -PodWeaver
PACKAGE_STASH_CONFLICTS

$fatpacked{"Package/Stash/PP.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'PACKAGE_STASH_PP';
  package Package::Stash::PP;
  use strict;
  use warnings;
  # ABSTRACT: pure perl implementation of the Package::Stash API

  our $VERSION = '0.38';

  use B;
  use Carp qw(confess);
  use Scalar::Util qw(blessed reftype weaken);
  use Symbol;
  # before 5.12, assigning to the ISA glob would make it lose its magical ->isa
  # powers
  use constant BROKEN_ISA_ASSIGNMENT => ($] < 5.012);
  # before 5.10, stashes don't ever seem to drop to a refcount of zero, so
  # weakening them isn't helpful
  use constant BROKEN_WEAK_STASH     => ($] < 5.010);
  # before 5.10, the scalar slot was always treated as existing if the
  # glob existed
  use constant BROKEN_SCALAR_INITIALIZATION => ($] < 5.010);
  # add_method on anon stashes triggers rt.perl #1804 otherwise
  # fixed in perl commit v5.13.3-70-g0fe688f
  use constant BROKEN_GLOB_ASSIGNMENT => ($] < 5.013004);
  # pre-5.10, ->isa lookups were cached in the ::ISA::CACHE:: slot
  use constant HAS_ISA_CACHE => ($] < 5.010);


  sub new {
      my $class = shift;
      my ($package) = @_;

      if (!defined($package) || (ref($package) && reftype($package) ne 'HASH')) {
          confess "Package::Stash->new must be passed the name of the "
                . "package to access";
      }
      elsif (ref($package) && reftype($package) eq 'HASH') {
          confess "The PP implementation of Package::Stash does not support "
                . "anonymous stashes before perl 5.14"
              if BROKEN_GLOB_ASSIGNMENT;

          return bless {
              'namespace' => $package,
          }, $class;
      }
      elsif ($package =~ /\A[0-9A-Z_a-z]+(?:::[0-9A-Z_a-z]+)*\z/) {
          return bless {
              'package' => $package,
          }, $class;
      }
      else {
          confess "$package is not a module name";
      }

  }

  sub name {
      confess "Can't call name as a class method"
          unless blessed($_[0]);
      confess "Can't get the name of an anonymous package"
          unless defined($_[0]->{package});
      return $_[0]->{package};
  }

  sub namespace {
      confess "Can't call namespace as a class method"
          unless blessed($_[0]);

      if (BROKEN_WEAK_STASH) {
          no strict 'refs';
          return \%{$_[0]->name . '::'};
      }
      else {
          return $_[0]->{namespace} if defined $_[0]->{namespace};

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

          weaken($_[0]->{namespace});

          return $_[0]->{namespace};
      }
  }

  {
      my %SIGIL_MAP = (
          '$' => 'SCALAR',
          '@' => 'ARRAY',
          '%' => 'HASH',
          '&' => 'CODE',
          ''  => 'IO',
      );

      sub _deconstruct_variable_name {
          my ($variable) = @_;

          my @ret;
          if (ref($variable) eq 'HASH') {
              @ret = @{$variable}{qw[name sigil type]};
          }
          else {
              (defined $variable && length $variable)
                  || confess "You must pass a variable name";

              my $sigil = substr($variable, 0, 1, '');

              if (exists $SIGIL_MAP{$sigil}) {
                  @ret = ($variable, $sigil, $SIGIL_MAP{$sigil});
              }
              else {
                  @ret = ("${sigil}${variable}", '', $SIGIL_MAP{''});
              }
          }

          # XXX in pure perl, this will access things in inner packages,
          # in xs, this will segfault - probably look more into this at
          # some point
          ($ret[0] !~ /::/)
              || confess "Variable names may not contain ::";

          return @ret;
      }
  }

  sub _valid_for_type {
      my ($value, $type) = @_;
      if ($type eq 'HASH' || $type eq 'ARRAY'
       || $type eq 'IO'   || $type eq 'CODE') {
          return reftype($value) eq $type;
      }
      else {
          my $ref = reftype($value);
          return !defined($ref) || $ref eq 'SCALAR' || $ref eq 'REF' || $ref eq 'LVALUE' || $ref eq 'REGEXP' || $ref eq 'VSTRING';
      }
  }

  sub add_symbol {
      my ($self, $variable, $initial_value, %opts) = @_;

      my ($name, $sigil, $type) = _deconstruct_variable_name($variable);

      if (@_ > 2) {
          _valid_for_type($initial_value, $type)
              || confess "$initial_value is not of type $type";

          # cheap fail-fast check for PERLDBf_SUBLINE and '&'
          if ($^P and $^P & 0x10 && $sigil eq '&') {
              my $filename = $opts{filename};
              my $first_line_num = $opts{first_line_num};

              (undef, $filename, $first_line_num) = caller
                  if not defined $filename;

              my $last_line_num = $opts{last_line_num} || ($first_line_num ||= 0);

              # http://perldoc.perl.org/perldebguts.html#Debugger-Internals
              $DB::sub{$self->name . '::' . $name} = "$filename:$first_line_num-$last_line_num";
          }
      }

      if (BROKEN_GLOB_ASSIGNMENT) {
          if (@_ > 2) {
              no strict 'refs';
              no warnings 'redefine';
              *{ $self->name . '::' . $name } = ref $initial_value
                  ? $initial_value : \$initial_value;
          }
          else {
              no strict 'refs';
              if (BROKEN_ISA_ASSIGNMENT && $name eq 'ISA') {
                  *{ $self->name . '::' . $name };
              }
              else {
                  my $undef = _undef_ref_for_type($type);
                  *{ $self->name . '::' . $name } = $undef;
              }
          }
      }
      else {
          my $namespace = $self->namespace;
          {
              # using glob aliasing instead of Symbol::gensym, because otherwise,
              # magic doesn't get applied properly.
              # see <20120710063744.19360.qmail@lists-nntp.develooper.com> on p5p
              local *__ANON__:: = $namespace;
              no strict 'refs';
              no warnings 'void';
              no warnings 'once';
              *{"__ANON__::$name"};
          }

          if (@_ > 2) {
              no warnings 'redefine';
              *{ $namespace->{$name} } = ref $initial_value
                  ? $initial_value : \$initial_value;
          }
          else {
              return if BROKEN_ISA_ASSIGNMENT && $name eq 'ISA';
              *{ $namespace->{$name} } = _undef_ref_for_type($type);
          }
      }
  }

  sub _undef_ref_for_type {
      my ($type) = @_;

      if ($type eq 'ARRAY') {
          return [];
      }
      elsif ($type eq 'HASH') {
          return {};
      }
      elsif ($type eq 'SCALAR') {
          return \undef;
      }
      elsif ($type eq 'IO') {
          return Symbol::geniosym;
      }
      elsif ($type eq 'CODE') {
          confess "Don't know how to vivify CODE variables";
      }
      else {
          confess "Unknown type $type in vivication";
      }
  }

  sub remove_glob {
      my ($self, $name) = @_;
      delete $self->namespace->{$name};
  }

  sub has_symbol {
      my ($self, $variable) = @_;

      my ($name, $sigil, $type) = _deconstruct_variable_name($variable);

      my $namespace = $self->namespace;

      return unless exists $namespace->{$name};

      my $entry_ref = \$namespace->{$name};
      if (reftype($entry_ref) eq 'GLOB') {
          if ($type eq 'SCALAR') {
              if (BROKEN_SCALAR_INITIALIZATION) {
                  return defined ${ *{$entry_ref}{$type} };
              }
              else {
                  my $sv = B::svref_2object($entry_ref)->SV;
                  return $sv->isa('B::SV')
                      || ($sv->isa('B::SPECIAL')
                       && $B::specialsv_name[$$sv] ne 'Nullsv');
              }
          }
          else {
              return defined *{$entry_ref}{$type};
          }
      }
      else {
          # a symbol table entry can be -1 (stub), string (stub with prototype),
          # or reference (constant)
          return $type eq 'CODE';
      }
  }

  sub get_symbol {
      my ($self, $variable, %opts) = @_;

      my ($name, $sigil, $type) = _deconstruct_variable_name($variable);

      my $namespace = $self->namespace;

      if (!exists $namespace->{$name}) {
          if ($opts{vivify}) {
              $self->add_symbol($variable);
          }
          else {
              return undef;
          }
      }

      my $entry_ref = \$namespace->{$name};

      if (ref($entry_ref) eq 'GLOB') {
          return *{$entry_ref}{$type};
      }
      else {
          if ($type eq 'CODE') {
              if (BROKEN_GLOB_ASSIGNMENT || defined($self->{package})) {
                  no strict 'refs';
                  return \&{ $self->name . '::' . $name };
              }

              # XXX we should really be able to support arbitrary anonymous
              # stashes here... (not just via Package::Anon)
              if (blessed($namespace) && $namespace->isa('Package::Anon')) {
                  # ->can will call gv_init for us, which inflates the glob
                  # don't know how to do this in general
                  $namespace->bless(\(my $foo))->can($name);
              }
              else {
                  confess "Don't know how to inflate a " . ref($entry_ref)
                        . " into a full coderef (perhaps you could use"
                        . " Package::Anon instead of a bare stash?)"
              }

              return *{ $namespace->{$name} }{CODE};
          }
          else {
              return undef;
          }
      }
  }

  sub get_or_add_symbol {
      my $self = shift;
      $self->get_symbol(@_, vivify => 1);
  }

  sub remove_symbol {
      my ($self, $variable) = @_;

      my ($name, $sigil, $type) = _deconstruct_variable_name($variable);

      # FIXME:
      # no doubt this is grossly inefficient and
      # could be done much easier and faster in XS

      my %desc = (
          SCALAR => { sigil => '$', type => 'SCALAR', name => $name },
          ARRAY  => { sigil => '@', type => 'ARRAY',  name => $name },
          HASH   => { sigil => '%', type => 'HASH',   name => $name },
          CODE   => { sigil => '&', type => 'CODE',   name => $name },
          IO     => { sigil => '',  type => 'IO',     name => $name },
      );
      confess "This should never ever ever happen" if !$desc{$type};

      my @types_to_store = grep { $type ne $_ && $self->has_symbol($desc{$_}) }
                                keys %desc;
      my %values = map { $_, $self->get_symbol($desc{$_}) } @types_to_store;

      $values{SCALAR} = $self->get_symbol($desc{SCALAR})
        if !defined $values{SCALAR}
          && $type ne 'SCALAR'
          && BROKEN_SCALAR_INITIALIZATION;

      $self->remove_glob($name);

      $self->add_symbol($desc{$_} => $values{$_})
          for grep { defined $values{$_} } keys %values;
  }

  sub list_all_symbols {
      my ($self, $type_filter) = @_;

      my $namespace = $self->namespace;
      if (HAS_ISA_CACHE) {
          return grep { $_ ne '::ISA::CACHE::' } keys %{$namespace}
              unless defined $type_filter;
      }
      else {
          return keys %{$namespace}
              unless defined $type_filter;
      }

      # NOTE:
      # or we can filter based on
      # type (SCALAR|ARRAY|HASH|CODE)
      if ($type_filter eq 'CODE') {
          return grep {
              # any non-typeglob in the symbol table is a constant or stub
              ref(\$namespace->{$_}) ne 'GLOB'
                  # regular subs are stored in the CODE slot of the typeglob
                  || defined(*{$namespace->{$_}}{CODE})
          } keys %{$namespace};
      }
      elsif ($type_filter eq 'SCALAR') {
          return grep {
              !(HAS_ISA_CACHE && $_ eq '::ISA::CACHE::') &&
              (BROKEN_SCALAR_INITIALIZATION
                  ? (ref(\$namespace->{$_}) eq 'GLOB'
                        && defined(${*{$namespace->{$_}}{'SCALAR'}}))
                  : (do {
                        my $entry = \$namespace->{$_};
                        ref($entry) eq 'GLOB'
                            && B::svref_2object($entry)->SV->isa('B::SV')
                    }))
          } keys %{$namespace};
      }
      else {
          return grep {
              ref(\$namespace->{$_}) eq 'GLOB'
                  && defined(*{$namespace->{$_}}{$type_filter})
          } keys %{$namespace};
      }
  }

  sub get_all_symbols {
      my ($self, $type_filter) = @_;

      my $namespace = $self->namespace;
      return { %{$namespace} } unless defined $type_filter;

      return {
          map { $_ => $self->get_symbol({name => $_, type => $type_filter}) }
              $self->list_all_symbols($type_filter)
      }
  }


  1;

  __END__

  =pod

  =encoding UTF-8

  =head1 NAME

  Package::Stash::PP - pure perl implementation of the Package::Stash API

  =head1 VERSION

  version 0.38

  =head1 SYNOPSIS

    use Package::Stash;

  =head1 DESCRIPTION

  This is a backend for L<Package::Stash> implemented in pure perl, for those without a compiler or who would like to use this inline in scripts.

  =head1 SEE ALSO

  =over 4

  =item * L<Class::MOP::Package>

  This module is a factoring out of code that used to live here

  =back

  =head1 SUPPORT

  You can find this documentation for this module with the perldoc command.

      perldoc Package::Stash

  You can also look for information at:

  =over 4

  =item * CPAN Ratings

  L<http://cpanratings.perl.org/d/Package-Stash>

  =item * RT: CPAN's request tracker

  L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Package-Stash>

  =item * Search CPAN

  L<http://search.cpan.org/dist/Package-Stash>

  =back

  =for Pod::Coverage BROKEN_ISA_ASSIGNMENT
  add_symbol
  get_all_symbols
  get_or_add_symbol
  get_symbol
  has_symbol
  list_all_symbols
  name
  namespace
  new
  remove_glob

  =head1 BUGS

  =over 4

  =item * remove_symbol also replaces the associated typeglob

  This can cause unexpected behavior when doing manipulation at compile time -
  removing subroutines will still allow them to be called from within the package
  as subroutines (although they will not be available as methods). This can be
  considered a feature in some cases (this is how L<namespace::clean> works, for
  instance), but should not be relied upon - use C<remove_glob> directly if you
  want this behavior.

  =item * Some minor memory leaks

  The pure perl implementation has a couple minor memory leaks (see the TODO
  tests in t/20-leaks.t) that I'm having a hard time tracking down - these may be
  core perl bugs, it's hard to tell.

  =back

  Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=Package-Stash>
  (or L<bug-Package-Stash@rt.cpan.org|mailto:bug-Package-Stash@rt.cpan.org>).

  =head1 AUTHOR

  Jesse Luehrs <doy at tozt dot net>

  Mostly copied from code from L<Class::MOP::Package>, by Stevan Little and the
  Moose Cabal.

  =head1 COPYRIGHT AND LICENSE

  This software is copyright (c) 2018 by Jesse Luehrs.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =cut
PACKAGE_STASH_PP

$fatpacked{"Reply/Plugin/TypeTiny.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'REPLY_PLUGIN_TYPETINY';
  package Reply::Plugin::TypeTiny;

  use strict;
  use warnings;

  BEGIN {
  	$Reply::Plugin::TypeTiny::AUTHORITY = 'cpan:TOBYINK';
  	$Reply::Plugin::TypeTiny::VERSION   = '1.000005';
  };

  require Reply::Plugin;
  our @ISA = 'Reply::Plugin';

  use Scalar::Util qw(blessed);
  use Term::ANSIColor;

  sub mangle_error {
  	my $self  = shift;
  	my ($err) = @_;

  	if (blessed $err and $err->isa("Error::TypeTiny::Assertion"))
  	{
  		my $explain = $err->explain;
  		if ($explain)
  		{
  			print color("cyan");
  			print "Error::TypeTiny::Assertion explain:\n";
  			$self->_explanation($explain, "");
  			local $| = 1;
  			print "\n";
  			print color("reset");
  		}
  	}

  	return @_;
  }

  sub _explanation
  {
  	my $self = shift;
  	my ($ex, $indent)  = @_;

  	for my $line (@$ex)
  	{
  		if (ref($line) eq q(ARRAY))
  		{
  			print "$indent * Explain:\n";
  			$self->_explanation($line, "$indent   ");
  		}
  		else
  		{
  			print "$indent * $line\n";
  		}
  	}
  }

  1;

  __END__

  =pod

  =encoding utf-8

  =head1 NAME

  Reply::Plugin::TypeTiny - improved type constraint exceptions in Reply

  =head1 STATUS

  This module is not covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  This is a small plugin to improve error messages in L<Reply>.
  Not massively tested.

  =begin trustme

  =item mangle_error

  =end trustme

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Error::TypeTiny::Assertion>, L<Reply>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

REPLY_PLUGIN_TYPETINY

$fatpacked{"Sub/Defer.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'SUB_DEFER';
  package Sub::Defer;
  use strict;
  use warnings;
  use Exporter qw(import);
  use Scalar::Util qw(weaken);
  use Carp qw(croak);

  our $VERSION = '2.006003';
  $VERSION = eval $VERSION;

  our @EXPORT = qw(defer_sub undefer_sub undefer_all);
  our @EXPORT_OK = qw(undefer_package defer_info);

  sub _getglob { no strict 'refs'; \*{$_[0]} }

  BEGIN {
    my $no_subname;
    *_subname
      = defined &Sub::Util::set_subname ? \&Sub::Util::set_subname
      : defined &Sub::Name::subname     ? \&Sub::Name::subname
      : (eval { require Sub::Util } && defined &Sub::Util::set_subname) ? \&Sub::Util::set_subname
      : (eval { require Sub::Name } && defined &Sub::Name::subname    ) ? \&Sub::Name::subname
      : ($no_subname = 1, sub { $_[1] });
    *_CAN_SUBNAME = $no_subname ? sub(){0} : sub(){1};
  }

  sub _name_coderef {
    shift if @_ > 2; # three args is (target, name, sub)
    _CAN_SUBNAME ? _subname(@_) : $_[1];
  }

  sub _install_coderef {
    my ($glob, $code) = (_getglob($_[0]), _name_coderef(@_));
    no warnings 'redefine';
    if (*{$glob}{CODE}) {
      *{$glob} = $code;
    }
    # perl will sometimes warn about mismatched prototypes coming from the
    # inheritance cache, so disable them if we aren't redefining a sub
    else {
      no warnings 'prototype';
      *{$glob} = $code;
    }
  }

  # We are dealing with three subs.  The first is the generator sub.  It is
  # provided by the user, so we cannot modify it.  When called, it generates the
  # undeferred sub.  This is also created, so it also cannot be modified.  These
  # are wrapped in a third sub.  The deferred sub is generated by us, and when
  # called it uses the generator sub to create the undeferred sub.  If it is a
  # named sub, it is installed in the symbol table, usually overwriting the
  # deferred sub.  From then on, the deferred sub will goto the undeferred sub
  # if it is called.
  #
  # In %DEFERRED we store array refs with information about these subs.  The key
  # is the stringified subref.  We have a CLONE method to fix this up in the
  # case of threading to deal with changing refaddrs.  The arrayrefs contain:
  #
  # 0. fully qualified sub name (or undef)
  # 1. generator sub
  # 2. options (attributes)
  # 3. scalar ref to undeferred sub (inner reference weakened)
  # 4. deferred sub (deferred only)
  # 5. info arrayref for undeferred sub (deferred only, after undefer)
  #
  # The deferred sub contains a strong reference to its info arrayref, and the
  # undeferred.

  our %DEFERRED;

  sub undefer_sub {
    my ($deferred) = @_;
    my $info = $DEFERRED{$deferred} or return $deferred;
    my ($target, $maker, $options, $undeferred_ref, $deferred_sub) = @$info;

    if (!(
      $deferred_sub && $deferred eq $deferred_sub
      || ${$undeferred_ref} && $deferred eq ${$undeferred_ref}
    )) {
      return $deferred;
    }

    return ${$undeferred_ref}
      if ${$undeferred_ref};
    ${$undeferred_ref} = my $made = $maker->();

    # make sure the method slot has not changed since deferral time
    if (defined($target) && $deferred eq *{_getglob($target)}{CODE}||'') {
      no warnings 'redefine';

      # I believe $maker already evals with the right package/name, so that
      # _install_coderef calls are not necessary --ribasushi
      *{_getglob($target)} = $made;
    }
    my $undefer_info = [ $target, $maker, $options, $undeferred_ref ];
    $info->[5] = $DEFERRED{$made} = $undefer_info;
    weaken ${$undefer_info->[3]};

    return $made;
  }

  sub undefer_all {
    undefer_sub($_) for keys %DEFERRED;
    return;
  }

  sub undefer_package {
    my $package = shift;
    undefer_sub($_)
      for grep {
        my $name = $DEFERRED{$_} && $DEFERRED{$_}[0];
        $name && $name =~ /^${package}::[^:]+$/
      } keys %DEFERRED;
    return;
  }

  sub defer_info {
    my ($deferred) = @_;
    my $info = $DEFERRED{$deferred||''} or return undef;

    my ($target, $maker, $options, $undeferred_ref, $deferred_sub) = @$info;
    if (!(
      $deferred_sub && $deferred eq $deferred_sub
      || ${$undeferred_ref} && $deferred eq ${$undeferred_ref}
    )) {
      delete $DEFERRED{$deferred};
      return undef;
    }
    [
      $target, $maker, $options,
      ( $undeferred_ref && $$undeferred_ref ? $$undeferred_ref : ()),
    ];
  }

  sub defer_sub {
    my ($target, $maker, $options) = @_;
    my $package;
    my $subname;
    ($package, $subname) = $target =~ /^(.*)::([^:]+)$/
      or croak "$target is not a fully qualified sub name!"
      if $target;
    $package ||= $options && $options->{package} || caller;
    my @attributes = @{$options && $options->{attributes} || []};
    if (@attributes) {
      /\A\w+(?:\(.*\))?\z/s || croak "invalid attribute $_"
        for @attributes;
    }
    my $deferred;
    my $undeferred;
    my $deferred_info = [ $target, $maker, $options, \$undeferred ];
    if (@attributes || $target && !_CAN_SUBNAME) {
      my $code
        =  q[#line ].(__LINE__+2).q[ "].__FILE__.qq["\n]
        . qq[package $package;\n]
        . ($target ? "sub $subname" : '+sub') . join('', map " :$_", @attributes)
        . q[ {
          package Sub::Defer;
          # uncoverable subroutine
          # uncoverable statement
          $undeferred ||= undefer_sub($deferred_info->[4]);
          goto &$undeferred; # uncoverable statement
          $undeferred; # fake lvalue return
        }]."\n"
        . ($target ? "\\&$subname" : '');
      my $e;
      $deferred = do {
        no warnings qw(redefine closure);
        local $@;
        eval $code or $e = $@; # uncoverable branch true
      };
      die $e if defined $e; # uncoverable branch true
    }
    else {
      # duplicated from above
      $deferred = sub {
        $undeferred ||= undefer_sub($deferred_info->[4]);
        goto &$undeferred;
      };
      _install_coderef($target, $deferred)
        if $target;
    }
    weaken($deferred_info->[4] = $deferred);
    weaken($DEFERRED{$deferred} = $deferred_info);
    return $deferred;
  }

  sub CLONE {
    %DEFERRED = map {
      defined $_ ? (
          $_->[4] ? ($_->[4] => $_)
        : ($_->[3] && ${$_->[3]}) ? (${$_->[3]} => $_)
        : ()
      ) : ()
    } values %DEFERRED;
  }

  1;
  __END__

  =head1 NAME

  Sub::Defer - Defer generation of subroutines until they are first called

  =head1 SYNOPSIS

   use Sub::Defer;

   my $deferred = defer_sub 'Logger::time_since_first_log' => sub {
      my $t = time;
      sub { time - $t };
   };

    Logger->time_since_first_log; # returns 0 and replaces itself
    Logger->time_since_first_log; # returns time - $t

  =head1 DESCRIPTION

  These subroutines provide the user with a convenient way to defer creation of
  subroutines and methods until they are first called.

  =head1 SUBROUTINES

  =head2 defer_sub

   my $coderef = defer_sub $name => sub { ... }, \%options;

  This subroutine returns a coderef that encapsulates the provided sub - when
  it is first called, the provided sub is called and is -itself- expected to
  return a subroutine which will be goto'ed to on subsequent calls.

  If a name is provided, this also installs the sub as that name - and when
  the subroutine is undeferred will re-install the final version for speed.

  Exported by default.

  =head3 Options

  A hashref of options can optionally be specified.

  =over 4

  =item package

  The package to generate the sub in.  Will be overridden by a fully qualified
  C<$name> option.  If not specified, will default to the caller's package.

  =item attributes

  The L<perlsub/Subroutine Attributes> to apply to the sub generated.  Should be
  specified as an array reference.

  =back

  =head2 undefer_sub

   my $coderef = undefer_sub \&Foo::name;

  If the passed coderef has been L<deferred|/defer_sub> this will "undefer" it.
  If the passed coderef has not been deferred, this will just return it.

  If this is confusing, take a look at the example in the L</SYNOPSIS>.

  Exported by default.

  =head2 defer_info

   my $data = defer_info $sub;
   my ($name, $generator, $options, $undeferred_sub) = @$data;

  Returns original arguments to defer_sub, plus the undeferred version if this
  sub has already been undeferred.

  Note that $sub can be either the original deferred version or the undeferred
  version for convenience.

  Not exported by default.

  =head2 undefer_all

   undefer_all();

  This will undefer all deferred subs in one go.  This can be very useful in a
  forking environment where child processes would each have to undefer the same
  subs.  By calling this just before you start forking children you can undefer
  all currently deferred subs in the parent so that the children do not have to
  do it.  Note this may bake the behavior of some subs that were intended to
  calculate their behavior later, so it shouldn't be used midway through a
  module load or class definition.

  Exported by default.

  =head2 undefer_package

    undefer_package($package);

  This undefers all deferred subs in a package.

  Not exported by default.

  =head1 SUPPORT

  See L<Sub::Quote> for support and contact information.

  =head1 AUTHORS

  See L<Sub::Quote> for authors.

  =head1 COPYRIGHT AND LICENSE

  See L<Sub::Quote> for the copyright and license.

  =cut
SUB_DEFER

$fatpacked{"Sub/Exporter/Progressive.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'SUB_EXPORTER_PROGRESSIVE';
  package Sub::Exporter::Progressive;
  $Sub::Exporter::Progressive::VERSION = '0.001013';
  use strict;
  use warnings;

  # ABSTRACT: Only use Sub::Exporter if you need it

  sub _croak {
    require Carp;
    &Carp::croak;
  }

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

     my $inner_target = caller;
     my $export_data = sub_export_options($inner_target, @args);

     my $full_exporter;
     no strict 'refs';
     no warnings 'once';
     @{"${inner_target}::EXPORT_OK"} = @{$export_data->{exports}};
     @{"${inner_target}::EXPORT"} = @{$export_data->{defaults}};
     %{"${inner_target}::EXPORT_TAGS"} = %{$export_data->{tags}};
     *{"${inner_target}::import"} = sub {
        use strict;
        my ($self, @args) = @_;

        if ( grep {
           length ref $_
              or
           $_ !~ / \A [:-]? \w+ \z /xm
        } @args ) {
           _croak 'your usage of Sub::Exporter::Progressive requires Sub::Exporter to be installed'
              unless eval { require Sub::Exporter };
           $full_exporter ||= Sub::Exporter::build_exporter($export_data->{original});

           goto $full_exporter;
        } elsif ( defined( (my ($num) = grep { m/^\d/ } @args)[0] ) ) {
           _croak "cannot export symbols with a leading digit: '$num'";
        } else {
           require Exporter;
           s/ \A - /:/xm for @args;
           @_ = ($self, @args);
           goto \&Exporter::import;
        }
     };
     return;
  }

  my $too_complicated = <<'DEATH';
  You are using Sub::Exporter::Progressive, but the features your program uses from
  Sub::Exporter cannot be implemented without Sub::Exporter, so you might as well
  just use vanilla Sub::Exporter
  DEATH

  sub sub_export_options {
     my ($inner_target, $setup, $options) = @_;

     my @exports;
     my @defaults;
     my %tags;

     if ( ($setup||'') eq '-setup') {
        my %options = %$options;

        OPTIONS:
        for my $opt (keys %options) {
           if ($opt eq 'exports') {

              _croak $too_complicated if ref $options{exports} ne 'ARRAY';
              @exports = @{$options{exports}};
              _croak $too_complicated if grep { length ref $_ } @exports;

           } elsif ($opt eq 'groups') {
              %tags = %{$options{groups}};
              for my $tagset (values %tags) {
                 _croak $too_complicated if grep {
                    length ref $_
                       or
                    $_ =~ / \A - (?! all \b ) /x
                 } @{$tagset};
              }
              @defaults = @{$tags{default} || [] };
           } else {
              _croak $too_complicated;
           }
        }
        @{$_} = map { / \A  [:-] all \z /x ? @exports : $_ } @{$_} for \@defaults, values %tags;
        $tags{all} ||= [ @exports ];
        my %exports = map { $_ => 1 } @exports;
        my @errors = grep { not $exports{$_} } @defaults;
        _croak join(', ', @errors) . " is not exported by the $inner_target module\n" if @errors;
     }

     return {
        exports => \@exports,
        defaults => \@defaults,
        original => $options,
        tags => \%tags,
     };
  }

  1;

  __END__

  =pod

  =encoding UTF-8

  =head1 NAME

  Sub::Exporter::Progressive - Only use Sub::Exporter if you need it

  =head1 VERSION

  version 0.001013

  =head1 SYNOPSIS

   package Syntax::Keyword::Gather;

   use Sub::Exporter::Progressive -setup => {
     exports => [qw( break gather gathered take )],
     groups => {
       default => [qw( break gather gathered take )],
     },
   };

   # elsewhere

   # uses Exporter for speed
   use Syntax::Keyword::Gather;

   # somewhere else

   # uses Sub::Exporter for features
   use Syntax::Keyword::Gather 'gather', take => { -as => 'grab' };

  =head1 DESCRIPTION

  L<Sub::Exporter> is an incredibly powerful module, but with that power comes
  great responsibility, er- as well as some runtime penalties.  This module
  is a C<Sub::Exporter> wrapper that will let your users just use L<Exporter>
  if all they are doing is picking exports, but use C<Sub::Exporter> if your
  users try to use C<Sub::Exporter>'s more advanced features, like
  renaming exports, if they try to use them.

  Note that this module will export C<@EXPORT>, C<@EXPORT_OK> and
  C<%EXPORT_TAGS> package variables for C<Exporter> to work.  Additionally, if
  your package uses advanced C<Sub::Exporter> features like currying, this module
  will only ever use C<Sub::Exporter>, so you might as well use it directly.

  =head1 CONTRIBUTORS

  ilmari - Dagfinn Ilmari Mannsåker (cpan:ILMARI) <ilmari@ilmari.org>

  mst - Matt S. Trout (cpan:MSTROUT) <mst@shadowcat.co.uk>

  leont - Leon Timmermans (cpan:LEONT) <leont@cpan.org>

  =head1 AUTHOR

  Arthur Axel "fREW" Schmidt <Sub-Exporter-Progressive@afoolishmanifesto.com>

  =head1 COPYRIGHT AND LICENSE

  This software is copyright (c) 2016 by Arthur Axel "fREW" Schmidt.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =cut
SUB_EXPORTER_PROGRESSIVE

$fatpacked{"Sub/Quote.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'SUB_QUOTE';
  package Sub::Quote;

  sub _clean_eval { eval $_[0] }

  use strict;
  use warnings;

  use Sub::Defer qw(defer_sub);
  use Scalar::Util qw(weaken);
  use Exporter qw(import);
  use Carp qw(croak);
  BEGIN { our @CARP_NOT = qw(Sub::Defer) }
  use B ();
  BEGIN {
    *_HAVE_IS_UTF8 = defined &utf8::is_utf8 ? sub(){1} : sub(){0};
    *_HAVE_PERLSTRING = defined &B::perlstring ? sub(){1} : sub(){0};
    *_BAD_BACKSLASH_ESCAPE = _HAVE_PERLSTRING() && "$]" == 5.010_000 ? sub(){1} : sub(){0};
  }

  our $VERSION = '2.006003';
  $VERSION = eval $VERSION;

  our @EXPORT = qw(quote_sub unquote_sub quoted_from_sub qsub);
  our @EXPORT_OK = qw(quotify capture_unroll inlinify sanitize_identifier);

  our %QUOTED;

  my %escape;
  if (_BAD_BACKSLASH_ESCAPE) {
    %escape = (
      (map +(chr($_) => sprintf '\x%02x', $_), 0 .. 0x31, 0x7f),
      "\t" => "\\t",
      "\n" => "\\n",
      "\r" => "\\r",
      "\f" => "\\f",
      "\b" => "\\b",
      "\a" => "\\a",
      "\e" => "\\e",
      (map +($_ => "\\$_"), qw(" \ $ @)),
    );
  }

  sub quotify {
    my $value = $_[0];
    no warnings 'numeric';
    ! defined $value     ? 'undef()'
    # numeric detection
    : (!(_HAVE_IS_UTF8 && utf8::is_utf8($value))
      && length( (my $dummy = '') & $value )
      && 0 + $value eq $value
    ) ? (
      $value != $value ? (
        $value eq -CORE::sin(9**9**9)
          ? '(-CORE::sin(9**9**9))' # -nan
          : 'CORE::sin(9**9**9)'    # nan
      )
      : $value == 9**9**9 ? '(9**9**9)'      # inf
      : $value == -9**9**9 ? '(-9**9**9)'    # -inf
      : int($value) == $value ? $value       # integer
      : do {
        my $float = sprintf('%.20f', $value);
        $float =~ s/(\.[0-9]+?)0+\z/$1/;
        $float;
      }
    )
    : !length($value) && eval { use warnings 'FATAL' => 'numeric'; $value == 0 } ? '(!1)' # false
    : _BAD_BACKSLASH_ESCAPE && _HAVE_IS_UTF8 && utf8::is_utf8($value) ? do {
      $value =~ s/(["\$\@\\[:cntrl:]]|[^\x00-\x7f])/
        $escape{$1} || sprintf('\x{%x}', ord($1))
      /ge;
      qq["$value"];
    }
    : _HAVE_PERLSTRING ? B::perlstring($value)
    : qq["\Q$value\E"];
  }

  sub sanitize_identifier {
    my $name = shift;
    $name =~ s/([_\W])/sprintf('_%x', ord($1))/ge;
    $name;
  }

  sub capture_unroll {
    my ($from, $captures, $indent) = @_;
    join(
      '',
      map {
        /^([\@\%\$])/
          or croak "capture key should start with \@, \% or \$: $_";
        (' ' x $indent).qq{my ${_} = ${1}{${from}->{${\quotify $_}}};\n};
      } keys %$captures
    );
  }

  sub inlinify {
    my ($code, $args, $extra, $local) = @_;
    $args = '()'
      if !defined $args;
    my $do = 'do { '.($extra||'');
    if ($code =~ s/^(\s*package\s+([a-zA-Z0-9:]+);)//) {
      $do .= $1;
    }
    if ($code =~ s{
      \A((?:\#\ BEGIN\ quote_sub\ PRELUDE\n.*?\#\ END\ quote_sub\ PRELUDE\n)?\s*)
      (^\s*) my \s* \(([^)]+)\) \s* = \s* \@_;
    }{}xms) {
      my ($pre, $indent, $code_args) = ($1, $2, $3);
      $do .= $pre;
      if ($code_args ne $args) {
        $do .= $indent . 'my ('.$code_args.') = ('.$args.'); ';
      }
    }
    elsif ($local || $args ne '@_') {
      $do .= ($local ? 'local ' : '').'@_ = ('.$args.'); ';
    }
    $do.$code.' }';
  }

  sub quote_sub {
    # HOLY DWIMMERY, BATMAN!
    # $name => $code => \%captures => \%options
    # $name => $code => \%captures
    # $name => $code
    # $code => \%captures => \%options
    # $code
    my $options =
      (ref($_[-1]) eq 'HASH' and ref($_[-2]) eq 'HASH')
        ? pop
        : {};
    my $captures = ref($_[-1]) eq 'HASH' ? pop : undef;
    undef($captures) if $captures && !keys %$captures;
    my $code = pop;
    my $name = $_[0];
    if ($name) {
      my $subname = $name;
      my $package = $subname =~ s/(.*)::// ? $1 : caller;
      $name = join '::', $package, $subname;
      croak qq{package name "$package" too long!}
        if length $package > 252;
      croak qq{package name "$package" is not valid!}
        unless $package =~ /^[^\d\W]\w*(?:::\w+)*$/;
      croak qq{sub name "$subname" too long!}
        if length $subname > 252;
      croak qq{sub name "$subname" is not valid!}
        unless $subname =~ /^[^\d\W]\w*$/;
    }
    my @caller = caller(0);
    my ($attributes, $file, $line) = @{$options}{qw(attributes file line)};
    if ($attributes) {
      /\A\w+(?:\(.*\))?\z/s || croak "invalid attribute $_"
        for @$attributes;
    }
    my $quoted_info = {
      name     => $name,
      code     => $code,
      captures => $captures,
      package      => (exists $options->{package}      ? $options->{package}      : $caller[0]),
      hints        => (exists $options->{hints}        ? $options->{hints}        : $caller[8]),
      warning_bits => (exists $options->{warning_bits} ? $options->{warning_bits} : $caller[9]),
      hintshash    => (exists $options->{hintshash}    ? $options->{hintshash}    : $caller[10]),
      ($attributes ? (attributes => $attributes) : ()),
      ($file       ? (file => $file) : ()),
      ($line       ? (line => $line) : ()),
    };
    my $unquoted;
    weaken($quoted_info->{unquoted} = \$unquoted);
    if ($options->{no_defer}) {
      my $fake = \my $var;
      local $QUOTED{$fake} = $quoted_info;
      my $sub = unquote_sub($fake);
      Sub::Defer::_install_coderef($name, $sub) if $name && !$options->{no_install};
      return $sub;
    }
    else {
      my $deferred = defer_sub(
        ($options->{no_install} ? undef : $name),
        sub {
          $unquoted if 0;
          unquote_sub($quoted_info->{deferred});
        },
        {
          ($attributes ? ( attributes => $attributes ) : ()),
          ($name ? () : ( package => $quoted_info->{package} )),
        },
      );
      weaken($quoted_info->{deferred} = $deferred);
      weaken($QUOTED{$deferred} = $quoted_info);
      return $deferred;
    }
  }

  sub _context {
    my $info = shift;
    $info->{context} ||= do {
      my ($package, $hints, $warning_bits, $hintshash, $file, $line)
        = @{$info}{qw(package hints warning_bits hintshash file line)};

      $line ||= 1
        if $file;

      my $line_mark = '';
      if ($line) {
        $line_mark = "#line ".($line-1);
        if ($file) {
          $line_mark .= qq{ "$file"};
        }
        $line_mark .= "\n";
      }

      $info->{context}
        ="# BEGIN quote_sub PRELUDE\n"
        ."package $package;\n"
        ."BEGIN {\n"
        ."  \$^H = ".quotify($hints).";\n"
        ."  \${^WARNING_BITS} = ".quotify($warning_bits).";\n"
        ."  \%^H = (\n"
        . join('', map
        "    ".quotify($_)." => ".quotify($hintshash->{$_}).",\n",
          keys %$hintshash)
        ."  );\n"
        ."}\n"
        .$line_mark
        ."# END quote_sub PRELUDE\n";
    };
  }

  sub quoted_from_sub {
    my ($sub) = @_;
    my $quoted_info = $QUOTED{$sub||''} or return undef;
    my ($name, $code, $captures, $unquoted, $deferred)
      = @{$quoted_info}{qw(name code captures unquoted deferred)};
    $code = _context($quoted_info) . $code;
    $unquoted &&= $$unquoted;
    if (($deferred && $deferred eq $sub)
        || ($unquoted && $unquoted eq $sub)) {
      return [ $name, $code, $captures, $unquoted, $deferred ];
    }
    return undef;
  }

  sub unquote_sub {
    my ($sub) = @_;
    my $quoted_info = $QUOTED{$sub} or return undef;
    my $unquoted = $quoted_info->{unquoted};
    unless ($unquoted && $$unquoted) {
      my ($name, $code, $captures, $package, $attributes)
        = @{$quoted_info}{qw(name code captures package attributes)};

      ($package, $name) = $name =~ /(.*)::(.*)/
        if $name;

      my %captures = $captures ? %$captures : ();
      $captures{'$_UNQUOTED'} = \$unquoted;
      $captures{'$_QUOTED'} = \$quoted_info;

      my $make_sub
        = "{\n"
        . capture_unroll("\$_[1]", \%captures, 2)
        . "  package ${package};\n"
        . (
          $name
            # disable the 'variable $x will not stay shared' warning since
            # we're not letting it escape from this scope anyway so there's
            # nothing trying to share it
            ? "  no warnings 'closure';\n  sub ${name} "
            : "  \$\$_UNQUOTED = sub "
        )
        . ($attributes ? join('', map ":$_ ", @$attributes) : '') . "{\n"
        . "  (\$_QUOTED,\$_UNQUOTED) if 0;\n"
        . _context($quoted_info)
        . $code
        . "  }".($name ? "\n  \$\$_UNQUOTED = \\&${name}" : '') . ";\n"
        . "}\n"
        . "1;\n";
      if (my $debug = $ENV{SUB_QUOTE_DEBUG}) {
        if ($debug =~ m{^([^\W\d]\w*(?:::\w+)*(?:::)?)$}) {
          my $filter = $1;
          my $match
            = $filter =~ /::$/ ? $package.'::'
            : $filter =~ /::/  ? $package.'::'.($name||'__ANON__')
            : ($name||'__ANON__');
          warn $make_sub
            if $match eq $filter;
        }
        elsif ($debug =~ m{\A/(.*)/\z}s) {
          my $filter = $1;
          warn $make_sub
            if $code =~ $filter;
        }
        else {
          warn $make_sub;
        }
      }
      {
        no strict 'refs';
        local *{"${package}::${name}"} if $name;
        my ($success, $e);
        {
          local $@;
          $success = _clean_eval($make_sub, \%captures);
          $e = $@;
        }
        unless ($success) {
          my $space = length($make_sub =~ tr/\n//);
          my $line = 0;
          $make_sub =~ s/^/sprintf "%${space}d: ", ++$line/emg;
          croak "Eval went very, very wrong:\n\n${make_sub}\n\n$e";
        }
        weaken($QUOTED{$$unquoted} = $quoted_info);
      }
    }
    $$unquoted;
  }

  sub qsub ($) {
    goto &quote_sub;
  }

  sub CLONE {
    my @quoted = map { defined $_ ? (
      $_->{unquoted} && ${$_->{unquoted}} ? (${ $_->{unquoted} } => $_) : (),
      $_->{deferred} ? ($_->{deferred} => $_) : (),
    ) : () } values %QUOTED;
    %QUOTED = @quoted;
    weaken($_) for values %QUOTED;
  }

  1;
  __END__

  =encoding utf-8

  =head1 NAME

  Sub::Quote - Efficient generation of subroutines via string eval

  =head1 SYNOPSIS

   package Silly;

   use Sub::Quote qw(quote_sub unquote_sub quoted_from_sub);

   quote_sub 'Silly::kitty', q{ print "meow" };

   quote_sub 'Silly::doggy', q{ print "woof" };

   my $sound = 0;

   quote_sub 'Silly::dagron',
     q{ print ++$sound % 2 ? 'burninate' : 'roar' },
     { '$sound' => \$sound };

  And elsewhere:

   Silly->kitty;  # meow
   Silly->doggy;  # woof
   Silly->dagron; # burninate
   Silly->dagron; # roar
   Silly->dagron; # burninate

  =head1 DESCRIPTION

  This package provides performant ways to generate subroutines from strings.

  =head1 SUBROUTINES

  =head2 quote_sub

   my $coderef = quote_sub 'Foo::bar', q{ print $x++ . "\n" }, { '$x' => \0 };

  Arguments: ?$name, $code, ?\%captures, ?\%options

  C<$name> is the subroutine where the coderef will be installed.

  C<$code> is a string that will be turned into code.

  C<\%captures> is a hashref of variables that will be made available to the
  code.  The keys should be the full name of the variable to be made available,
  including the sigil.  The values should be references to the values.  The
  variables will contain copies of the values.  See the L</SYNOPSIS>'s
  C<Silly::dagron> for an example using captures.

  Exported by default.

  =head3 options

  =over 2

  =item C<no_install>

  B<Boolean>.  Set this option to not install the generated coderef into the
  passed subroutine name on undefer.

  =item C<no_defer>

  B<Boolean>.  Prevents a Sub::Defer wrapper from being generated for the quoted
  sub.  If the sub will most likely be called at some point, setting this is a
  good idea.  For a sub that will most likely be inlined, it is not recommended.

  =item C<package>

  The package that the quoted sub will be evaluated in.  If not specified, the
  package from sub calling C<quote_sub> will be used.

  =item C<hints>

  The value of L<< C<$^H> | perlvar/$^H >> to use for the code being evaluated.
  This captures the settings of the L<strict> pragma.  If not specified, the value
  from the calling code will be used.

  =item C<warning_bits>

  The value of L<< C<${^WARNING_BITS}> | perlvar/${^WARNING_BITS} >> to use for
  the code being evaluated.  This captures the L<warnings> set.  If not specified,
  the warnings from the calling code will be used.

  =item C<%^H>

  The value of L<< C<%^H> | perlvar/%^H >> to use for the code being evaluated.
  This captures additional pragma settings.  If not specified, the value from the
  calling code will be used if possible (on perl 5.10+).

  =item C<attributes>

  The L<perlsub/Subroutine Attributes> to apply to the sub generated.  Should be
  specified as an array reference.  The attributes will be applied to both the
  generated sub and the deferred wrapper, if one is used.

  =item C<file>

  The apparent filename to use for the code being evaluated.

  =item C<line>

  The apparent line number
  to use for the code being evaluated.

  =back

  =head2 unquote_sub

   my $coderef = unquote_sub $sub;

  Forcibly replace subroutine with actual code.

  If $sub is not a quoted sub, this is a no-op.

  Exported by default.

  =head2 quoted_from_sub

   my $data = quoted_from_sub $sub;

   my ($name, $code, $captures, $compiled_sub) = @$data;

  Returns original arguments to quote_sub, plus the compiled version if this
  sub has already been unquoted.

  Note that $sub can be either the original quoted version or the compiled
  version for convenience.

  Exported by default.

  =head2 inlinify

   my $prelude = capture_unroll '$captures', {
     '$x' => 1,
     '$y' => 2,
   }, 4;

   my $inlined_code = inlinify q{
     my ($x, $y) = @_;

     print $x + $y . "\n";
   }, '$x, $y', $prelude;

  Takes a string of code, a string of arguments, a string of code which acts as a
  "prelude", and a B<Boolean> representing whether or not to localize the
  arguments.

  =head2 quotify

   my $quoted_value = quotify $value;

  Quotes a single (non-reference) scalar value for use in a code string.  Numbers
  aren't treated specially and will be quoted as strings, but undef will quoted as
  C<undef()>.

  =head2 capture_unroll

   my $prelude = capture_unroll '$captures', {
     '$x' => 1,
     '$y' => 2,
   }, 4;

  Arguments: $from, \%captures, $indent

  Generates a snippet of code which is suitable to be used as a prelude for
  L</inlinify>.  C<$from> is a string will be used as a hashref in the resulting
  code.  The keys of C<%captures> are the names of the variables and the values
  are ignored.  C<$indent> is the number of spaces to indent the result by.

  =head2 qsub

   my $hash = {
    coderef => qsub q{ print "hello"; },
    other   => 5,
   };

  Arguments: $code

  Works exactly like L</quote_sub>, but includes a prototype to only accept a
  single parameter.  This makes it easier to include in hash structures or lists.

  Exported by default.

  =head2 sanitize_identifier

   my $var_name = '$variable_for_' . sanitize_identifier('@name');
   quote_sub qq{ print \$${var_name} }, { $var_name => \$value };

  Arguments: $identifier

  Sanitizes a value so that it can be used in an identifier.

  =head1 ENVIRONMENT

  =head2 SUB_QUOTE_DEBUG

  Causes code to be output to C<STDERR> before being evaled.  Several forms are
  supported:

  =over 4

  =item C<1>

  All subs will be output.

  =item C</foo/>

  Subs will be output if their code matches the given regular expression.

  =item C<simple_identifier>

  Any sub with the given name will be output.

  =item C<Full::identifier>

  A sub matching the full name will be output.

  =item C<Package::Name::>

  Any sub in the given package (including anonymous subs) will be output.

  =back

  =head1 CAVEATS

  Much of this is just string-based code-generation, and as a result, a few
  caveats apply.

  =head2 return

  Calling C<return> from a quote_sub'ed sub will not likely do what you intend.
  Instead of returning from the code you defined in C<quote_sub>, it will return
  from the overall function it is composited into.

  So when you pass in:

     quote_sub q{  return 1 if $condition; $morecode }

  It might turn up in the intended context as follows:

    sub foo {

      <important code a>
      do {
        return 1 if $condition;
        $morecode
      };
      <important code b>

    }

  Which will obviously return from foo, when all you meant to do was return from
  the code context in quote_sub and proceed with running important code b.

  =head2 pragmas

  C<Sub::Quote> preserves the environment of the code creating the
  quoted subs.  This includes the package, strict, warnings, and any
  other lexical pragmas.  This is done by prefixing the code with a
  block that sets up a matching environment.  When inlining C<Sub::Quote>
  subs, care should be taken that user pragmas won't effect the rest
  of the code.

  =head1 SUPPORT

  Users' IRC: #moose on irc.perl.org

  =for :html
  L<(click for instant chatroom login)|http://chat.mibbit.com/#moose@irc.perl.org>

  Development and contribution IRC: #web-simple on irc.perl.org

  =for :html
  L<(click for instant chatroom login)|http://chat.mibbit.com/#web-simple@irc.perl.org>

  Bugtracker: L<https://rt.cpan.org/Public/Dist/Display.html?Name=Sub-Quote>

  Git repository: L<git://github.com/moose/Sub-Quote.git>

  Git browser: L<https://github.com/moose/Sub-Quote>

  =head1 AUTHOR

  mst - Matt S. Trout (cpan:MSTROUT) <mst@shadowcat.co.uk>

  =head1 CONTRIBUTORS

  frew - Arthur Axel "fREW" Schmidt (cpan:FREW) <frioux@gmail.com>

  ribasushi - Peter Rabbitson (cpan:RIBASUSHI) <ribasushi@cpan.org>

  Mithaldu - Christian Walde (cpan:MITHALDU) <walde.christian@googlemail.com>

  tobyink - Toby Inkster (cpan:TOBYINK) <tobyink@cpan.org>

  haarg - Graham Knop (cpan:HAARG) <haarg@cpan.org>

  bluefeet - Aran Deltac (cpan:BLUEFEET) <bluefeet@gmail.com>

  ether - Karen Etheridge (cpan:ETHER) <ether@cpan.org>

  dolmen - Olivier Mengué (cpan:DOLMEN) <dolmen@cpan.org>

  alexbio - Alessandro Ghedini (cpan:ALEXBIO) <alexbio@cpan.org>

  getty - Torsten Raudssus (cpan:GETTY) <torsten@raudss.us>

  arcanez - Justin Hunter (cpan:ARCANEZ) <justin.d.hunter@gmail.com>

  kanashiro - Lucas Kanashiro (cpan:KANASHIRO) <kanashiro.duarte@gmail.com>

  djerius - Diab Jerius (cpan:DJERIUS) <djerius@cfa.harvard.edu>

  =head1 COPYRIGHT

  Copyright (c) 2010-2016 the Sub::Quote L</AUTHOR> and L</CONTRIBUTORS>
  as listed above.

  =head1 LICENSE

  This library is free software and may be distributed under the same terms
  as perl itself. See L<http://dev.perl.org/licenses/>.

  =cut
SUB_QUOTE

$fatpacked{"Test/TypeTiny.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TEST_TYPETINY';
  package Test::TypeTiny;

  use strict;
  use warnings;

  use Test::More qw();
  use Scalar::Util qw(blessed);
  use Types::TypeTiny qw(to_TypeTiny);

  require Exporter::Tiny;
  our @ISA = 'Exporter::Tiny';

  BEGIN {
  	*EXTENDED_TESTING = $ENV{EXTENDED_TESTING} ? sub(){!!1} : sub(){!!0};
  };

  our $AUTHORITY = 'cpan:TOBYINK';
  our $VERSION   = '1.000005';
  our @EXPORT    = qw( should_pass should_fail ok_subtype );
  our @EXPORT_OK = qw( EXTENDED_TESTING matchfor );

  sub matchfor
  {
  	my @matchers = @_;
  	bless \@matchers, do {
  		package #
  		Test::TypeTiny::Internal::MATCHFOR;
  		use overload
  			q[==] => 'match',
  			q[eq] => 'match',
  			q[""] => 'to_string',
  			fallback => 1;
  		sub to_string {
  			$_[0][0]
  		}
  		sub match {
  			my ($self, $e) = @_;
  			my $does = Scalar::Util::blessed($e) ? ($e->can('DOES') || $e->can('isa')) : undef;
  			for my $s (@$self) {
  				return 1 if  ref($s) && $e =~ $s;
  				return 1 if !ref($s) && $does && $e->$does($s);
  			}
  			return;
  		}
  		__PACKAGE__;
  	};
  }

  sub _mk_message
  {
  	require Type::Tiny;
  	my ($template, $value) = @_;
  	sprintf($template, Type::Tiny::_dd($value));
  }

  sub ok_subtype
  {
  	my ($type, @s) = @_;
  	@_ = (
  		not(scalar grep !$_->is_subtype_of($type), @s),
  		sprintf("%s subtype: %s", $type, join q[, ], @s),
  	);
  	goto \&Test::More::ok;
  }

  eval(EXTENDED_TESTING ? <<'SLOW' : <<'FAST');

  sub should_pass
  {
  	my ($value, $type, $message) = @_;

  	local $Test::Builder::Level = $Test::Builder::Level + 1;
  	$type = to_TypeTiny($type) unless blessed($type) && $type->can("check");

  	my $strictures = $type->can("_strict_check");

  	my $test = "Test::Builder"->new->child(
  		$message || _mk_message("%s passes type constraint $type", $value),
  	);
  	$test->plan(tests => ($strictures ? 2 : 1));
  	$test->ok(!!$type->check($value), '->check');
  	$test->ok(!!$type->_strict_check($value), '->_strict_check') if $strictures;
  	$test->finalize;
  	return $test->is_passing;
  }

  sub should_fail
  {
  	my ($value, $type, $message) = @_;
  	$type = to_TypeTiny($type) unless blessed($type) && $type->can("check");

  	local $Test::Builder::Level = $Test::Builder::Level + 1;

  	my $strictures = $type->can("_strict_check");

  	my $test = "Test::Builder"->new->child(
  		$message || _mk_message("%s fails type constraint $type", $value),
  	);
  	$test->plan(tests => ($strictures ? 2 : 1));
  	$test->ok(!$type->check($value), '->check');
  	$test->ok(!$type->_strict_check($value), '->_strict_check') if $strictures;
  	$test->finalize;
  	return $test->is_passing;
  }

  SLOW

  sub should_pass
  {
  	my ($value, $type, $message) = @_;
  	$type = to_TypeTiny($type) unless blessed($type) && $type->can("check");
  	@_ = (
  		!!$type->check($value),
  		$message || _mk_message("%s passes type constraint $type", $value),
  	);
  	goto \&Test::More::ok;
  }

  sub should_fail
  {
  	my ($value, $type, $message) = @_;
  	$type = to_TypeTiny($type) unless blessed($type) && $type->can("check");
  	@_ = (
  		!$type->check($value),
  		$message || _mk_message("%s fails type constraint $type", $value),
  	);
  	goto \&Test::More::ok;
  }

  FAST

  1;

  __END__

  =pod

  =encoding utf-8

  =head1 NAME

  Test::TypeTiny - useful functions for testing the efficacy of type constraints

  =head1 SYNOPSIS

  =for test_synopsis
  BEGIN { die "SKIP: uses a module that doesn't exist as an example" };

     use strict;
     use warnings;
     use Test::More;
     use Test::TypeTiny;

     use Types::Mine qw(Integer Number);

     should_pass(1, Integer);
     should_pass(-1, Integer);
     should_pass(0, Integer);
     should_fail(2.5, Integer);

     ok_subtype(Number, Integer);

     done_testing;

  =head1 STATUS

  This module is covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  L<Test::TypeTiny> provides a few handy functions for testing type constraints.

  =head2 Functions

  =over

  =item C<< should_pass($value, $type, $test_name) >>

  =item C<< should_pass($value, $type) >>

  Test that passes iff C<< $value >> passes C<< $type->check >>.

  =item C<< should_fail($value, $type, $test_name) >>

  =item C<< should_fail($value, $type) >>

  Test that passes iff C<< $value >> fails C<< $type->check >>.

  =item C<< ok_subtype($type, @subtypes) >>

  Test that passes iff all C<< @subtypes >> are subtypes of C<< $type >>.

  =item C<< EXTENDED_TESTING >>

  Exportable boolean constant.

  =item C<< matchfor(@things) >>

  Assistant for matching exceptions. Not exported by default.
  See also L<Test::Fatal::matchfor>.

  =back

  =head1 ENVIRONMENT

  If the C<EXTENDED_TESTING> environment variable is set to true, this
  module will promote each C<should_pass> or C<should_fail> test into a
  subtest block and test the type constraint in both an inlined and
  non-inlined manner.

  This variable must be set at compile time (i.e. before this module is
  loaded).

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Type::Tiny>.

  For an alternative to C<should_pass>, see L<Test::Deep::Type> which will
  happily accept a Type::Tiny type constraint instead of a MooseX::Types one.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

TEST_TYPETINY

$fatpacked{"Try/Tiny.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TRY_TINY';
  package Try::Tiny; # git description: v0.29-2-g3b23a06
  use 5.006;
  # ABSTRACT: Minimal try/catch with proper preservation of $@

  our $VERSION = '0.30';

  use strict;
  use warnings;

  use Exporter 5.57 'import';
  our @EXPORT = our @EXPORT_OK = qw(try catch finally);

  use Carp;
  $Carp::Internal{+__PACKAGE__}++;

  BEGIN {
    my $su = $INC{'Sub/Util.pm'} && defined &Sub::Util::set_subname;
    my $sn = $INC{'Sub/Name.pm'} && eval { Sub::Name->VERSION(0.08) };
    unless ($su || $sn) {
      $su = eval { require Sub::Util; } && defined &Sub::Util::set_subname;
      unless ($su) {
        $sn = eval { require Sub::Name; Sub::Name->VERSION(0.08) };
      }
    }

    *_subname = $su ? \&Sub::Util::set_subname
              : $sn ? \&Sub::Name::subname
              : sub { $_[1] };
    *_HAS_SUBNAME = ($su || $sn) ? sub(){1} : sub(){0};
  }

  my %_finally_guards;

  # Need to prototype as @ not $$ because of the way Perl evaluates the prototype.
  # Keeping it at $$ means you only ever get 1 sub because we need to eval in a list
  # context & not a scalar one

  sub try (&;@) {
    my ( $try, @code_refs ) = @_;

    # we need to save this here, the eval block will be in scalar context due
    # to $failed
    my $wantarray = wantarray;

    # work around perl bug by explicitly initializing these, due to the likelyhood
    # this will be used in global destruction (perl rt#119311)
    my ( $catch, @finally ) = ();

    # find labeled blocks in the argument list.
    # catch and finally tag the blocks by blessing a scalar reference to them.
    foreach my $code_ref (@code_refs) {

      if ( ref($code_ref) eq 'Try::Tiny::Catch' ) {
        croak 'A try() may not be followed by multiple catch() blocks'
          if $catch;
        $catch = ${$code_ref};
      } elsif ( ref($code_ref) eq 'Try::Tiny::Finally' ) {
        push @finally, ${$code_ref};
      } else {
        croak(
          'try() encountered an unexpected argument ('
        . ( defined $code_ref ? $code_ref : 'undef' )
        . ') - perhaps a missing semi-colon before or'
        );
      }
    }

    # FIXME consider using local $SIG{__DIE__} to accumulate all errors. It's
    # not perfect, but we could provide a list of additional errors for
    # $catch->();

    # name the blocks if we have Sub::Name installed
    _subname(caller().'::try {...} ' => $try)
      if _HAS_SUBNAME;

    # set up scope guards to invoke the finally blocks at the end.
    # this should really be a function scope lexical variable instead of
    # file scope + local but that causes issues with perls < 5.20 due to
    # perl rt#119311
    local $_finally_guards{guards} = [
      map { Try::Tiny::ScopeGuard->_new($_) }
      @finally
    ];

    # save the value of $@ so we can set $@ back to it in the beginning of the eval
    # and restore $@ after the eval finishes
    my $prev_error = $@;

    my ( @ret, $error );

    # failed will be true if the eval dies, because 1 will not be returned
    # from the eval body
    my $failed = not eval {
      $@ = $prev_error;

      # evaluate the try block in the correct context
      if ( $wantarray ) {
        @ret = $try->();
      } elsif ( defined $wantarray ) {
        $ret[0] = $try->();
      } else {
        $try->();
      };

      return 1; # properly set $failed to false
    };

    # preserve the current error and reset the original value of $@
    $error = $@;
    $@ = $prev_error;

    # at this point $failed contains a true value if the eval died, even if some
    # destructor overwrote $@ as the eval was unwinding.
    if ( $failed ) {
      # pass $error to the finally blocks
      push @$_, $error for @{$_finally_guards{guards}};

      # if we got an error, invoke the catch block.
      if ( $catch ) {
        # This works like given($error), but is backwards compatible and
        # sets $_ in the dynamic scope for the body of C<$catch>
        for ($error) {
          return $catch->($error);
        }

        # in case when() was used without an explicit return, the C<for>
        # loop will be aborted and there's no useful return value
      }

      return;
    } else {
      # no failure, $@ is back to what it was, everything is fine
      return $wantarray ? @ret : $ret[0];
    }
  }

  sub catch (&;@) {
    my ( $block, @rest ) = @_;

    croak 'Useless bare catch()' unless wantarray;

    _subname(caller().'::catch {...} ' => $block)
      if _HAS_SUBNAME;
    return (
      bless(\$block, 'Try::Tiny::Catch'),
      @rest,
    );
  }

  sub finally (&;@) {
    my ( $block, @rest ) = @_;

    croak 'Useless bare finally()' unless wantarray;

    _subname(caller().'::finally {...} ' => $block)
      if _HAS_SUBNAME;
    return (
      bless(\$block, 'Try::Tiny::Finally'),
      @rest,
    );
  }

  {
    package # hide from PAUSE
      Try::Tiny::ScopeGuard;

    use constant UNSTABLE_DOLLARAT => ("$]" < '5.013002') ? 1 : 0;

    sub _new {
      shift;
      bless [ @_ ];
    }

    sub DESTROY {
      my ($code, @args) = @{ $_[0] };

      local $@ if UNSTABLE_DOLLARAT;
      eval {
        $code->(@args);
        1;
      } or do {
        warn
          "Execution of finally() block $code resulted in an exception, which "
        . '*CAN NOT BE PROPAGATED* due to fundamental limitations of Perl. '
        . 'Your program will continue as if this event never took place. '
        . "Original exception text follows:\n\n"
        . (defined $@ ? $@ : '$@ left undefined...')
        . "\n"
        ;
      }
    }
  }

  __PACKAGE__

  __END__

  =pod

  =encoding UTF-8

  =head1 NAME

  Try::Tiny - Minimal try/catch with proper preservation of $@

  =head1 VERSION

  version 0.30

  =head1 SYNOPSIS

  You can use Try::Tiny's C<try> and C<catch> to expect and handle exceptional
  conditions, avoiding quirks in Perl and common mistakes:

    # handle errors with a catch handler
    try {
      die "foo";
    } catch {
      warn "caught error: $_"; # not $@
    };

  You can also use it like a standalone C<eval> to catch and ignore any error
  conditions.  Obviously, this is an extreme measure not to be undertaken
  lightly:

    # just silence errors
    try {
      die "foo";
    };

  =head1 DESCRIPTION

  This module provides bare bones C<try>/C<catch>/C<finally> statements that are designed to
  minimize common mistakes with eval blocks, and NOTHING else.

  This is unlike L<TryCatch> which provides a nice syntax and avoids adding
  another call stack layer, and supports calling C<return> from the C<try> block to
  return from the parent subroutine. These extra features come at a cost of a few
  dependencies, namely L<Devel::Declare> and L<Scope::Upper> which are
  occasionally problematic, and the additional catch filtering uses L<Moose>
  type constraints which may not be desirable either.

  The main focus of this module is to provide simple and reliable error handling
  for those having a hard time installing L<TryCatch>, but who still want to
  write correct C<eval> blocks without 5 lines of boilerplate each time.

  It's designed to work as correctly as possible in light of the various
  pathological edge cases (see L</BACKGROUND>) and to be compatible with any style
  of error values (simple strings, references, objects, overloaded objects, etc).

  If the C<try> block dies, it returns the value of the last statement executed in
  the C<catch> block, if there is one. Otherwise, it returns C<undef> in scalar
  context or the empty list in list context. The following examples all
  assign C<"bar"> to C<$x>:

    my $x = try { die "foo" } catch { "bar" };
    my $x = try { die "foo" } || "bar";
    my $x = (try { die "foo" }) // "bar";

    my $x = eval { die "foo" } || "bar";

  You can add C<finally> blocks, yielding the following:

    my $x;
    try { die 'foo' } finally { $x = 'bar' };
    try { die 'foo' } catch { warn "Got a die: $_" } finally { $x = 'bar' };

  C<finally> blocks are always executed making them suitable for cleanup code
  which cannot be handled using local.  You can add as many C<finally> blocks to a
  given C<try> block as you like.

  Note that adding a C<finally> block without a preceding C<catch> block
  suppresses any errors. This behaviour is consistent with using a standalone
  C<eval>, but it is not consistent with C<try>/C<finally> patterns found in
  other programming languages, such as Java, Python, Javascript or C#. If you
  learnt the C<try>/C<finally> pattern from one of these languages, watch out for
  this.

  =head1 EXPORTS

  All functions are exported by default using L<Exporter>.

  If you need to rename the C<try>, C<catch> or C<finally> keyword consider using
  L<Sub::Import> to get L<Sub::Exporter>'s flexibility.

  =over 4

  =item try (&;@)

  Takes one mandatory C<try> subroutine, an optional C<catch> subroutine and C<finally>
  subroutine.

  The mandatory subroutine is evaluated in the context of an C<eval> block.

  If no error occurred the value from the first block is returned, preserving
  list/scalar context.

  If there was an error and the second subroutine was given it will be invoked
  with the error in C<$_> (localized) and as that block's first and only
  argument.

  C<$@> does B<not> contain the error. Inside the C<catch> block it has the same
  value it had before the C<try> block was executed.

  Note that the error may be false, but if that happens the C<catch> block will
  still be invoked.

  Once all execution is finished then the C<finally> block, if given, will execute.

  =item catch (&;@)

  Intended to be used in the second argument position of C<try>.

  Returns a reference to the subroutine it was given but blessed as
  C<Try::Tiny::Catch> which allows try to decode correctly what to do
  with this code reference.

    catch { ... }

  Inside the C<catch> block the caught error is stored in C<$_>, while previous
  value of C<$@> is still available for use.  This value may or may not be
  meaningful depending on what happened before the C<try>, but it might be a good
  idea to preserve it in an error stack.

  For code that captures C<$@> when throwing new errors (i.e.
  L<Class::Throwable>), you'll need to do:

    local $@ = $_;

  =item finally (&;@)

    try     { ... }
    catch   { ... }
    finally { ... };

  Or

    try     { ... }
    finally { ... };

  Or even

    try     { ... }
    finally { ... }
    catch   { ... };

  Intended to be the second or third element of C<try>. C<finally> blocks are always
  executed in the event of a successful C<try> or if C<catch> is run. This allows
  you to locate cleanup code which cannot be done via C<local()> e.g. closing a file
  handle.

  When invoked, the C<finally> block is passed the error that was caught.  If no
  error was caught, it is passed nothing.  (Note that the C<finally> block does not
  localize C<$_> with the error, since unlike in a C<catch> block, there is no way
  to know if C<$_ == undef> implies that there were no errors.) In other words,
  the following code does just what you would expect:

    try {
      die_sometimes();
    } catch {
      # ...code run in case of error
    } finally {
      if (@_) {
        print "The try block died with: @_\n";
      } else {
        print "The try block ran without error.\n";
      }
    };

  B<You must always do your own error handling in the C<finally> block>. C<Try::Tiny> will
  not do anything about handling possible errors coming from code located in these
  blocks.

  Furthermore B<exceptions in C<finally> blocks are not trappable and are unable
  to influence the execution of your program>. This is due to limitation of
  C<DESTROY>-based scope guards, which C<finally> is implemented on top of. This
  may change in a future version of Try::Tiny.

  In the same way C<catch()> blesses the code reference this subroutine does the same
  except it bless them as C<Try::Tiny::Finally>.

  =back

  =head1 BACKGROUND

  There are a number of issues with C<eval>.

  =head2 Clobbering $@

  When you run an C<eval> block and it succeeds, C<$@> will be cleared, potentially
  clobbering an error that is currently being caught.

  This causes action at a distance, clearing previous errors your caller may have
  not yet handled.

  C<$@> must be properly localized before invoking C<eval> in order to avoid this
  issue.

  More specifically,
  L<before Perl version 5.14.0|perl5140delta/"Exception Handling">
  C<$@> was clobbered at the beginning of the C<eval>, which
  also made it impossible to capture the previous error before you die (for
  instance when making exception objects with error stacks).

  For this reason C<try> will actually set C<$@> to its previous value (the one
  available before entering the C<try> block) in the beginning of the C<eval>
  block.

  =head2 Localizing $@ silently masks errors

  Inside an C<eval> block, C<die> behaves sort of like:

    sub die {
      $@ = $_[0];
      return_undef_from_eval();
    }

  This means that if you were polite and localized C<$@> you can't die in that
  scope, or your error will be discarded (printing "Something's wrong" instead).

  The workaround is very ugly:

    my $error = do {
      local $@;
      eval { ... };
      $@;
    };

    ...
    die $error;

  =head2 $@ might not be a true value

  This code is wrong:

    if ( $@ ) {
      ...
    }

  because due to the previous caveats it may have been unset.

  C<$@> could also be an overloaded error object that evaluates to false, but
  that's asking for trouble anyway.

  The classic failure mode (fixed in L<Perl 5.14.0|perl5140delta/"Exception Handling">) is:

    sub Object::DESTROY {
      eval { ... }
    }

    eval {
      my $obj = Object->new;

      die "foo";
    };

    if ( $@ ) {

    }

  In this case since C<Object::DESTROY> is not localizing C<$@> but still uses
  C<eval>, it will set C<$@> to C<"">.

  The destructor is called when the stack is unwound, after C<die> sets C<$@> to
  C<"foo at Foo.pm line 42\n">, so by the time C<if ( $@ )> is evaluated it has
  been cleared by C<eval> in the destructor.

  The workaround for this is even uglier than the previous ones. Even though we
  can't save the value of C<$@> from code that doesn't localize, we can at least
  be sure the C<eval> was aborted due to an error:

    my $failed = not eval {
      ...

      return 1;
    };

  This is because an C<eval> that caught a C<die> will always return a false
  value.

  =head1 ALTERNATE SYNTAX

  Using Perl 5.10 you can use L<perlsyn/"Switch statements"> (but please don't,
  because that syntax has since been deprecated because there was too much
  unexpected magical behaviour).

  =for stopwords topicalizer

  The C<catch> block is invoked in a topicalizer context (like a C<given> block),
  but note that you can't return a useful value from C<catch> using the C<when>
  blocks without an explicit C<return>.

  This is somewhat similar to Perl 6's C<CATCH> blocks. You can use it to
  concisely match errors:

    try {
      require Foo;
    } catch {
      when (/^Can't locate .*?\.pm in \@INC/) { } # ignore
      default { die $_ }
    };

  =head1 CAVEATS

  =over 4

  =item *

  C<@_> is not available within the C<try> block, so you need to copy your
  argument list. In case you want to work with argument values directly via C<@_>
  aliasing (i.e. allow C<$_[1] = "foo">), you need to pass C<@_> by reference:

    sub foo {
      my ( $self, @args ) = @_;
      try { $self->bar(@args) }
    }

  or

    sub bar_in_place {
      my $self = shift;
      my $args = \@_;
      try { $_ = $self->bar($_) for @$args }
    }

  =item *

  C<return> returns from the C<try> block, not from the parent sub (note that
  this is also how C<eval> works, but not how L<TryCatch> works):

    sub parent_sub {
      try {
        die;
      }
      catch {
        return;
      };

      say "this text WILL be displayed, even though an exception is thrown";
    }

  Instead, you should capture the return value:

    sub parent_sub {
      my $success = try {
        die;
        1;
      };
      return unless $success;

      say "This text WILL NEVER appear!";
    }
    # OR
    sub parent_sub_with_catch {
      my $success = try {
        die;
        1;
      }
      catch {
        # do something with $_
        return undef; #see note
      };
      return unless $success;

      say "This text WILL NEVER appear!";
    }

  Note that if you have a C<catch> block, it must return C<undef> for this to work,
  since if a C<catch> block exists, its return value is returned in place of C<undef>
  when an exception is thrown.

  =item *

  C<try> introduces another caller stack frame. L<Sub::Uplevel> is not used. L<Carp>
  will not report this when using full stack traces, though, because
  C<%Carp::Internal> is used. This lack of magic is considered a feature.

  =for stopwords unhygienically

  =item *

  The value of C<$_> in the C<catch> block is not guaranteed to be the value of
  the exception thrown (C<$@>) in the C<try> block.  There is no safe way to
  ensure this, since C<eval> may be used unhygienically in destructors.  The only
  guarantee is that the C<catch> will be called if an exception is thrown.

  =item *

  The return value of the C<catch> block is not ignored, so if testing the result
  of the expression for truth on success, be sure to return a false value from
  the C<catch> block:

    my $obj = try {
      MightFail->new;
    } catch {
      ...

      return; # avoid returning a true value;
    };

    return unless $obj;

  =item *

  C<$SIG{__DIE__}> is still in effect.

  Though it can be argued that C<$SIG{__DIE__}> should be disabled inside of
  C<eval> blocks, since it isn't people have grown to rely on it. Therefore in
  the interests of compatibility, C<try> does not disable C<$SIG{__DIE__}> for
  the scope of the error throwing code.

  =item *

  Lexical C<$_> may override the one set by C<catch>.

  For example Perl 5.10's C<given> form uses a lexical C<$_>, creating some
  confusing behavior:

    given ($foo) {
      when (...) {
        try {
          ...
        } catch {
          warn $_; # will print $foo, not the error
          warn $_[0]; # instead, get the error like this
        }
      }
    }

  Note that this behavior was changed once again in
  L<Perl5 version 18|https://metacpan.org/module/perldelta#given-now-aliases-the-global-_>.
  However, since the entirety of lexical C<$_> is now L<considered experimental
  |https://metacpan.org/module/perldelta#Lexical-_-is-now-experimental>, it
  is unclear whether the new version 18 behavior is final.

  =back

  =head1 SEE ALSO

  =over 4

  =item L<TryCatch>

  Much more feature complete, more convenient semantics, but at the cost of
  implementation complexity.

  =item L<autodie>

  Automatic error throwing for builtin functions and more. Also designed to
  work well with C<given>/C<when>.

  =item L<Throwable>

  A lightweight role for rolling your own exception classes.

  =item L<Error>

  Exception object implementation with a C<try> statement. Does not localize
  C<$@>.

  =item L<Exception::Class::TryCatch>

  Provides a C<catch> statement, but properly calling C<eval> is your
  responsibility.

  The C<try> keyword pushes C<$@> onto an error stack, avoiding some of the
  issues with C<$@>, but you still need to localize to prevent clobbering.

  =back

  =head1 LIGHTNING TALK

  I gave a lightning talk about this module, you can see the slides (Firefox
  only):

  L<http://web.archive.org/web/20100628040134/http://nothingmuch.woobling.org/talks/takahashi.xul>

  Or read the source:

  L<http://web.archive.org/web/20100305133605/http://nothingmuch.woobling.org/talks/yapc_asia_2009/try_tiny.yml>

  =head1 SUPPORT

  Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=Try-Tiny>
  (or L<bug-Try-Tiny@rt.cpan.org|mailto:bug-Try-Tiny@rt.cpan.org>).

  =head1 AUTHORS

  =over 4

  =item *

  יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>

  =item *

  Jesse Luehrs <doy@tozt.net>

  =back

  =head1 CONTRIBUTORS

  =for stopwords Karen Etheridge Peter Rabbitson Ricardo Signes Mark Fowler Graham Knop Lukas Mai Aristotle Pagaltzis Dagfinn Ilmari Mannsåker Paul Howarth Rudolf Leermakers anaxagoras awalker chromatic Alex cm-perl Andrew Yates David Lowe Glenn Hans Dieter Pearcey Jens Berthold Jonathan Yu Marc Mims Stosberg Pali

  =over 4

  =item *

  Karen Etheridge <ether@cpan.org>

  =item *

  Peter Rabbitson <ribasushi@cpan.org>

  =item *

  Ricardo Signes <rjbs@cpan.org>

  =item *

  Mark Fowler <mark@twoshortplanks.com>

  =item *

  Graham Knop <haarg@haarg.org>

  =item *

  Lukas Mai <l.mai@web.de>

  =item *

  Aristotle Pagaltzis <pagaltzis@gmx.de>

  =item *

  Dagfinn Ilmari Mannsåker <ilmari@ilmari.org>

  =item *

  Paul Howarth <paul@city-fan.org>

  =item *

  Rudolf Leermakers <rudolf@hatsuseno.org>

  =item *

  anaxagoras <walkeraj@gmail.com>

  =item *

  awalker <awalker@sourcefire.com>

  =item *

  chromatic <chromatic@wgz.org>

  =item *

  Alex <alex@koban.(none)>

  =item *

  cm-perl <cm-perl@users.noreply.github.com>

  =item *

  Andrew Yates <ayates@haddock.local>

  =item *

  David Lowe <davidl@lokku.com>

  =item *

  Glenn Fowler <cebjyre@cpan.org>

  =item *

  Hans Dieter Pearcey <hdp@weftsoar.net>

  =item *

  Jens Berthold <jens@jebecs.de>

  =item *

  Jonathan Yu <JAWNSY@cpan.org>

  =item *

  Marc Mims <marc@questright.com>

  =item *

  Mark Stosberg <mark@stosberg.com>

  =item *

  Pali <pali@cpan.org>

  =back

  =head1 COPYRIGHT AND LICENCE

  This software is Copyright (c) 2009 by יובל קוג'מן (Yuval Kogman).

  This is free software, licensed under:

    The MIT (X11) License

  =cut
TRY_TINY

$fatpacked{"Type/Coercion.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TYPE_COERCION';
  package Type::Coercion;

  use 5.006001;
  use strict;
  use warnings;

  BEGIN {
  	$Type::Coercion::AUTHORITY = 'cpan:TOBYINK';
  	$Type::Coercion::VERSION   = '1.000005';
  }

  use Eval::TypeTiny qw<>;
  use Scalar::Util qw< blessed >;
  use Types::TypeTiny qw<>;

  sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }

  use overload
  	q("")      => sub { caller =~ m{^(Moo::HandleMoose|Sub::Quote)} ? overload::StrVal($_[0]) : $_[0]->display_name },
  	q(bool)    => sub { 1 },
  	q(&{})     => "_overload_coderef",
  	fallback   => 1,
  ;

  BEGIN {
  	require Type::Tiny;
  	overload->import(
  		q(~~)    => sub { $_[0]->has_coercion_for_value($_[1]) },
  		fallback => 1, # 5.10 loses the fallback otherwise
  	) if Type::Tiny::SUPPORT_SMARTMATCH();
  }

  sub _overload_coderef
  {
  	my $self = shift;

  	if ("Sub::Quote"->can("quote_sub") && $self->can_be_inlined)
  	{
  		$self->{_overload_coderef} = Sub::Quote::quote_sub($self->inline_coercion('$_[0]'))
  			if !$self->{_overload_coderef} || !$self->{_sub_quoted}++;
  	}
  	else
  	{
  		$self->{_overload_coderef} ||= sub { $self->coerce(@_) };
  	}

  	$self->{_overload_coderef};
  }

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

  	$params{name} = '__ANON__' unless exists($params{name});
  	my $C = delete($params{type_coercion_map}) || [];
  	my $F = delete($params{frozen});

  	my $self = bless \%params, $class;
  	$self->add_type_coercions(@$C) if @$C;
  	$self->_preserve_type_constraint;
  	Scalar::Util::weaken($self->{type_constraint}); # break ref cycle
  	$self->{frozen} = $F if $F;

  	unless ($self->is_anon)
  	{
  		# First try a fast ASCII-only expression, but fall back to Unicode
  		$self->name =~ /^_{0,2}[A-Z][A-Za-z0-9_]+$/sm
  			or eval q( use 5.008; $self->name =~ /^_{0,2}\p{Lu}[\p{L}0-9_]+$/sm )
  			or _croak '"%s" is not a valid coercion name', $self->name;
  	}

  	return $self;
  }

  sub name                   { $_[0]{name} }
  sub display_name           { $_[0]{display_name}      ||= $_[0]->_build_display_name }
  sub library                { $_[0]{library} }
  sub type_constraint        { $_[0]{type_constraint}   ||= $_[0]->_maybe_restore_type_constraint }
  sub type_coercion_map      { $_[0]{type_coercion_map} ||= [] }
  sub moose_coercion         { $_[0]{moose_coercion}    ||= $_[0]->_build_moose_coercion }
  sub compiled_coercion      { $_[0]{compiled_coercion} ||= $_[0]->_build_compiled_coercion }
  sub frozen                 { $_[0]{frozen}            ||= 0 }
  sub coercion_generator     { $_[0]{coercion_generator} }
  sub parameters             { $_[0]{parameters} }
  sub parameterized_from     { $_[0]{parameterized_from} }

  sub has_library            { exists $_[0]{library} }
  sub has_type_constraint    { defined $_[0]->type_constraint } # sic
  sub has_coercion_generator { exists $_[0]{coercion_generator} }
  sub has_parameters         { exists $_[0]{parameters} }

  sub _preserve_type_constraint
  {
  	my $self = shift;
  	$self->{_compiled_type_constraint_check} = $self->{type_constraint}->compiled_check
  		if $self->{type_constraint};
  }

  sub _maybe_restore_type_constraint
  {
  	my $self = shift;
  	if ( my $check = $self->{_compiled_type_constraint_check} )
  	{
  		return Type::Tiny->new(constraint => $check);
  	}
  	return;
  }

  sub add
  {
  	my $class = shift;
  	my ($x, $y, $swap) = @_;

  	Types::TypeTiny::TypeTiny->check($x) and return $x->plus_fallback_coercions($y);
  	Types::TypeTiny::TypeTiny->check($y) and return $y->plus_coercions($x);

  	_croak "Attempt to add $class to something that is not a $class"
  		unless blessed($x) && blessed($y) && $x->isa($class) && $y->isa($class);

  	($y, $x) = ($x, $y) if $swap;

  	my %opts;
  	if ($x->has_type_constraint and $y->has_type_constraint and $x->type_constraint == $y->type_constraint)
  	{
  		$opts{type_constraint} = $x->type_constraint;
  	}
  	elsif ($x->has_type_constraint and $y->has_type_constraint)
  	{
  #		require Type::Tiny::Union;
  #		$opts{type_constraint} = "Type::Tiny::Union"->new(
  #			type_constraints => [ $x->type_constraint, $y->type_constraint ],
  #		);
  	}
  	$opts{display_name} ||= "$x+$y";
  	delete $opts{display_name} if $opts{display_name} eq '__ANON__+__ANON__';

  	my $new = $class->new(%opts);
  	$new->add_type_coercions( @{$x->type_coercion_map} );
  	$new->add_type_coercions( @{$y->type_coercion_map} );
  	return $new;
  }

  sub _build_display_name
  {
  	shift->name;
  }

  sub qualified_name
  {
  	my $self = shift;

  	if ($self->has_library and not $self->is_anon)
  	{
  		return sprintf("%s::%s", $self->library, $self->name);
  	}

  	return $self->name;
  }

  sub is_anon
  {
  	my $self = shift;
  	$self->name eq "__ANON__";
  }

  sub _clear_compiled_coercion
  {
  	delete $_[0]{_overload_coderef};
  	delete $_[0]{compiled_coercion};
  }

  sub freeze                    { $_[0]{frozen} = 1; $_[0] }
  sub i_really_want_to_unfreeze { $_[0]{frozen} = 0; $_[0] }

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

  sub assert_coerce
  {
  	my $self = shift;
  	my $r = $self->coerce(@_);
  	$self->type_constraint->assert_valid($r)
  		if $self->has_type_constraint;
  	return $r;
  }

  sub has_coercion_for_type
  {
  	my $self = shift;
  	my $type = Types::TypeTiny::to_TypeTiny($_[0]);

  	return "0 but true"
  		if $self->has_type_constraint && $type->is_a_type_of($self->type_constraint);

  	my $c = $self->type_coercion_map;
  	for (my $i = 0; $i <= $#$c; $i += 2)
  	{
  		return !!1 if $type->is_a_type_of($c->[$i]);
  	}
  	return;
  }

  sub has_coercion_for_value
  {
  	my $self = shift;
  	local $_ = $_[0];

  	return "0 but true"
  		if $self->has_type_constraint && $self->type_constraint->check(@_);

  	my $c = $self->type_coercion_map;
  	for (my $i = 0; $i <= $#$c; $i += 2)
  	{
  		return !!1 if $c->[$i]->check(@_);
  	}
  	return;
  }

  sub add_type_coercions
  {
  	my $self = shift;
  	my @args = @_;

  	_croak "Attempt to add coercion code to a Type::Coercion which has been frozen" if $self->frozen;

  	while (@args)
  	{
  		my $type     = Types::TypeTiny::to_TypeTiny(shift @args);
  		my $coercion = shift @args;

  		_croak "Types must be blessed Type::Tiny objects"
  			unless Types::TypeTiny::TypeTiny->check($type);
  		_croak "Coercions must be code references or strings"
  			unless Types::TypeTiny::StringLike->check($coercion) || Types::TypeTiny::CodeLike->check($coercion);

  		push @{$self->type_coercion_map}, $type, $coercion;
  	}

  	$self->_clear_compiled_coercion;
  	return $self;
  }

  sub _build_compiled_coercion
  {
  	my $self = shift;

  	my @mishmash = @{$self->type_coercion_map};
  	return sub { $_[0] } unless @mishmash;

  	if ($self->can_be_inlined)
  	{
  		return Eval::TypeTiny::eval_closure(
  			source      => sprintf('sub ($) { %s }', $self->inline_coercion('$_[0]')),
  			description => sprintf("compiled coercion '%s'", $self),
  		);
  	}

  	# These arrays will be closed over.
  	my (@types, @codes);
  	while (@mishmash)
  	{
  		push @types, shift @mishmash;
  		push @codes, shift @mishmash;
  	}
  	if ($self->has_type_constraint)
  	{
  		unshift @types, $self->type_constraint;
  		unshift @codes, undef;
  	}

  	my @sub;

  	for my $i (0..$#types)
  	{
  		push @sub,
  			$types[$i]->can_be_inlined ? sprintf('if (%s)', $types[$i]->inline_check('$_[0]')) :
  			sprintf('if ($checks[%d]->(@_))', $i);
  		push @sub,
  			!defined($codes[$i])
  				? sprintf('  { return $_[0] }') :
  			Types::TypeTiny::StringLike->check($codes[$i])
  				? sprintf('  { local $_ = $_[0]; return scalar(%s); }', $codes[$i]) :
  			sprintf('  { local $_ = $_[0]; return scalar($codes[%d]->(@_)) }', $i);
  	}

  	push @sub, 'return $_[0];';

  	return Eval::TypeTiny::eval_closure(
  		source      => sprintf('sub ($) { %s }', join qq[\n], @sub),
  		description => sprintf("compiled coercion '%s'", $self),
  		environment => {
  			'@checks' => [ map $_->compiled_check, @types ],
  			'@codes'  => \@codes,
  		},
  	);
  }

  sub can_be_inlined
  {
  	my $self = shift;

  	return unless $self->frozen;

  	return
  		if $self->has_type_constraint
  		&& !$self->type_constraint->can_be_inlined;

  	my @mishmash = @{$self->type_coercion_map};
  	while (@mishmash)
  	{
  		my ($type, $converter) = splice(@mishmash, 0, 2);
  		return unless $type->can_be_inlined;
  		return unless Types::TypeTiny::StringLike->check($converter);
  	}
  	return !!1;
  }

  sub _source_type_union
  {
  	my $self = shift;

  	my @r;
  	push @r, $self->type_constraint if $self->has_type_constraint;

  	my @mishmash = @{$self->type_coercion_map};
  	while (@mishmash)
  	{
  		my ($type) = splice(@mishmash, 0, 2);
  		push @r, $type;
  	}

  	require Type::Tiny::Union;
  	return "Type::Tiny::Union"->new(type_constraints => \@r, tmp => 1);
  }

  sub inline_coercion
  {
  	my $self = shift;
  	my $varname = $_[0];

  	_croak "This coercion cannot be inlined" unless $self->can_be_inlined;

  	my @mishmash = @{$self->type_coercion_map};
  	return "($varname)" unless @mishmash;

  	my (@types, @codes);
  	while (@mishmash)
  	{
  		push @types, shift @mishmash;
  		push @codes, shift @mishmash;
  	}
  	if ($self->has_type_constraint)
  	{
  		unshift @types, $self->type_constraint;
  		unshift @codes, undef;
  	}

  	my @sub;

  	for my $i (0..$#types)
  	{
  		push @sub, sprintf('(%s) ?', $types[$i]->inline_check($varname));
  		push @sub,
  			(defined($codes[$i]) && ($varname eq '$_'))
  				? sprintf('scalar(do { %s }) :', $codes[$i]) :
  			defined($codes[$i])
  				? sprintf('scalar(do { local $_ = %s; %s }) :', $varname, $codes[$i]) :
  			sprintf('%s :', $varname);
  	}

  	push @sub, "$varname";

  	"@sub";
  }

  sub _build_moose_coercion
  {
  	my $self = shift;

  	my %options = ();
  	$options{type_coercion_map} = [ $self->freeze->_codelike_type_coercion_map('moose_type') ];
  	$options{type_constraint}   = $self->type_constraint if $self->has_type_constraint;

  	require Moose::Meta::TypeCoercion;
  	my $r = "Moose::Meta::TypeCoercion"->new(%options);

  	return $r;
  }

  sub _codelike_type_coercion_map
  {
  	my $self = shift;
  	my $modifier = $_[0];

  	my @orig = @{ $self->type_coercion_map };
  	my @new;

  	while (@orig)
  	{
  		my ($type, $converter) = splice(@orig, 0, 2);

  		push @new, $modifier ? $type->$modifier : $type;

  		if (Types::TypeTiny::CodeLike->check($converter))
  		{
  			push @new, $converter;
  		}
  		else
  		{
  			push @new, Eval::TypeTiny::eval_closure(
  				source      => sprintf('sub { local $_ = $_[0]; %s }', $converter),
  				description => sprintf("temporary compiled converter from '%s'", $type),
  			);
  		}
  	}

  	return @new;
  }

  sub is_parameterizable
  {
  	shift->has_coercion_generator;
  }

  sub is_parameterized
  {
  	shift->has_parameters;
  }

  sub parameterize
  {
  	my $self = shift;
  	return $self unless @_;
  	$self->is_parameterizable
  		or _croak "Constraint '%s' does not accept parameters", "$self";

  	@_ = map Types::TypeTiny::to_TypeTiny($_), @_;

  	return ref($self)->new(
  		type_constraint    => $self->type_constraint,
  		type_coercion_map  => [ $self->coercion_generator->($self, $self->type_constraint, @_) ],
  		parameters         => \@_,
  		frozen             => 1,
  		parameterized_from => $self,
  	);
  }

  sub _reparameterize
  {
  	my $self = shift;
  	my ($target_type) = @_;

  	$self->is_parameterized or return $self;
  	my $parent = $self->parameterized_from;

  	return ref($self)->new(
  		type_constraint    => $target_type,
  		type_coercion_map  => [ $parent->coercion_generator->($parent, $target_type, @{$self->parameters}) ],
  		parameters         => \@_,
  		frozen             => 1,
  		parameterized_from => $parent,
  	);
  }

  sub isa
  {
  	my $self = shift;

  	if ($INC{"Moose.pm"} and blessed($self) and $_[0] eq 'Moose::Meta::TypeCoercion')
  	{
  		return !!1;
  	}

  	if ($INC{"Moose.pm"}
  	and blessed($self)
  	and $_[0] =~ /^(Class::MOP|MooseX?)::/)
  	{
  		my $r = $self->moose_coercion->isa(@_);
  		return $r if $r;
  	}

  	$self->SUPER::isa(@_);
  }

  sub can
  {
  	my $self = shift;

  	my $can = $self->SUPER::can(@_);
  	return $can if $can;

  	if ($INC{"Moose.pm"}
  	and blessed($self)
  	and my $method = $self->moose_coercion->can(@_))
  	{
  		return sub { $method->(shift->moose_coercion, @_) };
  	}

  	return;
  }

  sub AUTOLOAD
  {
  	my $self = shift;
  	my ($m) = (our $AUTOLOAD =~ /::(\w+)$/);
  	return if $m eq 'DESTROY';

  	if ($INC{"Moose.pm"} and blessed($self) and my $method = $self->moose_coercion->can($m))
  	{
  		return $method->($self->moose_coercion, @_);
  	}

  	_croak q[Can't locate object method "%s" via package "%s"], $m, ref($self)||$self;
  }

  # Private Moose method, but Moo uses this...
  sub _compiled_type_coercion
  {
  	my $self = shift;
  	if (@_)
  	{
  		my $thing = $_[0];
  		if (blessed($thing) and $thing->isa("Type::Coercion"))
  		{
  			$self->add_type_coercions(@{$thing->type_coercion_map});
  		}
  		elsif (Types::TypeTiny::CodeLike->check($thing))
  		{
  			require Types::Standard;
  			$self->add_type_coercions(Types::Standard::Any(), $thing);
  		}
  	}
  	$self->compiled_coercion;
  }

  *compile_type_coercion = \&compiled_coercion;
  sub meta { _croak("Not really a Moose::Meta::TypeCoercion. Sorry!") }

  1;

  __END__

  =pod

  =encoding utf-8

  =head1 NAME

  Type::Coercion - a set of coercions to a particular target type constraint

  =head1 STATUS

  This module is covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  =head2 Constructors

  =over

  =item C<< new(%attributes) >>

  Moose-style constructor function.

  =item C<< add($c1, $c2) >>

  Create a Type::Coercion from two existing Type::Coercion objects.

  =back

  =head2 Attributes

  Attributes are named values that may be passed to the constructor. For
  each attribute, there is a corresponding reader method. For example:

     my $c = Type::Coercion->new( type_constraint => Int );
     my $t = $c->type_constraint;  # Int

  =head3 Important attributes

  These are the attributes you are likely to be most interested in
  providing when creating your own type coercions, and most interested
  in reading when dealing with coercion objects.

  =over

  =item C<type_constraint>

  Weak reference to the target type constraint (i.e. the type constraint which
  the output of coercion coderefs is expected to conform to).

  =item C<type_coercion_map>

  Arrayref of source-type/code pairs.

  =item C<frozen>

  Boolean; default false. A frozen coercion cannot have C<add_type_coercions>
  called upon it.

  =item C<name>

  A name for the coercion. These need to conform to certain naming
  rules (they must begin with an uppercase letter and continue using only
  letters, digits 0-9 and underscores).

  Optional; if not supplied will be an anonymous coercion.

  =item C<display_name>

  A name to display for the coercion when stringified. These don't have
  to conform to any naming rules. Optional; a default name will be
  calculated from the C<name>.

  =item C<library>

  The package name of the type library this coercion is associated with.
  Optional. Informational only: setting this attribute does not install
  the coercion into the package.

  =back

  =head3 Attributes related to parameterizable and parameterized coercions

  The following attributes are used for parameterized coercions, but are not
  fully documented because they may change in the near future:

  =over

  =item C<< coercion_generator >>

  =item C<< parameters >>

  =item C<< parameterized_from >>

  =back

  =head3 Lazy generated attributes

  The following attributes should not be usually passed to the constructor;
  unless you're doing something especially unusual, you should rely on the
  default lazily-built return values.

  =over

  =item C<< compiled_coercion >>

  Coderef to coerce a value (C<< $_[0] >>).

  The general point of this attribute is that you should not set it, but
  rely on the lazily-built default. Type::Coerce will usually generate a
  pretty fast coderef, inlining all type constraint checks, etc.

  =item C<moose_coercion>

  A L<Moose::Meta::TypeCoercion> object equivalent to this one. Don't set this
  manually; rely on the default built one.

  =back

  =head2 Methods

  =head3 Predicate methods

  These methods return booleans indicating information about the coercion.
  They are each tightly associated with a particular attribute.
  (See L</"Attributes">.)

  =over

  =item C<has_type_constraint>, C<has_library>

  Simple Moose-style predicate methods indicating the presence or
  absence of an attribute.

  =item C<is_anon>

  Returns true iff the coercion does not have a C<name>.

  =back

  The following predicates are used for parameterized coercions, but are not
  fully documented because they may change in the near future:

  =over

  =item C<< has_coercion_generator >>

  =item C<< has_parameters >>

  =item C<< is_parameterizable >>

  =item C<< is_parameterized >>

  =back

  =head3 Coercion

  The following methods are used for coercing values to a type constraint:

  =over

  =item C<< coerce($value) >>

  Coerce the value to the target type.

  Returns the coerced value, or the original value if no coercion was
  possible.

  =item C<< assert_coerce($value) >>

  Coerce the value to the target type, and throw an exception if the result
  does not validate against the target type constraint.

  Returns the coerced value.

  =back

  =head3 Coercion code definition methods

  These methods all return C<< $self >> so are suitable for chaining.

  =over

  =item C<< add_type_coercions($type1, $code1, ...) >>

  Takes one or more pairs of L<Type::Tiny> constraints and coercion code,
  creating an ordered list of source types and coercion codes.

  Coercion codes can be expressed as either a string of Perl code (this
  includes objects which overload stringification), or a coderef (or object
  that overloads coderefification). In either case, the value to be coerced
  is C<< $_ >>.

  C<< add_type_coercions($coercion_object) >> also works, and can be used
  to copy coercions from another type constraint:

     $type->coercion->add_type_coercions($othertype->coercion)->freeze;

  =item C<< freeze >>

  Sets the C<frozen> attribute to true. Called automatically by L<Type::Tiny>
  sometimes.

  =item C<< i_really_want_to_unfreeze >>

  If you really want to unfreeze a coercion, call this method.

  Don't call this method. It will potentially lead to subtle bugs.

  This method is considered unstable; future versions of Type::Tiny may
  alter its behaviour (e.g. to throw an exception if it has been detected
  that unfreezing this particular coercion will cause bugs).

  =back

  =head3 Parameterization

  The following method is used for parameterized coercions, but is not
  fully documented because it may change in the near future:

  =over

  =item C<< parameterize(@params) >>

  =back

  =head3 Type coercion introspection methods

  These methods allow you to determine a coercion's relationship to type
  constraints:

  =over

  =item C<< has_coercion_for_type($source_type) >>

  Returns true iff this coercion has a coercion from the source type.

  Returns the special string C<< "0 but true" >> if no coercion should
  actually be necessary for this type. (For example, if a coercion coerces
  to a theoretical "Number" type, there is probably no coercion necessary
  for values that already conform to the "Integer" type.)

  =item C<< has_coercion_for_value($value) >>

  Returns true iff the value could be coerced by this coercion.

  Returns the special string C<< "0 but true" >> if no coercion would be
  actually be necessary for this value (due to it already meeting the target
  type constraint).

  =back

  The C<type_constraint> attribute provides a type constraint object for the
  target type constraint of the coercion. See L</"Attributes">.

  =head3 Inlining methods

  =for stopwords uated

  The following methods are used to generate strings of Perl code which
  may be pasted into stringy C<eval>uated subs to perform type coercions:

  =over

  =item C<< can_be_inlined >>

  Returns true iff the coercion can be inlined.

  =item C<< inline_coercion($varname) >>

  Much like C<inline_coerce> from L<Type::Tiny>.

  =back

  =head3 Other methods

  =over

  =item C<< qualified_name >>

  For non-anonymous coercions that have a library, returns a qualified
  C<< "MyLib::MyCoercion" >> sort of name. Otherwise, returns the same
  as C<name>.

  =item C<< isa($class) >>, C<< can($method) >>, C<< AUTOLOAD(@args) >>

  If Moose is loaded, then the combination of these methods is used to mock
  a Moose::Meta::TypeCoercion.

  =back

  The following methods exist for Moose/Mouse compatibility, but do not do
  anything useful.

  =over

  =item C<< compile_type_coercion >>

  =item C<< meta >>

  =back

  =head2 Overloading

  =over

  =item *

  Boolification is overloaded to always return true.

  =item *

  Coderefification is overloaded to call C<coerce>.

  =item *

  On Perl 5.10.1 and above, smart match is overloaded to call C<has_coercion_for_value>.

  =back

  Previous versions of Type::Coercion would overload the C<< + >> operator
  to call C<add>. Support for this was dropped after 0.040.

  =head1 DIAGNOSTICS

  =over

  =item B<< Attempt to add coercion code to a Type::Coercion which has been frozen >>

  Type::Tiny type constraints are designed as immutable objects. Once you've
  created a constraint, rather than modifying it you generally create child
  constraints to do what you need.

  Type::Coercion objects, on the other hand, are mutable. Coercion routines
  can be added at any time during the object's lifetime.

  Sometimes Type::Tiny needs to freeze a Type::Coercion object to prevent this.
  In L<Moose> and L<Mouse> code this is likely to happen as soon as you use a
  type constraint in an attribute.

  Workarounds:

  =over

  =item *

  Define as many of your coercions as possible within type libraries, not
  within the code that uses the type libraries. The type library will be
  evaluated relatively early, likely before there is any reason to freeze
  a coercion.

  =item *

  If you do need to add coercions to a type within application code outside
  the type library, instead create a subtype and add coercions to that. The
  C<plus_coercions> method provided by L<Type::Tiny> should make this simple.

  =back

  =back

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Type::Tiny::Manual>.

  L<Type::Tiny>, L<Type::Library>, L<Type::Utils>, L<Types::Standard>.

  L<Type::Coercion::Union>.

  L<Moose::Meta::TypeCoercion>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.


TYPE_COERCION

$fatpacked{"Type/Coercion/FromMoose.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TYPE_COERCION_FROMMOOSE';
  package Type::Coercion::FromMoose;

  use 5.006001;
  use strict;
  use warnings;

  BEGIN {
  	$Type::Coercion::FromMoose::AUTHORITY = 'cpan:TOBYINK';
  	$Type::Coercion::FromMoose::VERSION   = '1.000005';
  }

  use Scalar::Util qw< blessed >;
  use Types::TypeTiny ();

  sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }

  require Type::Coercion;
  our @ISA = 'Type::Coercion';

  sub type_coercion_map
  {
  	my $self = shift;

  	my @from;
  	if ($self->type_constraint)
  	{
  		my $moose = $self->type_constraint->{moose_type};
  		@from = @{ $moose->coercion->type_coercion_map } if $moose && $moose->has_coercion;
  	}
  	else
  	{
  		_croak "The type constraint attached to this coercion has been garbage collected... PANIC";
  	}

  	my @return;
  	while (@from)
  	{
  		my ($type, $code) = splice(@from, 0, 2);
  		$type = Moose::Util::TypeConstraints::find_type_constraint($type)
  			unless ref $type;
  		push @return, Types::TypeTiny::to_TypeTiny($type), $code;
  	}

  	return \@return;
  }

  sub add_type_coercions
  {
  	my $self = shift;
  	_croak "Adding coercions to Type::Coercion::FromMoose not currently supported" if @_;
  }

  sub _build_moose_coercion
  {
  	my $self = shift;

  	if ($self->type_constraint)
  	{
  		my $moose = $self->type_constraint->{moose_type};
  		return $moose->coercion if $moose && $moose->has_coercion;
  	}

  	$self->SUPER::_build_moose_coercion(@_);
  }

  sub can_be_inlined
  {
  	0;
  }

  1;

  __END__

  =pod

  =encoding utf-8

  =head1 NAME

  Type::Coercion::FromMoose - a set of coercions borrowed from Moose

  =head1 STATUS

  This module is considered part of Type-Tiny's internals. It is not
  covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  This package inherits from L<Type::Coercion>; see that for most documentation.
  The major differences are that C<add_type_coercions> always throws an
  exception, and the C<type_coercion_map> is automatically populated from
  Moose.

  This is mostly for internal purposes.

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Type::Coercion>.

  L<Moose::Meta::TypeCoercion>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

TYPE_COERCION_FROMMOOSE

$fatpacked{"Type/Coercion/Union.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TYPE_COERCION_UNION';
  package Type::Coercion::Union;

  use 5.006001;
  use strict;
  use warnings;

  BEGIN {
  	$Type::Coercion::Union::AUTHORITY = 'cpan:TOBYINK';
  	$Type::Coercion::Union::VERSION   = '1.000005';
  }

  use Scalar::Util qw< blessed >;
  use Types::TypeTiny ();

  sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }

  require Type::Coercion;
  our @ISA = 'Type::Coercion';

  sub _preserve_type_constraint
  {
  	my $self = shift;
  	$self->{_union_of} = $self->{type_constraint}->type_constraints
  		if $self->{type_constraint};
  }

  sub _maybe_restore_type_constraint
  {
  	my $self = shift;
  	if ( my $union = $self->{_union_of} )
  	{
  		return Type::Tiny::Union->new(type_constraints => $union);
  	}
  	return;
  }

  sub type_coercion_map
  {
  	my $self = shift;

  	Types::TypeTiny::TypeTiny->assert_valid(my $type = $self->type_constraint);
  	$type->isa('Type::Tiny::Union')
  		or _croak "Type::Coercion::Union must be used in conjunction with Type::Tiny::Union";

  	my @c;
  	for my $tc (@$type)
  	{
  		next unless $tc->has_coercion;
  		push @c, @{$tc->coercion->type_coercion_map};
  	}
  	return \@c;
  }

  sub add_type_coercions
  {
  	my $self = shift;
  	_croak "Adding coercions to Type::Coercion::Union not currently supported" if @_;
  }

  sub _build_moose_coercion
  {
  	my $self = shift;

  	my %options = ();
  	$options{type_constraint} = $self->type_constraint if $self->has_type_constraint;

  	require Moose::Meta::TypeCoercion::Union;
  	my $r = "Moose::Meta::TypeCoercion::Union"->new(%options);

  	return $r;
  }

  sub can_be_inlined
  {
  	my $self = shift;

  	Types::TypeTiny::TypeTiny->assert_valid(my $type = $self->type_constraint);

  	for my $tc (@$type)
  	{
  		next unless $tc->has_coercion;
  		return !!0 unless $tc->coercion->can_be_inlined;
  	}

  	!!1;
  }

  1;

  __END__

  =pod

  =encoding utf-8

  =head1 NAME

  Type::Coercion::Union - a set of coercions to a union type constraint

  =head1 STATUS

  This module is covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  This package inherits from L<Type::Coercion>; see that for most documentation.
  The major differences are that C<add_type_coercions> always throws an
  exception, and the C<type_coercion_map> is automatically populated from
  the child constraints of the union type constraint.

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Type::Coercion>.

  L<Moose::Meta::TypeCoercion::Union>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

TYPE_COERCION_UNION

$fatpacked{"Type/Library.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TYPE_LIBRARY';
  package Type::Library;

  use 5.006001;
  use strict;
  use warnings;

  BEGIN {
  	$Type::Library::AUTHORITY = 'cpan:TOBYINK';
  	$Type::Library::VERSION   = '1.000005';
  }

  use Eval::TypeTiny qw< eval_closure >;
  use Scalar::Util qw< blessed refaddr >;
  use Type::Tiny;
  use Types::TypeTiny qw< TypeTiny to_TypeTiny >;

  require Exporter::Tiny;
  our @ISA = 'Exporter::Tiny';

  BEGIN { *NICE_PROTOTYPES = ($] >= 5.014) ? sub () { !!1 } : sub () { !!0 } };

  sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }

  {
  	my $got_subname;
  	my %already; # prevent renaming established functions
  	sub _subname ($$)
  	{
  		($got_subname or eval "require Sub::Name")
  			and ($got_subname = 1)
  			and !$already{refaddr($_[1])}++
  			and return(Sub::Name::subname(@_));
  		return $_[1];
  	}
  }

  sub _exporter_validate_opts
  {
  	my $class = shift;

  	no strict "refs";
  	my $into  = $_[0]{into};
  	push @{"$into\::ISA"}, $class if $_[0]{base};

  	return $class->SUPER::_exporter_validate_opts(@_);
  }

  sub _exporter_expand_tag
  {
  	my $class = shift;
  	my ($name, $value, $globals) = @_;

  	$name eq 'types'     and return map [ "$_"        => $value ], $class->type_names;
  	$name eq 'is'        and return map [ "is_$_"     => $value ], $class->type_names;
  	$name eq 'assert'    and return map [ "assert_$_" => $value ], $class->type_names;
  	$name eq 'to'        and return map [ "to_$_"     => $value ], $class->type_names;
  	$name eq 'coercions' and return map [ "$_"        => $value ], $class->coercion_names;

  	if ($name eq 'all')
  	{
  		no strict "refs";
  		return (
  			map(
  				[ "+$_" => $value ],
  				$class->type_names,
  			),
  			map(
  				[ $_ => $value ],
  				$class->coercion_names,
  				@{"$class\::EXPORT"},
  				@{"$class\::EXPORT_OK"},
  			),
  		);
  	}

  	return $class->SUPER::_exporter_expand_tag(@_);
  }

  sub _mksub
  {
  	my $class = shift;
  	my ($type, $post_method) = @_;
  	$post_method ||= q();

  	my $source = $type->is_parameterizable
  		? sprintf(
  			q{
  				sub (%s) {
  					return $_[0]->complete($type) if ref($_[0]) eq 'Type::Tiny::_HalfOp';
  					my $params; $params = shift if ref($_[0]) eq q(ARRAY);
  					my $t = $params ? $type->parameterize(@$params) : $type;
  					@_ && wantarray ? return($t%s, @_) : return $t%s;
  				}
  			},
  			NICE_PROTOTYPES ? q(;$) : q(;@),
  			$post_method,
  			$post_method,
  		)
  		: sprintf(
  			q{ sub () { $type%s if $] } },
  			$post_method,
  		);

  	return _subname(
  		$type->qualified_name,
  		eval_closure(
  			source      => $source,
  			description => sprintf("exportable function '%s'", $type),
  			environment => {'$type' => \$type},
  		),
  	);
  }

  sub _exporter_permitted_regexp
  {
  	my $class = shift;

  	my $inherited = $class->SUPER::_exporter_permitted_regexp(@_);
  	my $types = join "|", map quotemeta, sort {
  		length($b) <=> length($a) or $a cmp $b
  	} $class->type_names;
  	my $coercions = join "|", map quotemeta, sort {
  		length($b) <=> length($a) or $a cmp $b
  	} $class->coercion_names;

  	qr{^(?:
  		$inherited
  		| (?: (?:is_|to_|assert_)? (?:$types) )
  		| (?:$coercions)
  	)$}xms;
  }

  sub _exporter_expand_sub
  {
  	my $class = shift;
  	my ($name, $value, $globals) = @_;

  	if ($name =~ /^\+(.+)/ and $class->has_type($1))
  	{
  		my $type   = $1;
  		my $value2 = +{%{$value||{}}};

  		return map $class->_exporter_expand_sub($_, $value2, $globals),
  			$type, "is_$type", "assert_$type", "to_$type";
  	}

  	if (my $type = $class->get_type($name))
  	{
  		my $post_method = q();
  		$post_method = '->mouse_type' if $globals->{mouse};
  		$post_method = '->moose_type' if $globals->{moose};
  		return ($name => $class->_mksub($type, $post_method)) if $post_method;
  	}

  	return $class->SUPER::_exporter_expand_sub(@_);
  }

  sub _exporter_install_sub
  {
  	my $class = shift;
  	my ($name, $value, $globals, $sym) = @_;

  	my $package = $globals->{into};

  	if (!ref $package and my $type = $class->get_type($name))
  	{
  		my ($prefix) = grep defined, $value->{-prefix}, $globals->{prefix}, q();
  		my ($suffix) = grep defined, $value->{-suffix}, $globals->{suffix}, q();
  		my $as = $prefix . ($value->{-as} || $name) . $suffix;

  		$INC{'Type/Registry.pm'}
  			? 'Type::Registry'->for_class($package)->add_type($type, $as)
  			: ($Type::Registry::DELAYED{$package}{$as} = $type);
  	}

  	$class->SUPER::_exporter_install_sub(@_);
  }

  sub _exporter_fail
  {
  	my $class = shift;
  	my ($name, $value, $globals) = @_;

  	my $into = $globals->{into}
  		or _croak("Parameter 'into' not supplied");

  	if ($globals->{declare})
  	{
  		my $declared = sub (;$)
  		{
  			my $params; $params = shift if ref($_[0]) eq "ARRAY";
  			my $type = $into->get_type($name);
  			unless ($type)
  			{
  				_croak "Cannot parameterize a non-existant type" if $params;
  				$type = $name;
  			}

  			my $t = $params ? $type->parameterize(@$params) : $type;
  			@_ && wantarray ? return($t, @_) : return $t;
  		};

  		return(
  			$name,
  			_subname(
  				"$class\::$name",
  				NICE_PROTOTYPES ? sub (;$) { goto $declared } : sub (;@) { goto $declared },
  			),
  		);
  	}

  	return $class->SUPER::_exporter_fail(@_);
  }

  sub meta
  {
  	no strict "refs";
  	no warnings "once";
  	return $_[0] if blessed $_[0];
  	${"$_[0]\::META"} ||= bless {}, $_[0];
  }

  sub add_type
  {
  	my $meta  = shift->meta;
  	my $class = blessed($meta);

  	my $type =
  		ref($_[0]) =~ /^Type::Tiny\b/  ? $_[0] :
  		blessed($_[0])                 ? to_TypeTiny($_[0]) :
  		ref($_[0]) eq q(HASH)          ? "Type::Tiny"->new(library => $class, %{$_[0]}) :
  		"Type::Tiny"->new(library => $class, @_);
  	my $name = $type->{name};

  	$meta->{types} ||= {};
  	_croak 'Type %s already exists in this library', $name if $meta->has_type($name);
  	_croak 'Type %s conflicts with coercion of same name', $name if $meta->has_coercion($name);
  	_croak 'Cannot add anonymous type to a library' if $type->is_anon;
  	$meta->{types}{$name} = $type;

  	no strict "refs";
  	no warnings "redefine", "prototype";

  	my $to_type = $type->has_coercion && $type->coercion->frozen
  		? $type->coercion->compiled_coercion
  		: sub ($) { $type->coerce($_[0]) };

  	*{"$class\::$name"}        = $class->_mksub($type);
  	*{"$class\::is_$name"}     = _subname "$class\::is_$name", $type->compiled_check;
  	*{"$class\::to_$name"}     = _subname "$class\::to_$name", $to_type;
  	*{"$class\::assert_$name"} = _subname "$class\::assert_$name", $type->_overload_coderef;

  	return $type;
  }

  sub get_type
  {
  	my $meta = shift->meta;
  	$meta->{types}{$_[0]};
  }

  sub has_type
  {
  	my $meta = shift->meta;
  	exists $meta->{types}{$_[0]};
  }

  sub type_names
  {
  	my $meta = shift->meta;
  	keys %{ $meta->{types} };
  }

  sub add_coercion
  {
  	require Type::Coercion;
  	my $meta = shift->meta;
  	my $c    = blessed($_[0]) ? $_[0] : "Type::Coercion"->new(@_);
  	my $name = $c->name;

  	$meta->{coercions} ||= {};
  	_croak 'Coercion %s already exists in this library', $name if $meta->has_coercion($name);
  	_croak 'Coercion %s conflicts with type of same name', $name if $meta->has_type($name);
  	_croak 'Cannot add anonymous type to a library' if $c->is_anon;
  	$meta->{coercions}{$name} = $c;

  	no strict "refs";
  	no warnings "redefine", "prototype";

  	my $class = blessed($meta);
  	*{"$class\::$name"} = $class->_mksub($c);

  	return $c;
  }

  sub get_coercion
  {
  	my $meta = shift->meta;
  	$meta->{coercions}{$_[0]};
  }

  sub has_coercion
  {
  	my $meta = shift->meta;
  	exists $meta->{coercions}{$_[0]};
  }

  sub coercion_names
  {
  	my $meta = shift->meta;
  	keys %{ $meta->{coercions} };
  }

  sub make_immutable
  {
  	my $meta  = shift->meta;
  	my $class = ref($meta);

  	for my $type (values %{$meta->{types}})
  	{
  		$type->coercion->freeze;

  		no strict "refs";
  		no warnings "redefine", "prototype";

  		my $to_type = $type->has_coercion && $type->coercion->frozen
  			? $type->coercion->compiled_coercion
  			: sub ($) { $type->coerce($_[0]) };
  		my $name = $type->name;

  		*{"$class\::to_$name"} = _subname "$class\::to_$name", $to_type;
  	}

  	1;
  }

  1;

  __END__

  =pod

  =encoding utf-8

  =for stopwords Moo(se)-compatible MooseX::Types-like

  =head1 NAME

  Type::Library - tiny, yet Moo(se)-compatible type libraries

  =head1 SYNOPSIS

  =for test_synopsis
  BEGIN { die "SKIP: crams multiple modules into single example" };

     package Types::Mine {
        use Scalar::Util qw(looks_like_number);
        use Type::Library -base;
        use Type::Tiny;

        my $NUM = "Type::Tiny"->new(
           name       => "Number",
           constraint => sub { looks_like_number($_) },
           message    => sub { "$_ ain't a number" },
        );

        __PACKAGE__->meta->add_type($NUM);

        __PACKAGE__->meta->make_immutable;
     }

     package Ermintrude {
        use Moo;
        use Types::Mine qw(Number);
        has favourite_number => (is => "ro", isa => Number);
     }

     package Bullwinkle {
        use Moose;
        use Types::Mine qw(Number);
        has favourite_number => (is => "ro", isa => Number);
     }

     package Maisy {
        use Mouse;
        use Types::Mine qw(Number);
        has favourite_number => (is => "ro", isa => Number);
     }

  =head1 STATUS

  This module is covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  L<Type::Library> is a tiny class for creating MooseX::Types-like type
  libraries which are compatible with Moo, Moose and Mouse.

  If you're reading this because you want to create a type library, then
  you're probably better off reading L<Type::Tiny::Manual::Libraries>.

  =head2 Methods

  A type library is a singleton class. Use the C<meta> method to get a blessed
  object which other methods can get called on. For example:

     Types::Mine->meta->add_type($foo);

  =begin trustme

  =item meta

  =end trustme

  =over

  =item C<< add_type($type) >> or C<< add_type(%opts) >>

  Add a type to the library. If C<< %opts >> is given, then this method calls
  C<< Type::Tiny->new(%opts) >> first, and adds the resultant type.

  Adding a type named "Foo" to the library will automatically define four
  functions in the library's namespace:

  =over

  =item C<< Foo >>

  Returns the Type::Tiny object.

  =item C<< is_Foo($value) >>

  Returns true iff $value passes the type constraint.

  =item C<< assert_Foo($value) >>

  Returns $value iff $value passes the type constraint. Dies otherwise.

  =item C<< to_Foo($value) >>

  Coerces the value to the type.

  =back

  =item C<< get_type($name) >>

  Gets the C<Type::Tiny> object corresponding to the name.

  =item C<< has_type($name) >>

  Boolean; returns true if the type exists in the library.

  =item C<< type_names >>

  List all types defined by the library.

  =item C<< add_coercion($c) >> or C<< add_coercion(%opts) >>

  Add a standalone coercion to the library. If C<< %opts >> is given, then
  this method calls C<< Type::Coercion->new(%opts) >> first, and adds the
  resultant coercion.

  Adding a coercion named "FooFromBar" to the library will automatically
  define a function in the library's namespace:

  =over

  =item C<< FooFromBar >>

  Returns the Type::Coercion object.

  =back

  =item C<< get_coercion($name) >>

  Gets the C<Type::Coercion> object corresponding to the name.

  =item C<< has_coercion($name) >>

  Boolean; returns true if the coercion exists in the library.

  =item C<< coercion_names >>

  List all standalone coercions defined by the library.

  =item C<< import(@args) >>

  Type::Library-based libraries are exporters.

  =item C<< make_immutable >>

  A shortcut for calling C<< $type->coercion->freeze >> on every
  type constraint in the library.

  =back

  =head2 Constants

  =over

  =item C<< NICE_PROTOTYPES >>

  If this is true, then Type::Library will give parameterizable type constraints
  slightly the nicer prototype of C<< (;$) >> instead of the default C<< (;@) >>.
  This allows constructs like:

     ArrayRef[Int] | HashRef[Int]

  ... to "just work".

  =back

  =head2 Export

  Type libraries are exporters. For the purposes of the following examples,
  assume that the C<Types::Mine> library defines types C<Number> and C<String>.

     # Exports nothing.
     #
     use Types::Mine;

     # Exports a function "String" which is a constant returning
     # the String type constraint.
     #
     use Types::Mine qw( String );

     # Exports both String and Number as above.
     #
     use Types::Mine qw( String Number );

     # Same.
     #
     use Types::Mine qw( :types );

     # Exports a sub "is_String" so that "is_String($foo)" is equivalent
     # to "String->check($foo)".
     #
     use Types::Mine qw( is_String );

     # Exports "is_String" and "is_Number".
     #
     use Types::Mine qw( :is );

     # Exports a sub "assert_String" so that "assert_String($foo)" is
     # equivalent to "String->assert_return($foo)".
     #
     use Types::Mine qw( assert_String );

     # Exports "assert_String" and "assert_Number".
     #
     use Types::Mine qw( :assert );

     # Exports a sub "to_String" so that "to_String($foo)" is equivalent
     # to "String->coerce($foo)".
     #
     use Types::Mine qw( to_String );

     # Exports "to_String" and "to_Number".
     #
     use Types::Mine qw( :to );

     # Exports "String", "is_String", "assert_String" and "coerce_String".
     #
     use Types::Mine qw( +String );

     # Exports everything.
     #
     use Types::Mine qw( :all );

  Type libraries automatically inherit from L<Exporter::Tiny>; see the
  documentation of that module for tips and tricks importing from libraries.

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Type::Tiny::Manual>.

  L<Type::Tiny>, L<Type::Utils>, L<Types::Standard>, L<Type::Coercion>.

  L<Moose::Util::TypeConstraints>,
  L<Mouse::Util::TypeConstraints>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.


TYPE_LIBRARY

$fatpacked{"Type/Params.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TYPE_PARAMS';
  package Type::Params;

  use 5.006001;
  use strict;
  use warnings;

  BEGIN {
  	if ($] < 5.008) { require Devel::TypeTiny::Perl56Compat };
  }

  BEGIN {
  	$Type::Params::AUTHORITY = 'cpan:TOBYINK';
  	$Type::Params::VERSION   = '1.000005';
  }

  use B qw();
  use Eval::TypeTiny;
  use Scalar::Util qw(refaddr);
  use Error::TypeTiny;
  use Error::TypeTiny::Assertion;
  use Error::TypeTiny::WrongNumberOfParameters;
  use Type::Tiny::Union;
  use Types::Standard -types;
  use Types::TypeTiny qw(CodeLike ArrayLike to_TypeTiny);

  require Exporter::Tiny;
  our @ISA = 'Exporter::Tiny';

  our @EXPORT = qw( compile );
  our @EXPORT_OK = qw( multisig validate Invocant );

  BEGIN {
  	my $Invocant = 'Type::Tiny::Union'->new(
  		name             => 'Invocant',
  		type_constraints => [Object, ClassName],
  	);
  	sub Invocant () { $Invocant };
  };

  sub _mkslurpy
  {
  	my ($name, $type, $tc, $i) = @_;
  	$name = 'local $_' if $name eq '$_';

  	$type eq '@'
  		? sprintf(
  			'%s = [ @_[%d..$#_] ];',
  			$name,
  			$i,
  		)
  		: sprintf(
  			'%s = (($#_-%d)%%2)==0 ? "Error::TypeTiny::WrongNumberOfParameters"->throw(message => sprintf("Odd number of elements in %%s", %s)) : +{ @_[%d..$#_] };',
  			$name,
  			$i,
  			B::perlstring("$tc"),
  			$i,
  		);
  }

  sub compile
  {
  	my (@code, %env);
  	@code = 'my (@R, %tmp, $tmp);';
  	push @code, '#placeholder';   # $code[1]

  	my %options    = (ref($_[0]) eq "HASH" && !$_[0]{slurpy}) ? %{+shift} : ();
  	my $arg        = -1;
  	my $saw_slurpy = 0;
  	my $min_args   = 0;
  	my $max_args   = 0;
  	my $saw_opt    = 0;

  	while (@_)
  	{
  		++$arg;
  		my $constraint = shift;
  		my $is_optional;
  		my $really_optional;
  		my $is_slurpy;
  		my $varname;

  		if (Bool->check($constraint))
  		{
  			$constraint = $constraint ? Any : Optional[Any];
  		}

  		if (HashRef->check($constraint))
  		{
  			$constraint = to_TypeTiny($constraint->{slurpy});
  			push @code,
  				$constraint->is_a_type_of(Dict)     ? _mkslurpy('$_', '%', $constraint => $arg) :
  				$constraint->is_a_type_of(Map)      ? _mkslurpy('$_', '%', $constraint => $arg) :
  				$constraint->is_a_type_of(Tuple)    ? _mkslurpy('$_', '@', $constraint => $arg) :
  				$constraint->is_a_type_of(HashRef)  ? _mkslurpy('$_', '%', $constraint => $arg) :
  				$constraint->is_a_type_of(ArrayRef) ? _mkslurpy('$_', '@', $constraint => $arg) :
  				Error::TypeTiny::croak("Slurpy parameter not of type HashRef or ArrayRef");
  			$varname = '$_';
  			$is_slurpy++;
  			$saw_slurpy++;
  		}
  		else
  		{
  			Error::TypeTiny::croak("Parameter following slurpy parameter") if $saw_slurpy;

  			$is_optional     = grep $_->{uniq} == Optional->{uniq}, $constraint->parents;
  			$really_optional = $is_optional && $constraint->parent->{uniq} eq Optional->{uniq} && $constraint->type_parameter;

  			if ($is_optional)
  			{
  				push @code, sprintf 'return @R if $#_ < %d;', $arg;
  				$saw_opt++;
  				$max_args++;
  			}
  			else
  			{
  				Error::TypeTiny::croak("Non-Optional parameter following Optional parameter") if $saw_opt;
  				$min_args++;
  				$max_args++;
  			}

  			$varname = sprintf '$_[%d]', $arg;
  		}

  		if ($constraint->has_coercion and $constraint->coercion->can_be_inlined)
  		{
  			push @code, sprintf(
  				'$tmp%s = %s;',
  				($is_optional ? '{x}' : ''),
  				$constraint->coercion->inline_coercion($varname)
  			);
  			$varname = '$tmp'.($is_optional ? '{x}' : '');
  		}
  		elsif ($constraint->has_coercion)
  		{
  			$env{'@coerce'}[$arg] = $constraint->coercion->compiled_coercion;
  			push @code, sprintf(
  				'$tmp%s = $coerce[%d]->(%s);',
  				($is_optional ? '{x}' : ''),
  				$arg,
  				$varname,
  			);
  			$varname = '$tmp'.($is_optional ? '{x}' : '');
  		}

  		if ($constraint->can_be_inlined)
  		{
  			push @code, sprintf(
  				'(%s) or Type::Tiny::_failed_check(%d, %s, %s, varname => %s);',
  				$really_optional
  					? $constraint->type_parameter->inline_check($varname)
  					: $constraint->inline_check($varname),
  				$constraint->{uniq},
  				B::perlstring($constraint),
  				$varname,
  				$is_slurpy ? 'q{$SLURPY}' : sprintf('q{$_[%d]}', $arg),
  			);
  		}
  		else
  		{
  			$env{'@check'}[$arg] = $really_optional
  				? $constraint->type_parameter->compiled_check
  				: $constraint->compiled_check;
  			push @code, sprintf(
  				'%s or Type::Tiny::_failed_check(%d, %s, %s, varname => %s);',
  				sprintf(sprintf '$check[%d]->(%s)', $arg, $varname),
  				$constraint->{uniq},
  				B::perlstring($constraint),
  				$varname,
  				$is_slurpy ? 'q{$SLURPY}' : sprintf('q{$_[%d]}', $arg),
  			);
  		}

  		push @code, sprintf 'push @R, %s;', $varname;
  	}

  	if ($min_args == $max_args and not $saw_slurpy)
  	{
  		$code[1] = sprintf(
  			'"Error::TypeTiny::WrongNumberOfParameters"->throw(got => scalar(@_), minimum => %d, maximum => %d) if @_ != %d;',
  			$min_args,
  			$max_args,
  			$min_args,
  		);
  	}
  	elsif ($min_args < $max_args and not $saw_slurpy)
  	{
  		$code[1] = sprintf(
  			'"Error::TypeTiny::WrongNumberOfParameters"->throw(got => scalar(@_), minimum => %d, maximum => %d) if @_ < %d || @_ > %d;',
  			$min_args,
  			$max_args,
  			$min_args,
  			$max_args,
  		);
  	}
  	elsif ($min_args and $saw_slurpy)
  	{
  		$code[1] = sprintf(
  			'"Error::TypeTiny::WrongNumberOfParameters"->throw(got => scalar(@_), minimum => %d) if @_ < %d;',
  			$min_args,
  			$min_args,
  		);
  	}

  	push @code, '@R;';

  	my $source  = "sub { no warnings; ".join("\n", @code)." };";

  	return $source if $options{want_source};

  	my $closure = eval_closure(
  		source      => $source,
  		description => sprintf("parameter validation for '%s'", [caller(1+($options{caller_level}||0))]->[3] || '__ANON__'),
  		environment => \%env,
  	);

  	return {
  		min_args   => $min_args,
  		max_args   => $saw_slurpy ? undef : $max_args,
  		closure    => $closure,
  	} if $options{want_details};

  	return $closure;
  }

  my %compiled;
  sub validate
  {
  	my $arr = shift;
  	my $sub = $compiled{ join ":", map($_->{uniq}||"\@$_->{slurpy}", @_) } ||= compile({ caller_level => 1 }, @_);
  	@_ = @$arr;
  	goto $sub;
  }

  sub multisig
  {
  	my %options = (ref($_[0]) eq "HASH" && !$_[0]{slurpy}) ? %{+shift} : ();
  	my @multi = map {
  		CodeLike->check($_)  ? { closure => $_ } :
  		ArrayLike->check($_) ? compile({ want_details => 1 }, @$_) :
  		$_;
  	} @_;

  	my @code = 'sub { my $r; ';

  	for my $i (0 .. $#multi)
  	{
  		my $sig = $multi[$i];
  		my @cond;
  		push @cond, sprintf('@_ >= %s', $sig->{min_args}) if defined $sig->{min_args};
  		push @cond, sprintf('@_ <= %s', $sig->{max_args}) if defined $sig->{max_args};
  		push @code, sprintf('if (%s){', join(' and ', @cond)) if @cond;
  		push @code, sprintf('eval { $r = [ $multi[%d]{closure}->(@_) ] };', $i);
  		push @code, 'return(@$r) if $r;';
  		push @code, '}' if @cond;
  	}

  	push @code, '"Error::TypeTiny"->throw(message => "Parameter validation failed");';
  	push @code, '}';

  	eval_closure(
  		source      => \@code,
  		description => sprintf("parameter validation for '%s'", [caller(1+($options{caller_level}||0))]->[3] || '__ANON__'),
  		environment => { '@multi' => \@multi },
  	);
  }

  1;

  __END__

  =pod

  =encoding utf-8

  =for stopwords evals

  =head1 NAME

  Type::Params - Params::Validate-like parameter validation using Type::Tiny type constraints and coercions

  =head1 SYNOPSIS

   use v5.10;
   use strict;
   use warnings;

   use Type::Params qw( compile );
   use Types::Standard qw( slurpy Str ArrayRef Num );

   sub deposit_monies
   {
      state $check = compile( Str, Str, slurpy ArrayRef[Num] );
      my ($sort_code, $account_number, $monies) = $check->(@_);

      my $account = Local::BankAccount->new($sort_code, $account_number);
      $account->deposit($_) for @$monies;
   }

   deposit_monies("12-34-56", "11223344", 1.2, 3, 99.99);

  =head1 STATUS

  This module is covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  Type::Params uses L<Type::Tiny> constraints to validate the parameters to a
  sub. It takes the slightly unorthodox approach of separating validation
  into two stages:

  =over

  =item 1.

  Compiling the parameter specification into a coderef; then

  =item 2.

  Using the coderef to validate parameters.

  =back

  The first stage is slow (it might take a couple of milliseconds), but you
  only need to do it the first time the sub is called. The second stage is
  fast; according to my benchmarks faster even than the XS version of
  L<Params::Validate>.

  If you're using a modern version of Perl, you can use the C<state> keyword
  which was a feature added to Perl in 5.10. If you're stuck on Perl 5.8, the
  example from the SYNOPSIS could be rewritten as:

   my $deposit_monies_check;
   sub deposit_monies
   {
      $deposit_monies_check ||= compile( Str, Str, slurpy ArrayRef[Num] );
      my ($sort_code, $account_number, $monies) = $check->(@_);

      ...;
   }

  Not quite as neat, but not awful either.

  There's a shortcut reducing it to one step:

   use Type::Params qw( validate );

   sub deposit_monies
   {
      my ($sort_code, $account_number, $monies) =
         validate( \@_, Str, Str, slurpy ArrayRef[Num] );

      ...;
   }

  Type::Params has a few tricks up its sleeve to make sure performance doesn't
  suffer too much with the shortcut, but it's never going to be as fast as the
  two stage compile/execute.

  =begin trustme

  Dude, these functions are documented!

  =item compile

  =item validate

  =item Invocant

  =item multisig

  =end trustme

  =head1 COOKBOOK

  =head2 Positional Parameters

     sub nth_root
     {
        state $check = compile( Num, Num );
        my ($x, $n) = $check->(@_);

        return $x ** (1 / $n);
     }

  =head2 Method Calls

  Type::Params exports an additional keyword C<Invocant> on request. This is
  a type constraint accepting blessed objects and also class names.

     use Types::Standard qw( ClassName Object Str Int );
     use Type::Params qw( compile Invocant );

     # a class method
     sub new_from_json
     {
        state $check = compile( ClassName, Str );
        my ($class, $json) = $check->(@_);

        $class->new( from_json($json) );
     }

     # an object method
     sub dump
     {
        state $check = compile( Object, Int );
        my ($self, $limit) = $check->(@_);

        local $Data::Dumper::Maxdepth = $limit;
        print Data::Dumper::Dumper($self);
     }

     # can be called as either and object or class method
     sub run
     {
        state $check = compile( Invocant );
        my ($proto) = $check->(@_);

        my $self = ref($proto) ? $proto : $default_instance;
        $self->_run;
     }

  =head2 Optional Parameters

     use Types::Standard qw( Object Optional Int );

     sub dump
     {
        state $check = compile( Object, Optional[Int] );
        my ($self, $limit) = $check->(@_);
        $limit //= 0;

        local $Data::Dumper::Maxdepth = $limit;
        print Data::Dumper::Dumper($self);
     }

     $obj->dump(1);      # ok
     $obj->dump();       # ok
     $obj->dump(undef);  # dies

  =head2 Slurpy Parameters

     use Types::Standard qw( slurpy ClassName HashRef );

     sub new
     {
        state $check = compile( ClassName, slurpy HashRef );
        my ($class, $ref) = $check->(@_);
        bless $ref => $class;
     }

     __PACKAGE__->new(foo => 1, bar => 2);

  The following types from L<Types::Standard> can be made slurpy:
  C<ArrayRef>, C<Tuple>, C<HashRef>, C<Map>, C<Dict>. Hash-like types
  will die if an odd number of elements are slurped in.

  A check may only have one slurpy parameter, and it must be the last
  parameter.

  =head2 Named Parameters

  Just use a slurpy C<Dict>:

     use Types::Standard qw( slurpy Dict Ref Optional Int );

     sub dump
     {
        state $check = compile(
           slurpy Dict[
              var    => Ref,
              limit  => Optional[Int],
           ],
        );
        my ($arg) = $check->(@_);

        local $Data::Dumper::Maxdepth = $arg->{limit};
        print Data::Dumper::Dumper($arg->{var});
     }

     dump(var => $foo, limit => 1);   # ok
     dump(var => $foo);               # ok
     dump(limit => 1);                # dies

  =head2 Mixed Positional and Named Parameters

     use Types::Standard qw( slurpy Dict Ref Optional Int );

     sub my_print
     {
        state $check = compile(
           Str,
           slurpy Dict[
              colour => Optional[Str],
              size   => Optional[Int],
           ],
        );
        my ($string, $arg) = $check->(@_);
     }

     my_print("Hello World", colour => "blue");

  =head2 Coercions

  Coercions will automatically be applied for I<all> type constraints that have
  a coercion associated.

     use Type::Utils;
     use Types::Standard qw( Int Num );

     my $RoundedInt = declare as Int;
     coerce $RoundedInt, from Num, q{ int($_) };

     sub set_age
     {
        state $check = compile( Object, $RoundedInt );
        my ($self, $age) = $check->(@_);

        $self->{age} = $age;
     }

     $obj->set_age(32.5);   # ok; coerced to "32".

  Coercions carry over into structured types such as C<ArrayRef> automatically:

     sub delete_articles
     {
        state $check = compile( Object, slurpy ArrayRef[$RoundedInt] );
        my ($db, $articles) = $check->(@_);

        $db->select_article($_)->delete for @$articles;
     }

     # delete articles 1, 2 and 3
     delete_articles($my_db, 1.1, 2.2, 3.3);

  If type C<Foo> has coercions from C<Str> and C<ArrayRef> and you want to
  B<prevent> coercion, then use:

     state $check = compile( Foo->no_coercions );

  Or if you just want to prevent coercion from C<Str>, use:

     state $check = compile( Foo->minus_coercions(Str) );

  Or maybe add an extra coercion:

     state $check = compile(
        Foo->plus_coercions(Int, q{ Foo->new_from_number($_) }),
     );

  Note that the coercion is specified as a string of Perl code. This is usually
  the fastest way to do it, but a coderef is also accepted. Either way, the
  value to be coerced is C<< $_ >>.

  =head2 Alternatives

  Type::Params can export a C<multisig> function that compiles multiple
  alternative signatures into one, and uses the first one that works:

     state $check = multisig(
        [ Int, ArrayRef ],
        [ HashRef, Num ],
        [ CodeRef ],
     );

     my ($int, $arrayref) = $check->( 1, [] );
     my ($hashref, $num)  = $check->( {}, 1.1 );
     my ($code)           = $check->( sub { 1 } );

     $check->( sub { 1 }, 1.1 );  # throws an exception

  Coercions, slurpy parameters, etc still work.

  There's currently no indication of which of the multiple signatures
  succeeded.

  The present implementation involves compiling each signature independently,
  and trying them each (in their given order!) in an C<eval> block. The only
  slightly intelligent part is that it checks if C<< scalar(@_) >> fits into
  the signature properly (taking into account optional and slurpy parameters),
  and skips evals which couldn't possibly succeed.

  It's also possible to list coderefs as alternatives in C<multisig>:

     state $check = multisig(
        [ Int, ArrayRef ],
        sub { ... },
        [ HashRef, Num ],
        [ CodeRef ],
     );

  The coderef is expected to die if that alternative should be abandoned (and
  the next alternative tried), or return the list of accepted parameters. Here's
  a full example:

     sub get_from {
        state $check = multisig(
           [ Int, ArrayRef ],
           [ Str, HashRef ],
           sub {
              my ($meth, $obj);
              die unless is_Object($obj);
              die unless $obj->can($meth);
              return ($meth, $obj);
           },
        );
        my ($needle, $haystack) = $check->(@_);

        is_HashRef($haystack)  ? $haystack->{$needle} :
        is_ArrayRef($haystack) ? $haystack->[$needle] :
        is_Object($haystack)   ? $haystack->$needle   :
        die;
     }

     get_from(0, \@array);      # returns $array[0]
     get_from('foo', \%hash);   # returns $hash{foo}
     get_from('foo', $obj);     # returns $obj->foo

  =head1 COMPARISON WITH PARAMS::VALIDATE

  L<Type::Params> is not really a drop-in replacement for L<Params::Validate>;
  the API differs far too much to claim that. Yet it performs a similar task,
  so it makes sense to compare them.

  =over

  =item *

  Type::Params will tend to be faster if you've got a sub which is called
  repeatedly, but may be a little slower than Params::Validate for subs that
  are only called a few times. This is because it does a bunch of work the
  first time your sub is called to make subsequent calls a lot faster.

  =item *

  Type::Params is mostly geared towards positional parameters, while
  Params::Validate seems to be primarily aimed at named parameters. (Though
  either works for either.) Params::Validate doesn't appear to have a
  particularly natural way of validating a mix of positional and named
  parameters.

  =item *

  Type::Utils allows you to coerce parameters. For example, if you expect
  a L<Path::Tiny> object, you could coerce it from a string.

  =item *

  Params::Validate allows you to supply defaults for missing parameters;
  Type::Params does not, but you may be able to use coercion from Undef.

  =item *

  If you are primarily writing object-oriented code, using Moose or similar,
  and you are using Type::Tiny type constraints for your attributes, then
  using Type::Params allows you to use the same constraints for method calls.

  =item *

  Type::Params comes bundled with Types::Standard, which provides a much
  richer vocabulary of types than the type validation constants that come
  with Params::Validate. For example, Types::Standard provides constraints
  like C<< ArrayRef[Int] >> (an arrayref of integers), while the closest from
  Params::Validate is C<< ARRAYREF >>, which you'd need to supplement with
  additional callbacks if you wanted to check that the arrayref contained
  integers.

  Whatsmore, Type::Params doesn't just work with Types::Standard, but also
  any other Type::Tiny type constraints.

  =back

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Type::Tiny>, L<Type::Coercion>, L<Types::Standard>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

TYPE_PARAMS

$fatpacked{"Type/Parser.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TYPE_PARSER';
  package Type::Parser;

  use strict;
  use warnings;

  sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }

  our $AUTHORITY = 'cpan:TOBYINK';
  our $VERSION   = '1.000005';

  # Token types
  #
  sub TYPE      () { "TYPE" };
  sub QUOTELIKE () { "QUOTELIKE" };
  sub STRING    () { "STRING" };
  sub CLASS     () { "CLASS" };
  sub L_BRACKET () { "L_BRACKET" };
  sub R_BRACKET () { "R_BRACKET" };
  sub COMMA     () { "COMMA" };
  sub SLURPY    () { "SLURPY" };
  sub UNION     () { "UNION" };
  sub INTERSECT () { "INTERSECT" };
  sub NOT       () { "NOT" };
  sub L_PAREN   () { "L_PAREN" };
  sub R_PAREN   () { "R_PAREN" };
  sub MYSTERY   () { "MYSTERY" };

  our @EXPORT_OK = qw( eval_type _std_eval parse extract_type );

  require Exporter::Tiny;
  our @ISA = 'Exporter::Tiny';

  Evaluate: {

  	sub parse
  	{
  		my $str = $_[0];
  		my $parser = "Type::Parser::AstBuilder"->new(input => $str);
  		$parser->build;
  		wantarray ? ($parser->ast, $parser->remainder) : $parser->ast;
  	}

  	sub extract_type
  	{
  		my ($str, $reg) = @_;
  		my ($parsed, $tail) = parse($str);
  		wantarray ? (_eval_type($parsed, $reg), $tail) : _eval_type($parsed, $reg);
  	}

  	sub eval_type
  	{
  		my ($str, $reg) = @_;
  		my ($parsed, $tail) = parse($str);
  		_croak("Unexpected tail on type expression: $tail") if $tail =~ /\S/sm;
  		return _eval_type($parsed, $reg);
  	}

  	my $std;
  	sub _std_eval
  	{
  		require Type::Registry;
  		unless ($std)
  		{
  			$std = "Type::Registry"->new;
  			$std->add_types(-Standard);
  		}
  		eval_type($_[0], $std);
  	}

  	sub _eval_type
  	{
  		my ($node, $reg) = @_;

  		$node = _simplify_expression($node);

  		if ($node->{type} eq "list")
  		{
  			return map _eval_type($_, $reg), @{$node->{list}};
  		}

  		if ($node->{type} eq "union")
  		{
  			return $reg->make_union(
  				map _eval_type($_, $reg), @{$node->{union}}
  			);
  		}

  		if ($node->{type} eq "intersect")
  		{
  			return $reg->make_intersection(
  				map _eval_type($_, $reg), @{$node->{intersect}}
  			);
  		}

  		if ($node->{type} eq "slurpy")
  		{
  			return +{ slurpy => _eval_type($node->{of}, $reg) };
  		}

  		if ($node->{type} eq "complement")
  		{
  			return _eval_type($node->{of}, $reg)->complementary_type;
  		}

  		if ($node->{type} eq "parameterized")
  		{
  			my $base = _eval_type($node->{base}, $reg);

  			return $base unless $base->is_parameterizable || $node->{params};
  			return $base->parameterize($node->{params} ? _eval_type($node->{params}, $reg) : ());
  		}

  		if ($node->{type} eq "primary" and $node->{token}->type eq CLASS)
  		{
  			my $class = substr(
  				$node->{token}->spelling,
  				0,
  				length($node->{token}->spelling) - 2
  			);
  			return $reg->make_class_type($class);
  		}

  		if ($node->{type} eq "primary" and $node->{token}->type eq QUOTELIKE)
  		{
  			return eval($node->{token}->spelling); #ARGH
  		}

  		if ($node->{type} eq "primary" and $node->{token}->type eq STRING)
  		{
  			return $node->{token}->spelling;
  		}

  		if ($node->{type} eq "primary" and $node->{token}->type eq TYPE)
  		{
  			my $t = $node->{token}->spelling;
  			my $r = ($t =~ /^(.+)::(\w+)$/)
  				? $reg->foreign_lookup($t, 1)
  				: $reg->simple_lookup($t, 1);
  			$r or _croak("%s is not a known type constraint", $node->{token}->spelling);
  			return $r;
  		}
  	}

  	sub _simplify_expression
  	{
  		my $expr = shift;

  		if ($expr->{type} eq "expression" and $expr->{op}[0] eq COMMA)
  		{
  			return _simplify("list", COMMA, $expr);
  		}

  		if ($expr->{type} eq "expression" and $expr->{op}[0] eq UNION)
  		{
  			return _simplify("union", UNION, $expr);
  		}

  		if ($expr->{type} eq "expression" and $expr->{op}[0] eq INTERSECT)
  		{
  			return _simplify("intersect", INTERSECT, $expr);
  		}

  		return $expr;
  	}

  	sub _simplify
  	{
  		my $type = shift;
  		my $op   = shift;

  		my @list;
  		for my $expr ($_[0]{lhs}, $_[0]{rhs})
  		{
  			if ($expr->{type} eq "expression" and $expr->{op}[0] eq $op)
  			{
  				my $simple = _simplify($type, $op, $expr);
  				push @list, @{ $simple->{$type} };
  			}
  			else
  			{
  				push @list, $expr;
  			}
  		}

  		return { type => $type, $type => \@list };
  	}
  }

  {
  	package # hide from CPAN
  	Type::Parser::AstBuilder;

  	sub new
  	{
  		my $class = shift;
  		bless { @_ }, $class;
  	}

  	our %precedence = (
  #		Type::Parser::COMMA()     , 1 ,
  		Type::Parser::UNION()     , 2 ,
  		Type::Parser::INTERSECT() , 3 ,
  		Type::Parser::NOT()       , 4 ,
  	);

  	sub _parse_primary
  	{
  		my $self   = shift;
  		my $tokens = $self->{tokens};

  		$tokens->assert_not_empty;

  		if ($tokens->peek(0)->type eq Type::Parser::NOT)
  		{
  			$tokens->eat(Type::Parser::NOT);
  			$tokens->assert_not_empty;
  			return {
  				type  => "complement",
  				of    => $self->_parse_primary,
  			};
  		}

  		if ($tokens->peek(0)->type eq Type::Parser::SLURPY)
  		{
  			$tokens->eat(Type::Parser::SLURPY);
  			$tokens->assert_not_empty;
  			return {
  				type  => "slurpy",
  				of    => $self->_parse_primary,
  			};
  		}

  		if ($tokens->peek(0)->type eq Type::Parser::L_PAREN)
  		{
  			$tokens->eat(Type::Parser::L_PAREN);
  			my $r = $self->_parse_expression;
  			$tokens->eat(Type::Parser::R_PAREN);
  			return $r;
  		}

  		if ($tokens->peek(1)
  		and $tokens->peek(0)->type eq Type::Parser::TYPE
  		and $tokens->peek(1)->type eq Type::Parser::L_BRACKET)
  		{
  			my $base = { type  => "primary", token => $tokens->eat(Type::Parser::TYPE) };
  			$tokens->eat(Type::Parser::L_BRACKET);
  			$tokens->assert_not_empty;

  			local $precedence{ Type::Parser::COMMA() } = 1;

  			my $params = undef;
  			if ($tokens->peek(0)->type eq Type::Parser::R_BRACKET)
  			{
  				$tokens->eat(Type::Parser::R_BRACKET);
  			}
  			else
  			{
  				$params = $self->_parse_expression;
  				$params = { type => "list", list => [$params] } unless $params->{type} eq "list";
  				$tokens->eat(Type::Parser::R_BRACKET);
  			}
  			return {
  				type   => "parameterized",
  				base   => $base,
  				params => $params,
  			};
  		}

  		my $type = $tokens->peek(0)->type;
  		if ($type eq Type::Parser::TYPE
  		or  $type eq Type::Parser::QUOTELIKE
  		or  $type eq Type::Parser::STRING
  		or  $type eq Type::Parser::CLASS)
  		{
  			return { type  => "primary", token => $tokens->eat };
  		}

  		Type::Parser::_croak("Unexpected token in primary type expression; got '%s'", $tokens->peek(0)->spelling);
  	}

  	sub _parse_expression_1
  	{
  		my $self   = shift;
  		my $tokens = $self->{tokens};

  		my ($lhs, $min_p) = @_;
  		while (!$tokens->empty and defined($precedence{$tokens->peek(0)->type}) and $precedence{$tokens->peek(0)->type} >= $min_p)
  		{
  			my $op  = $tokens->eat;
  			my $rhs = $self->_parse_primary;

  			while (!$tokens->empty and defined($precedence{$tokens->peek(0)->type}) and $precedence{$tokens->peek(0)->type} > $precedence{$op->type})
  			{
  				my $lookahead = $tokens->peek(0);
  				$rhs = $self->_parse_expression_1($rhs, $precedence{$lookahead->type});
  			}

  			$lhs = {
  				type => "expression",
  				op   => $op,
  				lhs  => $lhs,
  				rhs  => $rhs,
  			};
  		}
  		return $lhs;
  	}

  	sub _parse_expression
  	{
  		my $self   = shift;
  		my $tokens = $self->{tokens};

  		return $self->_parse_expression_1($self->_parse_primary, 0);
  	}

  	sub build
  	{
  		my $self = shift;
  		$self->{tokens} = "Type::Parser::TokenStream"->new(remaining => $self->{input});
  		$self->{ast}    = $self->_parse_expression;
  	}

  	sub ast
  	{
  		$_[0]{ast};
  	}

  	sub remainder
  	{
  		$_[0]{tokens}->remainder;
  	}
  }

  {
  	package # hide from CPAN
  	Type::Parser::Token;
  	sub type     { $_[0][0] }
  	sub spelling { $_[0][1] }
  }

  {
  	package # hide from CPAN
  	Type::Parser::TokenStream;

  	use Scalar::Util qw(looks_like_number);
  	use Text::Balanced qw(extract_quotelike);

  	sub new
  	{
  		my $class = shift;
  		bless { stack => [], done => [], @_ }, $class;
  	}

  	sub peek
  	{
  		my $self  = shift;
  		my $ahead = $_[0];

  		while ($self->_stack_size <= $ahead and length $self->{remaining})
  		{
  			$self->_stack_extend;
  		}

  		my @tokens = grep ref, @{ $self->{stack} };
  		return $tokens[$ahead];
  	}

  	sub empty
  	{
  		my $self = shift;
  		not $self->peek(0);
  	}

  	sub eat
  	{
  		my $self = shift;
  		$self->_stack_extend unless $self->_stack_size;
  		my $r;
  		while (defined(my $item = shift @{$self->{stack}}))
  		{
  			push @{ $self->{done} }, $item;
  			if (ref $item)
  			{
  				$r = $item;
  				last;
  			}
  		}

  		if (@_ and $_[0] ne $r->type)
  		{
  			unshift @{$self->{stack}}, pop @{$self->{done}};
  			Type::Parser::_croak("Expected $_[0]; got ".$r->type);
  		}

  		return $r;
  	}

  	sub assert_not_empty
  	{
  		my $self = shift;
  		Type::Parser::_croak("Expected token; got empty string") if $self->empty;
  	}

  	sub _stack_size
  	{
  		my $self = shift;
  		scalar grep ref, @{ $self->{stack} };
  	}

  	sub _stack_extend
  	{
  		my $self = shift;
  		push @{ $self->{stack} }, $self->_read_token;
  		my ($space) = ($self->{remaining} =~ m/^([\s\n\r]*)/sm);
  		return unless length $space;
  		push @{ $self->{stack} }, $space;
  		substr($self->{remaining}, 0, length $space) = "";
  	}

  	sub remainder
  	{
  		my $self = shift;
  		return join "",
  			map { ref($_) ? $_->spelling : $_ }
  			(@{$self->{stack}}, $self->{remaining})
  	}

  	my %punctuation = (
  		'['       => bless([ Type::Parser::L_BRACKET, "[" ], "Type::Parser::Token"),
  		']'       => bless([ Type::Parser::R_BRACKET, "]" ], "Type::Parser::Token"),
  		'('       => bless([ Type::Parser::L_PAREN,   "[" ], "Type::Parser::Token"),
  		')'       => bless([ Type::Parser::R_PAREN,   "]" ], "Type::Parser::Token"),
  		','       => bless([ Type::Parser::COMMA,     "," ], "Type::Parser::Token"),
  		'=>'      => bless([ Type::Parser::COMMA,     "=>" ], "Type::Parser::Token"),
  		'slurpy'  => bless([ Type::Parser::SLURPY,    "slurpy" ], "Type::Parser::Token"),
  		'|'       => bless([ Type::Parser::UNION,     "|" ], "Type::Parser::Token"),
  		'&'       => bless([ Type::Parser::INTERSECT, "&" ], "Type::Parser::Token"),
  		'~'       => bless([ Type::Parser::NOT,       "~" ], "Type::Parser::Token"),
  	);

  	sub _read_token
  	{
  		my $self = shift;

  		return if $self->{remaining} eq "";

  		# Punctuation
  		#

  		if ($self->{remaining} =~ /^( => | [()\]\[|&~,] )/xsm)
  		{
  			my $spelling = $1;
  			substr($self->{remaining}, 0, length $spelling) = "";
  			return $punctuation{$spelling};
  		}

  		if (my $quotelike = extract_quotelike $self->{remaining})
  		{
  			return bless([ Type::Parser::QUOTELIKE, $quotelike ], "Type::Parser::Token"),;
  		}

  		if ($self->{remaining} =~ /^([+-]?[\w:.+]+)/sm)
  		{
  			my $spelling = $1;
  			substr($self->{remaining}, 0, length $spelling) = "";

  			if ($spelling =~ /::$/sm)
  			{
  				return bless([ Type::Parser::CLASS, $spelling ], "Type::Parser::Token"),;
  			}
  			elsif (looks_like_number($spelling))
  			{
  				return bless([ Type::Parser::STRING, $spelling ], "Type::Parser::Token"),;
  			}
  			elsif ($self->{remaining} =~ /^\s*=>/sm) # peek ahead
  			{
  				return bless([ Type::Parser::STRING, $spelling ], "Type::Parser::Token"),;
  			}
  			elsif ($spelling eq "slurpy")
  			{
  				return $punctuation{$spelling};
  			}

  			return bless([ Type::Parser::TYPE, $spelling ], "Type::Parser::Token");
  		}

  		my $rest = $self->{remaining};
  		$self->{remaining} = "";
  		return bless([ Type::Parser::MYSTERY, $rest ], "Type::Parser::Token");
  	}
  }

  1;

  __END__

  =pod

  =encoding utf-8

  =for stopwords non-whitespace

  =head1 NAME

  Type::Parser - parse type constraint strings

  =head1 SYNOPSIS

   use v5.10;
   use strict;
   use warnings;

   use Type::Parser qw( eval_type );
   use Type::Registry;

   my $reg = Type::Registry->for_me;
   $reg->add_types("Types::Standard");

   my $type = eval_type("Int | ArrayRef[Int]", $reg);

   $type->check(10);        # true
   $type->check([1..4]);    # true
   $type->check({foo=>1});  # false

  =head1 STATUS

  This module is covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  Generally speaking, you probably don't want to be using this module directly.
  Instead use the C<< lookup >> method from L<Type::Registry> which wraps it.

  =head2 Functions

  =over

  =item C<< parse($string) >>

  Parse the type constraint string into something like an AST.

  If called in list context, also returns any "tail" found on the original string.

  =item C<< extract_type($string, $registry) >>

  Compile a type constraint string into a L<Type::Tiny> object.

  If called in list context, also returns any "tail" found on the original string.

  =item C<< eval_type($string, $registry) >>

  Compile a type constraint string into a L<Type::Tiny> object.

  Throws an error if the "tail" contains any non-whitespace character.

  =back

  =head2 Constants

  The following constants correspond to values returned by C<< $token->type >>.

  =over

  =item C<< TYPE >>

  =item C<< QUOTELIKE >>

  =item C<< STRING >>

  =item C<< CLASS >>

  =item C<< L_BRACKET >>

  =item C<< R_BRACKET >>

  =item C<< COMMA >>

  =item C<< SLURPY >>

  =item C<< UNION >>

  =item C<< INTERSECT >>

  =item C<< NOT >>

  =item C<< L_PAREN >>

  =item C<< R_PAREN >>

  =item C<< MYSTERY >>

  =back

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Type::Registry>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

TYPE_PARSER

$fatpacked{"Type/Registry.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TYPE_REGISTRY';
  package Type::Registry;

  use 5.006001;
  use strict;
  use warnings;

  BEGIN {
  	$Type::Registry::AUTHORITY = 'cpan:TOBYINK';
  	$Type::Registry::VERSION   = '1.000005';
  }

  use Exporter::Tiny qw( mkopt );
  use Scalar::Util qw( refaddr );
  use Type::Parser qw( eval_type );
  use Types::TypeTiny qw( CodeLike ArrayLike to_TypeTiny );

  our @ISA = 'Exporter::Tiny';
  our @EXPORT_OK = qw(t);

  sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }

  sub _exporter_expand_sub
  {
  	my $class = shift;
  	my ($name, $value, $globals, $permitted) = @_;

  	if ($name eq "t")
  	{
  		my $caller = $globals->{into};
  		my $reg = $class->for_class(
  			ref($caller) ? sprintf('HASH(0x%08X)', refaddr($caller)) : $caller
  		);
  		return t => sub (;$) { @_ ? $reg->lookup(@_) : $reg };
  	}

  	return $class->SUPER::_exporter_expand_sub(@_);
  }

  sub new
  {
  	my $class = shift;
  	ref($class) and _croak("Not an object method");
  	bless {}, $class;
  }

  {
  	my %registries;

  	sub for_class
  	{
  		my $class = shift;
  		my ($for) = @_;
  		$registries{$for} ||= $class->new;
  	}

  	sub for_me
  	{
  		my $class = shift;
  		my $for   = caller;
  		$registries{$for} ||= $class->new;
  	}
  }

  sub add_types
  {
  	my $self = shift;
  	my $opts = mkopt(\@_);
  	for my $opt (@$opts)
  	{
  		my ($lib, $types) = @_;

  		$lib =~ s/^-/Types::/;
  		eval "require $lib";

  		my %hash;

  		if ($lib->isa("Type::Library") or $lib eq 'Types::TypeTiny')
  		{
  			$types ||= [qw/-types/];
  			ArrayLike->check($types)
  				or _croak("Expected arrayref following '%s'; got %s", $lib, $types);

  			$lib->import({into => \%hash}, @$types);
  			$hash{$_} = &{$hash{$_}}() for keys %hash;
  		}
  		elsif ($lib->isa("MooseX::Types::Base"))
  		{
  			$types ||= [];
  			ArrayLike->check($types) && (@$types == 0)
  				or _croak("Library '%s' is a MooseX::Types type constraint library. No import options currently supported", $lib);

  			require Moose::Util::TypeConstraints;
  			my $moosextypes = $lib->type_storage;
  			for my $name (sort keys %$moosextypes)
  			{
  				my $tt = to_TypeTiny(
  					Moose::Util::TypeConstraints::find_type_constraint($moosextypes->{$name})
  				);
  				$hash{$name} = $tt;
  			}
  		}
  		elsif ($lib->isa("MouseX::Types::Base"))
  		{
  			$types ||= [];
  			ArrayLike->check($types) && (@$types == 0)
  				or _croak("Library '%s' is a MouseX::Types type constraint library. No import options currently supported", $lib);

  			require Mouse::Util::TypeConstraints;
  			my $moosextypes = $lib->type_storage;
  			for my $name (sort keys %$moosextypes)
  			{
  				my $tt = to_TypeTiny(
  					Mouse::Util::TypeConstraints::find_type_constraint($moosextypes->{$name})
  				);
  				$hash{$name} = $tt;
  			}
  		}
  		else
  		{
  			_croak("%s is not a type library", $lib);
  		}

  		for my $key (sort keys %hash)
  		{
  			exists($self->{$key})
  				and $self->{$key}{uniq} != $hash{$key}{uniq}
  				and _croak("Duplicate type name: %s", $key);
  			$self->{$key} = $hash{$key};
  		}
  	}
  	$self;
  }

  sub add_type
  {
  	my $self = shift;
  	my ($type, $name) = @_;
  	$type = to_TypeTiny($type);
  	$name ||= do {
  		$type->is_anon
  			and _croak("Expected named type constraint; got anonymous type constraint");
  		$type->name;
  	};

  	exists($self->{$name})
  		and $self->{$name}{uniq} != $type->{uniq}
  		and _croak("Duplicate type name: %s", $name);

  	$self->{$name} = $type;
  	$self;
  }

  sub alias_type
  {
  	my $self = shift;
  	my ($old, @new) = @_;
  	my $lookup = eval { $self->lookup($old) }
  		or _croak("Expected existing type constraint name; got '$old'");
  	$self->{$_} = $lookup for @new;
  	$self;
  }

  sub simple_lookup
  {
  	my $self = shift;

  	my ($tc) = @_;
  	$tc =~ s/(^\s+|\s+$)//g;

  	if (exists $self->{$tc})
  	{
  		return $self->{$tc};
  	}

  	return;
  }

  sub foreign_lookup
  {
  	my $self = shift;

  	return $_[1] ? () : $self->simple_lookup($_[0], 1)
  		unless $_[0] =~ /^(.+)::(\w+)$/;

  	my $library  = $1;
  	my $typename = $2;

  	eval "require $library;";

  	if ( $library->isa('MooseX::Types::Base') )
  	{
  		require Moose::Util::TypeConstraints;
  		my $type = Moose::Util::TypeConstraints::find_type_constraint(
  			$library->get_type($typename)
  		) or return;
  		return to_TypeTiny($type);
  	}

  	if ( $library->isa('MouseX::Types::Base') )
  	{
  		require Mouse::Util::TypeConstraints;
  		my $sub  = $library->can($typename) or return;
  		my $type = Mouse::Util::TypeConstraints::find_type_constraint($sub->()) or return;
  		return to_TypeTiny($type);
  	}

  	if ( $library->can("get_type") )
  	{
  		my $type = $library->get_type($typename);
  		return to_TypeTiny($type);
  	}

  	return;
  }

  sub lookup
  {
  	my $self = shift;

  	$self->simple_lookup(@_) or eval_type($_[0], $self);
  }

  sub make_union
  {
  	my $self = shift;
  	my (@types) = @_;

  	require Type::Tiny::Union;
  	return "Type::Tiny::Union"->new(type_constraints => \@types);
  }

  sub make_intersection
  {
  	my $self = shift;
  	my (@types) = @_;

  	require Type::Tiny::Intersection;
  	return "Type::Tiny::Intersection"->new(type_constraints => \@types);
  }

  sub make_class_type
  {
  	my $self = shift;
  	my ($class) = @_;

  	require Type::Tiny::Class;
  	return "Type::Tiny::Class"->new(class => $class);
  }

  sub make_role_type
  {
  	my $self = shift;
  	my ($role) = @_;

  	require Type::Tiny::Role;
  	return "Type::Tiny::Role"->new(role => $role);
  }

  sub AUTOLOAD
  {
  	my $self = shift;
  	my ($method) = (our $AUTOLOAD =~ /(\w+)$/);
  	my $type = $self->simple_lookup($method);
  	return $type if $type;
  	_croak(q[Can't locate object method "%s" via package "%s"], $method, ref($self));
  }

  # Prevent AUTOLOAD being called for DESTROY!
  sub DESTROY
  {
  	return;
  }

  DELAYED: {
  	our %DELAYED;
  	for my $package (sort keys %DELAYED)
  	{
  		my $reg   = __PACKAGE__->for_class($package);
  		my $types = $DELAYED{$package};

  		for my $name (sort keys %$types)
  		{
  			$reg->add_type($types->{$name}, $name);
  		}
  	}
  }

  1;

  __END__

  =pod

  =encoding utf-8

  =for stopwords optlist

  =head1 NAME

  Type::Registry - a glorified hashref for looking up type constraints

  =head1 SYNOPSIS

  =for test_synopsis no warnings qw(misc);

     package Foo::Bar;

     use Type::Registry;

     my $reg = "Type::Registry"->for_me;  # a registry for Foo::Bar

     # Register all types from Types::Standard
     $reg->add_types(-Standard);

     # Register just one type from Types::XSD
     $reg->add_types(-XSD => ["NonNegativeInteger"]);

     # Register all types from MyApp::Types
     $reg->add_types("MyApp::Types");

     # Create a type alias
     $reg->alias_type("NonNegativeInteger" => "Count");

     # Look up a type constraint
     my $type = $reg->lookup("ArrayRef[Count]");

     $type->check([1, 2, 3.14159]);  # croaks

  Alternatively:

     package Foo::Bar;

     use Type::Registry qw( t );

     # Register all types from Types::Standard
     t->add_types(-Standard);

     # Register just one type from Types::XSD
     t->add_types(-XSD => ["NonNegativeInteger"]);

     # Register all types from MyApp::Types
     t->add_types("MyApp::Types");

     # Create a type alias
     t->alias_type("NonNegativeInteger" => "Count");

     # Look up a type constraint
     my $type = t("ArrayRef[Count]");

     $type->check([1, 2, 3.14159]);  # croaks

  =head1 STATUS

  This module is covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  A type registry is basically just a hashref mapping type names to type
  constraint objects.

  =head2 Constructors

  =over

  =item C<< new >>

  Create a new glorified hashref.

  =item C<< for_class($class) >>

  Create or return the existing glorified hashref associated with the given
  class.

  Note that any type constraint you have imported from Type::Library-based
  type libraries will be automatically available in your class' registry.

  =item C<< for_me >>

  Create or return the existing glorified hashref associated with the caller.

  =back

  =head2 Methods

  =over

  =item C<< add_types(@libraries) >>

  The libraries list is treated as an "optlist" (a la L<Data::OptList>).

  Strings are the names of type libraries; if the first character is a
  hyphen, it is expanded to the "Types::" prefix. If followed by an
  arrayref, this is the list of types to import from that library.
  Otherwise, imports all types from the library.

     use Type::Registry qw(t);

     t->add_types(-Standard);  # OR: t->add_types("Types::Standard");

     t->add_types(
        -TypeTiny => ['HashLike'],
        -Standard => ['HashRef' => { -as => 'RealHash' }],
     );

  L<MooseX::Types> (and experimentally, L<MouseX::Types>) libraries can
  also be added this way, but I<< cannot be followed by an arrayref of
  types to import >>.

  =item C<< add_type($type, $name) >>

  The long-awaited singular form of C<add_types>. Given a type constraint
  object, adds it to the registry with a given name. The name may be
  omitted, in which case C<< $type->name >> is called, and Type::Registry
  will throw an error if C<< $type >> is anonymous. If a name is explicitly
  given, Type::Registry cares not one wit whether the type constraint is
  anonymous.

  This method can even add L<MooseX::Types> and L<MouseX::Types> type
  constraints; indeed anything that can be handled by L<Types::TypeTiny>'s
  C<to_TypeTiny> function. (Bear in mind that to_TypeTiny I<always> results
  in an anonymous type constraint, so C<< $name >> will be required.)

  =item C<< alias_type($oldname, $newname) >>

  Create an alias for an existing type.

  =item C<< simple_lookup($name) >>

  Look up a type in the registry by name.

  Returns undef if not found.

  =item C<< foreign_lookup($name) >>

  Like C<simple_lookup>, but if the type name contains "::", will attempt
  to load it from a type library. (And will attempt to load that module.)

  =item C<< lookup($name) >>

  Look up by name, with a DSL.

     t->lookup("Int|ArrayRef[Int]")

  The DSL can be summed up as:

     X               type from this registry
     My::Lib::X      type from a type library
     ~X              complementary type
     X | Y           union
     X & Y           intersection
     X[...]          parameterized type
     slurpy X        slurpy type
     Foo::Bar::      class type

  Croaks if not found.

  =item C<< make_union(@constraints) >>,
  C<< make_intersection(@constraints) >>,
  C<< make_class_type($class) >>,
  C<< make_role_type($role) >>

  Convenience methods for creating certain common type constraints.

  =item C<< AUTOLOAD >>

  Overloaded to call C<lookup>.

     $registry->Str;  # like $registry->lookup("Str")

  =back

  =head2 Functions

  =over

  =item C<< t >>

  This class can export a function C<< t >> which acts like
  C<< "Type::Registry"->for_class($importing_class) >>.

  =back

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Type::Library>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

TYPE_REGISTRY

$fatpacked{"Type/Tiny.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TYPE_TINY';
  package Type::Tiny;

  use 5.006001;
  use strict;
  use warnings;

  BEGIN {
  	if ($] < 5.008) { require Devel::TypeTiny::Perl56Compat };
  }

  BEGIN {
  	$Type::Tiny::AUTHORITY   = 'cpan:TOBYINK';
  	$Type::Tiny::VERSION     = '1.000005';
  	$Type::Tiny::XS_VERSION  = '0.010';
  }

  use Eval::TypeTiny ();
  use Scalar::Util qw( blessed weaken refaddr isweak );
  use Types::TypeTiny ();

  sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }

  sub _swap { $_[2] ? @_[1,0] : @_[0,1] }

  BEGIN {
  	($] < 5.010001)
  		? eval q{ sub SUPPORT_SMARTMATCH () { !!0 } }
  		: eval q{ sub SUPPORT_SMARTMATCH () { !!1 } };
  	($] >= 5.014)
  		? eval q{ sub _FIXED_PRECEDENCE () { !!1 } }
  		: eval q{ sub _FIXED_PRECEDENCE () { !!0 } };
  };

  BEGIN {
  	my $try_xs =
  		exists($ENV{PERL_TYPE_TINY_XS}) ? !!$ENV{PERL_TYPE_TINY_XS} :
  		exists($ENV{PERL_ONLY})         ?  !$ENV{PERL_ONLY} :
  		1;

  	my $use_xs = 0;
  	$try_xs and eval {
  		require Type::Tiny::XS;
  		'Type::Tiny::XS'->VERSION($Type::Tiny::XS_VERSION);
  		$use_xs++;
  	};

  	*_USE_XS = $use_xs
  		? sub () { !!1 }
  		: sub () { !!0 };

  	*_USE_MOUSE = $try_xs
  		? sub () { $INC{'Mouse/Util.pm'} and Mouse::Util::MOUSE_XS() }
  		: sub () { !!0 };
  };

  use overload
  	q("")      => sub { caller =~ m{^(Moo::HandleMoose|Sub::Quote)} ? overload::StrVal($_[0]) : $_[0]->display_name },
  	q(bool)    => sub { 1 },
  	q(&{})     => "_overload_coderef",
  	q(|)       => sub {
  		my @tc = _swap @_;
  		if (!_FIXED_PRECEDENCE && !blessed $tc[0] && ref $tc[0] eq 'ARRAY') {
  			require Type::Tiny::_HalfOp;
  			return "Type::Tiny::_HalfOp"->new('|', @tc);
  		}
  		require Type::Tiny::Union;
  		"Type::Tiny::Union"->new(type_constraints => \@tc)
  	},
  	q(&)       => sub {
  		my @tc = _swap @_;
  		if (!_FIXED_PRECEDENCE && !blessed $tc[0] && ref $tc[0] eq 'ARRAY') {
  			require Type::Tiny::_HalfOp;
  			return "Type::Tiny::_HalfOp"->new('&', @tc);
  		}
  		require Type::Tiny::Intersection;
  		"Type::Tiny::Intersection"->new(type_constraints => \@tc)
  	},
  	q(~)       => sub { shift->complementary_type },
  	q(==)      => sub { $_[0]->equals($_[1]) },
  	q(<)       => sub { my $m = $_[0]->can('is_subtype_of'); $m->(_swap @_) },
  	q(>)       => sub { my $m = $_[0]->can('is_subtype_of'); $m->(reverse _swap @_) },
  	q(<=)      => sub { my $m = $_[0]->can('is_a_type_of');  $m->(_swap @_) },
  	q(>=)      => sub { my $m = $_[0]->can('is_a_type_of');  $m->(reverse _swap @_) },
  	q(eq)      => sub { "$_[0]" eq "$_[1]" },
  	q(cmp)     => sub { $_[2] ? ("$_[1]" cmp "$_[0]") : ("$_[0]" cmp "$_[1]") },
  	fallback   => 1,
  ;
  BEGIN {
  	overload->import(
  		q(~~)    => sub { $_[0]->check($_[1]) },
  		fallback => 1, # 5.10 loses the fallback otherwise
  	) if Type::Tiny::SUPPORT_SMARTMATCH;
  }

  sub _overload_coderef
  {
  	my $self = shift;
  	$self->message unless exists $self->{message};

  #	if ($self->has_parent && $self->_is_null_constraint)
  #	{
  #		$self->{_overload_coderef} ||= $self->parent->_overload_coderef;
  #	}
  #	els
  	if (!exists($self->{message}) && exists(&Sub::Quote::quote_sub) && $self->can_be_inlined)
  	{
  		$self->{_overload_coderef} = Sub::Quote::quote_sub($self->inline_assert('$_[0]'))
  			if !$self->{_overload_coderef} || !$self->{_sub_quoted}++;
  	}
  	else
  	{
  		$self->{_overload_coderef} ||= sub { $self->assert_return(@_) };
  	}

  	$self->{_overload_coderef};
  }

  our %ALL_TYPES;

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

  	if (exists $params{parent})
  	{
  		$params{parent} = ref($params{parent}) =~ /^Type::Tiny\b/
  			? $params{parent}
  			: Types::TypeTiny::to_TypeTiny($params{parent});

  		_croak "Parent must be an instance of %s", __PACKAGE__
  			unless blessed($params{parent}) && $params{parent}->isa(__PACKAGE__);
  	}

  	$params{name} = "__ANON__" unless exists $params{name};
  	$params{uniq} = $uniq++;

  	if ($params{name} ne "__ANON__")
  	{
  		# First try a fast ASCII-only expression, but fall back to Unicode
  		$params{name} =~ /^_{0,2}[A-Z][A-Za-z0-9_]+$/sm
  			or eval q( use 5.008; $params{name} =~ /^_{0,2}\p{Lu}[\p{L}0-9_]+$/sm )
  			or _croak '"%s" is not a valid type name', $params{name};
  	}

  	if (exists $params{coercion} and !ref $params{coercion} and $params{coercion})
  	{
  		$params{parent}->has_coercion
  			or _croak "coercion => 1 requires type to have a direct parent with a coercion";

  		$params{coercion} = $params{parent}->coercion->type_coercion_map;
  	}

  	if (!exists $params{inlined}
  	and exists $params{constraint}
  	and ( !exists $params{parent} or $params{parent}->can_be_inlined )
  	and $QFS ||= "Sub::Quote"->can("quoted_from_sub"))
  	{
  		my (undef, $perlstring, $captures) = @{ $QFS->($params{constraint}) || [] };

  		$params{inlined} = sub {
  			my ($self, $var) = @_;
  			my $code = Sub::Quote::inlinify(
  				$perlstring,
  				$var,
  				$var eq q($_) ? '' : "local \$_ = $var;",
  				1,
  			);
  			$code = sprintf('%s and %s', $self->parent->inline_check($var), $code) if $self->has_parent;
  			return $code;
  		} if $perlstring && !$captures;
  	}

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

  	unless ($params{tmp})
  	{
  		my $uniq = $self->{uniq};

  		$ALL_TYPES{$uniq} = $self;
  		weaken( $ALL_TYPES{$uniq} );

  		package # no index
  			Moo::HandleMoose;
  		my $tmp = $self;
  		Scalar::Util::weaken($tmp);
  		$Moo::HandleMoose::TYPE_MAP{$self} = sub { $tmp };
  	}

  	if (ref($params{coercion}) eq q(CODE))
  	{
  		require Types::Standard;
  		my $code = delete($params{coercion});
  		$self->{coercion} = $self->_build_coercion;
  		$self->coercion->add_type_coercions(Types::Standard::Any(), $code);
  	}
  	elsif (ref($params{coercion}) eq q(ARRAY))
  	{
  		my $arr = delete($params{coercion});
  		$self->{coercion} = $self->_build_coercion;
  		$self->coercion->add_type_coercions(@$arr);
  	}

  	if ($params{my_methods} and eval { require Sub::Name })
  	{
  		for my $key (keys %{$params{my_methods}})
  		{
  			Sub::Name::subname(
  				sprintf("%s::my_%s", $self->qualified_name, $key),
  				$params{my_methods}{$key},
  			);
  		}
  	}

  	return $self;
  }

  sub DESTROY
  {
  	my $self = shift;
  	delete( $ALL_TYPES{$self->{uniq}} );
  	package # no index
  		Moo::HandleMoose;
  	delete( $Moo::HandleMoose::TYPE_MAP{$self} );
  	return;
  }

  sub _clone
  {
  	my $self = shift;
  	my %opts;
  	$opts{$_} = $self->{$_} for qw< name display_name message >;
  	$self->create_child_type(%opts);
  }

  our $DD;
  sub _dd
  {
  	@_ = $_ unless @_;
  	my ($value) = @_;

  	goto $DD if ref($DD) eq q(CODE);

  	require B;

  	!defined $value ? 'Undef' :
  	!ref $value     ? sprintf('Value %s', B::perlstring($value)) :
  	do {
  		my $N = 0 + (defined($DD) ? $DD : 72);
  		require Data::Dumper;
  		local $Data::Dumper::Indent   = 0;
  		local $Data::Dumper::Useqq    = 1;
  		local $Data::Dumper::Terse    = 1;
  		local $Data::Dumper::Sortkeys = 1;
  		local $Data::Dumper::Maxdepth = 2;
  		my $str = Data::Dumper::Dumper($value);
  		$str = substr($str, 0, $N - 12).'...'.substr($str, -1, 1)
  			if length($str) >= $N;
  		"Reference $str";
  	}
  }

  sub _loose_to_TypeTiny
  {
  	map +(
  		ref($_)
  			? Types::TypeTiny::to_TypeTiny($_)
  			: do { require Type::Utils; Type::Utils::dwim_type($_) }
  	), @_;
  }

  sub name                     { $_[0]{name} }
  sub display_name             { $_[0]{display_name}   ||= $_[0]->_build_display_name }
  sub parent                   { $_[0]{parent} }
  sub constraint               { $_[0]{constraint}     ||= $_[0]->_build_constraint }
  sub compiled_check           { $_[0]{compiled_type_constraint} ||= $_[0]->_build_compiled_check }
  sub coercion                 { $_[0]{coercion}       ||= $_[0]->_build_coercion }
  sub message                  { $_[0]{message} }
  sub library                  { $_[0]{library} }
  sub inlined                  { $_[0]{inlined} }
  sub constraint_generator     { $_[0]{constraint_generator} }
  sub inline_generator         { $_[0]{inline_generator} }
  sub name_generator           { $_[0]{name_generator} ||= $_[0]->_build_name_generator }
  sub coercion_generator       { $_[0]{coercion_generator} }
  sub parameters               { $_[0]{parameters} }
  sub moose_type               { $_[0]{moose_type}     ||= $_[0]->_build_moose_type }
  sub mouse_type               { $_[0]{mouse_type}     ||= $_[0]->_build_mouse_type }
  sub deep_explanation         { $_[0]{deep_explanation} }
  sub my_methods               { $_[0]{my_methods}     ||= $_[0]->_build_my_methods }

  sub has_parent               { exists $_[0]{parent} }
  sub has_library              { exists $_[0]{library} }
  sub has_coercion             {        $_[0]{coercion} and !!@{ $_[0]{coercion}->type_coercion_map } }
  sub has_inlined              { exists $_[0]{inlined} }
  sub has_constraint_generator { exists $_[0]{constraint_generator} }
  sub has_inline_generator     { exists $_[0]{inline_generator} }
  sub has_coercion_generator   { exists $_[0]{coercion_generator} }
  sub has_parameters           { exists $_[0]{parameters} }
  sub has_message              { defined $_[0]{message} }
  sub has_deep_explanation     { exists $_[0]{deep_explanation} }

  sub _default_message         { $_[0]{_default_message} ||= $_[0]->_build_default_message }

  sub _assert_coercion
  {
  	my $self = shift;
  	_croak "No coercion for this type constraint"
  		unless $self->has_coercion && @{$self->coercion->type_coercion_map};
  	return $self->coercion;
  }

  my $null_constraint = sub { !!1 };

  sub _build_display_name
  {
  	shift->name;
  }

  sub _build_constraint
  {
  	return $null_constraint;
  }

  sub _is_null_constraint
  {
  	shift->constraint == $null_constraint;
  }

  sub _build_coercion
  {
  	require Type::Coercion;
  	my $self = shift;
  	my %opts = (type_constraint => $self);
  	$opts{display_name} = "to_$self" unless $self->is_anon;
  	return "Type::Coercion"->new(%opts);
  }

  sub _build_default_message
  {
  	my $self = shift;
  	return sub { sprintf '%s did not pass type constraint', _dd($_[0]) } if "$self" eq "__ANON__";
  	my $name = "$self";
  	return sub { sprintf '%s did not pass type constraint "%s"', _dd($_[0]), $name };
  }

  sub _build_name_generator
  {
  	my $self = shift;
  	return sub {
  		my ($s, @a) = @_;
  		sprintf('%s[%s]', $s, join q[,], @a);
  	};
  }

  sub _build_compiled_check
  {
  	my $self = shift;

  	if ($self->_is_null_constraint and $self->has_parent)
  	{
  		return $self->parent->compiled_check;
  	}

  	return Eval::TypeTiny::eval_closure(
  		source      => sprintf('sub ($) { %s }', $self->inline_check('$_[0]')),
  		description => sprintf("compiled check '%s'", $self),
  	) if $self->can_be_inlined;

  	my @constraints;
  	push @constraints, $self->parent->compiled_check if $self->has_parent;
  	push @constraints, $self->constraint if !$self->_is_null_constraint;
  	return $null_constraint unless @constraints;

  	return sub ($)
  	{
  		local $_ = $_[0];
  		for my $c (@constraints)
  		{
  			return unless $c->(@_);
  		}
  		return !!1;
  	};
  }

  sub equals
  {
  	my ($self, $other) = _loose_to_TypeTiny(@_);
  	return unless blessed($self)  && $self->isa("Type::Tiny");
  	return unless blessed($other) && $other->isa("Type::Tiny");

  	return !!1 if refaddr($self) == refaddr($other);

  	return !!1 if $self->has_parent  && $self->_is_null_constraint  && $self->parent==$other;
  	return !!1 if $other->has_parent && $other->_is_null_constraint && $other->parent==$self;

  	return !!1 if refaddr($self->compiled_check) == refaddr($other->compiled_check);

  	return $self->qualified_name eq $other->qualified_name
  		if $self->has_library && !$self->is_anon && $other->has_library && !$other->is_anon;

  	return $self->inline_check('$x') eq $other->inline_check('$x')
  		if $self->can_be_inlined && $other->can_be_inlined;

  	return;
  }

  sub is_subtype_of
  {
  	my ($self, $other) = _loose_to_TypeTiny(@_);
  	return unless blessed($self)  && $self->isa("Type::Tiny");
  	return unless blessed($other) && $other->isa("Type::Tiny");

  #	my $this = $self;
  #	while (my $parent = $this->parent)
  #	{
  #		return !!1 if $parent->equals($other);
  #		$this = $parent;
  #	}
  #	return;

  	return unless $self->has_parent;
  	$self->parent->equals($other) or $self->parent->is_subtype_of($other);
  }

  sub is_supertype_of
  {
  	my ($self, $other) = _loose_to_TypeTiny(@_);
  	return unless blessed($self)  && $self->isa("Type::Tiny");
  	return unless blessed($other) && $other->isa("Type::Tiny");

  	$other->is_subtype_of($self);
  }

  sub is_a_type_of
  {
  	my ($self, $other) = _loose_to_TypeTiny(@_);
  	return unless blessed($self)  && $self->isa("Type::Tiny");
  	return unless blessed($other) && $other->isa("Type::Tiny");

  	$self->equals($other) or $self->is_subtype_of($other);
  }

  sub strictly_equals
  {
  	my ($self, $other) = _loose_to_TypeTiny(@_);
  	return unless blessed($self)  && $self->isa("Type::Tiny");
  	return unless blessed($other) && $other->isa("Type::Tiny");
  	$self->{uniq} == $other->{uniq};
  }

  sub is_strictly_subtype_of
  {
  	my ($self, $other) = _loose_to_TypeTiny(@_);
  	return unless blessed($self)  && $self->isa("Type::Tiny");
  	return unless blessed($other) && $other->isa("Type::Tiny");

  #	my $this = $self;
  #	while (my $parent = $this->parent)
  #	{
  #		return !!1 if $parent->strictly_equals($other);
  #		$this = $parent;
  #	}
  #	return;

  	return unless $self->has_parent;
  	$self->parent->strictly_equals($other) or $self->parent->is_strictly_subtype_of($other);
  }

  sub is_strictly_supertype_of
  {
  	my ($self, $other) = _loose_to_TypeTiny(@_);
  	return unless blessed($self)  && $self->isa("Type::Tiny");
  	return unless blessed($other) && $other->isa("Type::Tiny");

  	$other->is_strictly_subtype_of($self);
  }

  sub is_strictly_a_type_of
  {
  	my ($self, $other) = _loose_to_TypeTiny(@_);
  	return unless blessed($self)  && $self->isa("Type::Tiny");
  	return unless blessed($other) && $other->isa("Type::Tiny");

  	$self->strictly_equals($other) or $self->is_strictly_subtype_of($other);
  }

  sub qualified_name
  {
  	my $self = shift;
  	(exists $self->{library} and $self->name ne "__ANON__")
  		? "$self->{library}::$self->{name}"
  		: $self->{name};
  }

  sub is_anon
  {
  	my $self = shift;
  	$self->name eq "__ANON__";
  }

  sub parents
  {
  	my $self = shift;
  	return unless $self->has_parent;
  	return ($self->parent, $self->parent->parents);
  }

  sub find_parent
  {
  	my $self = shift;
  	my ($test) = @_;

  	local ($_, $.);
  	my $type  = $self;
  	my $count = 0;
  	while ($type)
  	{
  		if ($test->($_=$type, $.=$count))
  		{
  			return wantarray ? ($type, $count) : $type;
  		}
  		else
  		{
  			$type = $type->parent;
  			$count++;
  		}
  	}

  	return;
  }

  sub check
  {
  	my $self = shift;
  	($self->{compiled_type_constraint} ||= $self->_build_compiled_check)->(@_);
  }

  sub _strict_check
  {
  	my $self = shift;
  	local $_ = $_[0];

  	my @constraints =
  		reverse
  		map  { $_->constraint }
  		grep { not $_->_is_null_constraint }
  		($self, $self->parents);

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

  	return !!1;
  }

  sub get_message
  {
  	my $self = shift;
  	local $_ = $_[0];
  	$self->has_message
  		? $self->message->(@_)
  		: $self->_default_message->(@_);
  }

  sub validate
  {
  	my $self = shift;

  	return undef if ($self->{compiled_type_constraint} ||= $self->_build_compiled_check)->(@_);

  	local $_ = $_[0];
  	return $self->get_message(@_);
  }

  sub validate_explain
  {
  	my $self = shift;
  	my ($value, $varname) = @_;
  	$varname = '$_' unless defined $varname;

  	return undef if $self->check($value);

  	if ($self->has_parent)
  	{
  		my $parent = $self->parent->validate_explain($value, $varname);
  		return [ sprintf('"%s" is a subtype of "%s"', $self, $self->parent), @$parent ] if $parent;
  	}

  	my $message = sprintf(
  		'%s%s',
  		$self->get_message($value),
  		$varname eq q{$_} ? '' : sprintf(' (in %s)', $varname),
  	);

  	if ($self->is_parameterized and $self->parent->has_deep_explanation)
  	{
  		my $deep = $self->parent->deep_explanation->($self, $value, $varname);
  		return [ $message, @$deep ] if $deep;
  	}

  	return [ $message, sprintf('"%s" is defined as: %s', $self, $self->_perlcode) ];
  }

  my $b;
  sub _perlcode
  {
  	my $self = shift;

  	return $self->inline_check('$_')
  		if $self->can_be_inlined;

  	$b ||= do {
  		require B::Deparse;
  		my $tmp = "B::Deparse"->new;
  		$tmp->ambient_pragmas(strict => "all", warnings => "all") if $tmp->can('ambient_pragmas');
  		$tmp;
  	};

  	my $code = $b->coderef2text($self->constraint);
  	$code =~ s/\s+/ /g;
  	return "sub $code";
  }

  sub assert_valid
  {
  	my $self = shift;

  	return !!1 if ($self->{compiled_type_constraint} ||= $self->_build_compiled_check)->(@_);

  	local $_ = $_[0];
  	$self->_failed_check("$self", $_);
  }

  sub assert_return
  {
  	my $self = shift;

  	return $_[0] if ($self->{compiled_type_constraint} ||= $self->_build_compiled_check)->(@_);

  	local $_ = $_[0];
  	$self->_failed_check("$self", $_);
  }

  sub can_be_inlined
  {
  	my $self = shift;
  	return $self->parent->can_be_inlined
  		if $self->has_parent && $self->_is_null_constraint;
  	return !!1
  		if !$self->has_parent && $self->_is_null_constraint;
  	return $self->has_inlined;
  }

  sub inline_check
  {
  	my $self = shift;
  	_croak 'Cannot inline type constraint check for "%s"', $self
  		unless $self->can_be_inlined;

  	return $self->parent->inline_check(@_)
  		if $self->has_parent && $self->_is_null_constraint;
  	return '(!!1)'
  		if !$self->has_parent && $self->_is_null_constraint;

  	local $_ = $_[0];
  	my @r = $self->inlined->($self, @_);
  	if (@r and not defined $r[0])
  	{
  		_croak 'Inlining type constraint check for "%s" returned undef!', $self
  			unless $self->has_parent;
  		$r[0] = $self->parent->inline_check(@_);
  	}
  	my $r = join " && " => map { /[;{}]/ ? "do { $_ }" : "($_)" } @r;
  	return @r==1 ? $r : "($r)";
  }

  sub inline_assert
  {
  	require B;
  	my $self = shift;
  	my $varname = $_[0];
  	my $code = sprintf(
  		q[do { no warnings "void"; %s ? %s : Type::Tiny::_failed_check(%d, %s, %s) };],
  		$self->inline_check(@_),
  		$varname,
  		$self->{uniq},
  		B::perlstring("$self"),
  		$varname,
  	);
  	return $code;
  }

  sub _failed_check
  {
  	require Error::TypeTiny::Assertion;

  	my ($self, $name, $value, %attrs) = @_;
  	$self = $ALL_TYPES{$self} unless ref $self;

  	my $exception_class = delete($attrs{exception_class}) || "Error::TypeTiny::Assertion";

  	if ($self)
  	{
  		$exception_class->throw(
  			message => $self->get_message($value),
  			type    => $self,
  			value   => $value,
  			%attrs,
  		);
  	}
  	else
  	{
  		$exception_class->throw(
  			message => sprintf('%s did not pass type constraint "%s"', _dd($value), $name),
  			value   => $value,
  			%attrs,
  		);
  	}
  }

  sub coerce
  {
  	my $self = shift;
  	$self->_assert_coercion->coerce(@_);
  }

  sub assert_coerce
  {
  	my $self = shift;
  	$self->_assert_coercion->assert_coerce(@_);
  }

  sub is_parameterizable
  {
  	shift->has_constraint_generator;
  }

  sub is_parameterized
  {
  	shift->has_parameters;
  }

  my %param_cache;
  sub parameterize
  {
  	my $self = shift;

  	$self->is_parameterizable
  		or @_ ? _croak("Type '%s' does not accept parameters", "$self") : return($self);

  	@_ = map Types::TypeTiny::to_TypeTiny($_), @_;

  	# Generate a key for caching parameterized type constraints,
  	# but only if all the parameters are strings or type constraints.
  	my $key;
  	if ( not grep(ref($_) && !Types::TypeTiny::TypeTiny->check($_), @_) )
  	{
  		require B;
  		$key = join ":", map(Types::TypeTiny::TypeTiny->check($_) ? $_->{uniq} : B::perlstring($_), $self, @_);
  	}

  	return $param_cache{$key} if defined $key && defined $param_cache{$key};

  	local $Type::Tiny::parameterize_type = $self;
  	local $_ = $_[0];
  	my $P;

  	my ($constraint, $compiled) = $self->constraint_generator->(@_);

  	if (Types::TypeTiny::TypeTiny->check($constraint))
  	{
  		$P = $constraint;
  	}
  	else
  	{
  		my %options = (
  			constraint   => $constraint,
  			display_name => $self->name_generator->($self, @_),
  			parameters   => [@_],
  		);
  		$options{compiled_type_constraint} = $compiled
  			if $compiled;
  		$options{inlined} = $self->inline_generator->(@_)
  			if $self->has_inline_generator;
  		exists $options{$_} && !defined $options{$_} && delete $options{$_}
  			for keys %options;

  		$P = $self->create_child_type(%options);

  		my $coercion;
  		$coercion = $self->coercion_generator->($self, $P, @_)
  			if $self->has_coercion_generator;
  		$P->coercion->add_type_coercions( @{$coercion->type_coercion_map} )
  			if $coercion;
  	}

  	if (defined $key)
  	{
  		$param_cache{$key} = $P;
  		weaken($param_cache{$key});
  	}

  	$P->coercion->freeze;

  	return $P;
  }

  sub child_type_class
  {
  	__PACKAGE__;
  }

  sub create_child_type
  {
  	my $self = shift;
  	return $self->child_type_class->new(parent => $self, @_);
  }

  sub complementary_type
  {
  	my $self = shift;
  	my $r    = ($self->{complementary_type} ||= $self->_build_complementary_type);
  	weaken($self->{complementary_type}) unless isweak($self->{complementary_type});
  	return $r;
  }

  sub _build_complementary_type
  {
  	my $self = shift;
  	my %opts = (
  		constraint   => sub { not $self->check($_) },
  		display_name => sprintf("~%s", $self),
  	);
  	$opts{display_name} =~ s/^\~{2}//;
  	$opts{inlined} = sub { shift; "not(".$self->inline_check(@_).")" }
  		if $self->can_be_inlined;
  	return "Type::Tiny"->new(%opts);
  }

  sub _instantiate_moose_type
  {
  	my $self = shift;
  	my %opts = @_;
  	require Moose::Meta::TypeConstraint;
  	return "Moose::Meta::TypeConstraint"->new(%opts);
  }

  sub _build_moose_type
  {
  	my $self = shift;

  	my $r;
  	if ($self->{_is_core})
  	{
  		require Moose::Util::TypeConstraints;
  		$r = Moose::Util::TypeConstraints::find_type_constraint($self->name);
  		$r->{"Types::TypeTiny::to_TypeTiny"} = $self;
  		Scalar::Util::weaken($r->{"Types::TypeTiny::to_TypeTiny"});
  	}
  	else
  	{
  		my $wrapped_inlined = sub {
  			shift;
  			$self->inline_check(@_);
  		};

  		my %opts;
  		$opts{name}       = $self->qualified_name     if $self->has_library && !$self->is_anon;
  		$opts{parent}     = $self->parent->moose_type if $self->has_parent;
  		$opts{constraint} = $self->constraint         unless $self->_is_null_constraint;
  		$opts{message}    = $self->message            if $self->has_message;
  		$opts{inlined}    = $wrapped_inlined          if $self->has_inlined;

  		$r = $self->_instantiate_moose_type(%opts);
  		$r->{"Types::TypeTiny::to_TypeTiny"} = $self;
  		$self->{moose_type} = $r;  # prevent recursion
  		$r->coercion($self->coercion->moose_coercion) if $self->has_coercion;
  	}

  	return $r;
  }

  sub _build_mouse_type
  {
  	my $self = shift;

  	my %options;
  	$options{name}       = $self->qualified_name     if $self->has_library && !$self->is_anon;
  	$options{parent}     = $self->parent->mouse_type if $self->has_parent;
  	$options{constraint} = $self->constraint         unless $self->_is_null_constraint;
  	$options{message}    = $self->message            if $self->has_message;

  	require Mouse::Meta::TypeConstraint;
  	my $r = "Mouse::Meta::TypeConstraint"->new(%options);

  	$self->{mouse_type} = $r;  # prevent recursion
  	$r->_add_type_coercions(
  		$self->coercion->freeze->_codelike_type_coercion_map('mouse_type')
  	) if $self->has_coercion;

  	return $r;
  }

  sub _process_coercion_list
  {
  	my $self = shift;

  	my @pairs;
  	while (@_)
  	{
  		my $next = shift;
  		if (blessed($next) and $next->isa('Type::Coercion') and $next->is_parameterized)
  		{
  			push @pairs => (
  				@{ $next->_reparameterize($self)->type_coercion_map }
  			);
  		}
  		elsif (blessed($next) and $next->can('type_coercion_map'))
  		{
  			push @pairs => (
  				@{ $next->type_coercion_map },
  			);
  		}
  		elsif (ref($next) eq q(ARRAY))
  		{
  			unshift @_, @$next;
  		}
  		else
  		{
  			push @pairs => (
  				Types::TypeTiny::to_TypeTiny($next),
  				shift,
  			);
  		}
  	}

  	return @pairs;
  }

  sub plus_coercions
  {
  	my $self = shift;
  	my $new = $self->_clone;
  	$new->coercion->add_type_coercions(
  		$self->_process_coercion_list(@_),
  		@{$self->coercion->type_coercion_map},
  	);
  	$new->coercion->freeze;
  	return $new;
  }

  sub plus_fallback_coercions
  {
  	my $self = shift;

  	my $new = $self->_clone;
  	$new->coercion->add_type_coercions(
  		@{$self->coercion->type_coercion_map},
  		$self->_process_coercion_list(@_),
  	);
  	$new->coercion->freeze;
  	return $new;
  }

  sub minus_coercions
  {
  	my $self = shift;

  	my $new = $self->_clone;
  	my @not = grep Types::TypeTiny::TypeTiny->check($_), $self->_process_coercion_list($new, @_);

  	my @keep;
  	my $c = $self->coercion->type_coercion_map;
  	for (my $i = 0; $i <= $#$c; $i += 2)
  	{
  		my $keep_this = 1;
  		NOT: for my $n (@not)
  		{
  			if ($c->[$i] == $n)
  			{
  				$keep_this = 0;
  				last NOT;
  			}
  		}

  		push @keep, $c->[$i], $c->[$i+1] if $keep_this;
  	}

  	$new->coercion->add_type_coercions(@keep);
  	$new->coercion->freeze;
  	return $new;
  }

  sub no_coercions
  {
  	my $new = shift->_clone;
  	$new->coercion->freeze;
  	$new;
  }

  sub coercibles
  {
  	my $self = shift;
  	$self->has_coercion ? $self->coercion->_source_type_union : $self;
  }

  sub isa
  {
  	my $self = shift;

  	if ($INC{"Moose.pm"} and ref($self) and $_[0] =~ /^(?:Class::MOP|MooseX?::Meta)::(.+)$/)
  	{
  		my $meta = $1;

  		return !!1                             if $meta eq 'TypeConstraint';
  		return $self->is_parameterized         if $meta eq 'TypeConstraint::Parameterized';
  		return $self->is_parameterizable       if $meta eq 'TypeConstraint::Parameterizable';
  		return $self->isa('Type::Tiny::Union') if $meta eq 'TypeConstraint::Union';

  		my $inflate = $self->moose_type;
  		return $inflate->isa(@_);
  	}

  	if ($INC{"Mouse.pm"} and ref($self) and $_[0] eq 'Mouse::Meta::TypeConstraint')
  	{
  		return !!1;
  	}

  	$self->SUPER::isa(@_);
  }

  sub _build_my_methods
  {
  	return {};
  }

  sub _lookup_my_method
  {
  	my $self = shift;
  	my ($name) = @_;

  	if ($self->my_methods->{$name})
  	{
  		return $self->my_methods->{$name};
  	}

  	if ($self->has_parent)
  	{
  		return $self->parent->_lookup_my_method(@_);
  	}

  	return;
  }

  sub can
  {
  	my $self = shift;

  	return !!0 if $_[0] eq 'type_parameter' && blessed($_[0]) && $_[0]->has_parameters;

  	my $can = $self->SUPER::can(@_);
  	return $can if $can;

  	if (ref($self))
  	{
  		if ($INC{"Moose.pm"})
  		{
  			my $method = $self->moose_type->can(@_);
  			return sub { shift->moose_type->$method(@_) } if $method;
  		}
  		if ($_[0] =~ /\Amy_(.+)\z/)
  		{
  			my $method = $self->_lookup_my_method($1);
  			return $method if $method;
  		}
  	}

  	return;
  }

  sub AUTOLOAD
  {
  	my $self = shift;
  	my ($m) = (our $AUTOLOAD =~ /::(\w+)$/);
  	return if $m eq 'DESTROY';

  	if (ref($self))
  	{
  		if ($INC{"Moose.pm"})
  		{
  			my $method = $self->moose_type->can($m);
  			return $self->moose_type->$method(@_) if $method;
  		}
  		if ($m =~ /\Amy_(.+)\z/)
  		{
  			my $method = $self->_lookup_my_method($1);
  			return $self->$method(@_) if $method;
  		}
  	}

  	_croak q[Can't locate object method "%s" via package "%s"], $m, ref($self)||$self;
  }

  sub DOES
  {
  	my $self = shift;

  	return !!1 if  ref($self) && $_[0] =~ m{^ Type::API::Constraint (?: ::Coercible | ::Inlinable )? $}x;
  	return !!1 if !ref($self) && $_[0] eq 'Type::API::Constraint::Constructor';

  	"UNIVERSAL"->can("DOES") ? $self->SUPER::DOES(@_) : $self->isa(@_);
  }

  sub _has_xsub
  {
  	require B;
  	!!B::svref_2object( shift->compiled_check )->XSUB;
  }

  sub of                         { shift->parameterize(@_) }
  sub where                      { shift->create_child_type(constraint => @_) }

  # fill out Moose-compatible API
  sub inline_environment         { +{} }
  sub _inline_check              { shift->inline_check(@_) }
  sub _compiled_type_constraint  { shift->compiled_check(@_) }
  sub meta                       { _croak("Not really a Moose::Meta::TypeConstraint. Sorry!") }
  sub compile_type_constraint    { shift->compiled_check }
  sub _actually_compile_type_constraint   { shift->_build_compiled_check }
  sub hand_optimized_type_constraint      { shift->{hand_optimized_type_constraint} }
  sub has_hand_optimized_type_constraint  { exists(shift->{hand_optimized_type_constraint}) }
  sub type_parameter             { (shift->parameters || [])->[0] }

  # some stuff for Mouse-compatible API
  sub __is_parameterized         { shift->is_parameterized(@_) }
  sub _add_type_coercions        { shift->coercion->add_type_coercions(@_) };
  sub _as_string                 { shift->qualified_name(@_) }
  sub _compiled_type_coercion    { shift->coercion->compiled_coercion(@_) };
  sub _identity                  { refaddr(shift) };
  sub _unite                     { require Type::Tiny::Union; "Type::Tiny::Union"->new(type_constraints => \@_) };

  # Hooks for Type::Tie
  sub TIESCALAR  { require Type::Tie; unshift @_, 'Type::Tie::SCALAR'; goto \&Type::Tie::SCALAR::TIESCALAR };
  sub TIEARRAY   { require Type::Tie; unshift @_, 'Type::Tie::ARRAY';  goto \&Type::Tie::ARRAY::TIEARRAY };
  sub TIEHASH    { require Type::Tie; unshift @_, 'Type::Tie::HASH';   goto \&Type::Tie::HASH::TIEHASH };

  1;

  __END__

  =pod

  =encoding utf-8

  =for stopwords Moo(se)-compatible MooseX MouseX MooX Moose-compat invocant

  =head1 NAME

  Type::Tiny - tiny, yet Moo(se)-compatible type constraint

  =head1 SYNOPSIS

     use Scalar::Util qw(looks_like_number);
     use Type::Tiny;

     my $NUM = "Type::Tiny"->new(
        name       => "Number",
        constraint => sub { looks_like_number($_) },
        message    => sub { "$_ ain't a number" },
     );

     package Ermintrude {
        use Moo;
        has favourite_number => (is => "ro", isa => $NUM);
     }

     package Bullwinkle {
        use Moose;
        has favourite_number => (is => "ro", isa => $NUM);
     }

     package Maisy {
        use Mouse;
        has favourite_number => (is => "ro", isa => $NUM);
     }

  =head1 STATUS

  This module is covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  L<Type::Tiny> is a tiny class for creating Moose-like type constraint
  objects which are compatible with Moo, Moose and Mouse.

  Maybe now we won't need to have separate MooseX, MouseX and MooX versions
  of everything? We can but hope...

  This documents the internals of L<Type::Tiny>. L<Type::Tiny::Manual> is
  a better starting place if you're new.

  =head2 Constructor

  =over

  =item C<< new(%attributes) >>

  Moose-style constructor function.

  =back

  =head2 Attributes

  Attributes are named values that may be passed to the constructor. For
  each attribute, there is a corresponding reader method. For example:

     my $type = Type::Tiny->new( name => "Foo" );
     print $type->name, "\n";   # says "Foo"

  =head3 Important attributes

  These are the attributes you are likely to be most interested in
  providing when creating your own type constraints, and most interested
  in reading when dealing with type constraint objects.

  =over

  =item C<< constraint >>

  Coderef to validate a value (C<< $_ >>) against the type constraint. The
  coderef will not be called unless the value is known to pass any parent
  type constraint (see C<parent> below).

  Defaults to C<< sub { 1 } >> - i.e. a coderef that passes all values.

  =item C<< parent >>

  Optional attribute; parent type constraint. For example, an "Integer"
  type constraint might have a parent "Number".

  If provided, must be a Type::Tiny object.

  =item C<< inlined >>

  A coderef which returns a string of Perl code suitable for inlining this
  type. Optional.

  If C<constraint> (above) is a coderef generated via L<Sub::Quote>, then
  Type::Tiny I<may> be able to automatically generate C<inlined> for you.

  =item C<< name >>

  The name of the type constraint. These need to conform to certain naming
  rules (they must begin with an uppercase letter and continue using only
  letters, digits 0-9 and underscores).

  Optional; if not supplied will be an anonymous type constraint.

  =item C<< display_name >>

  A name to display for the type constraint when stringified. These don't
  have to conform to any naming rules. Optional; a default name will be
  calculated from the C<name>.

  =item C<< library >>

  The package name of the type library this type is associated with.
  Optional. Informational only: setting this attribute does not install
  the type into the package.

  =item C<< message >>

  Coderef that returns an error message when C<< $_ >> does not validate
  against the type constraint. Optional (there's a vaguely sensible default.)

  =item C<< coercion >>

  A L<Type::Coercion> object associated with this type.

  Generally speaking this attribute should not be passed to the constructor;
  you should rely on the default lazily-built coercion object.

  You may pass C<< coercion => 1 >> to the constructor to inherit coercions
  from the constraint's parent. (This requires the parent constraint to have
  a coercion.)

  =item C<< my_methods >>

  Experimenal hashref of additional methods that can be called on the type
  constraint object.

  =back

  =head3 Attributes related to parameterizable and parameterized types

  The following additional attributes are used for parameterizable (e.g.
  C<ArrayRef>) and parameterized (e.g. C<< ArrayRef[Int] >>) type
  constraints. Unlike Moose, these aren't handled by separate subclasses.

  =over

  =item C<< constraint_generator >>

  Coderef that generates a new constraint coderef based on parameters.
  Alternatively, the constraint generator can return a fully-formed
  Type::Tiny object, in which case the C<name_generator>, C<inline_generator>,
  and C<coercion_generator> attributes documented below are ignored.

  Optional; providing a generator makes this type into a parameterizable
  type constraint.

  =item C<< name_generator >>

  A coderef which generates a new display_name based on parameters.
  Optional; the default is reasonable.

  =item C<< inline_generator >>

  A coderef which generates a new inlining coderef based on parameters.

  =item C<< coercion_generator >>

  A coderef which generates a new L<Type::Coercion> object based on parameters.

  =item C<< deep_explanation >>

  This API is not finalized. Coderef used by L<Error::TypeTiny::Assertion> to
  peek inside parameterized types and figure out why a value doesn't pass the
  constraint.

  =item C<< parameters >>

  In parameterized types, returns an arrayref of the parameters.

  =back

  =head3 Lazy generated attributes

  The following attributes should not be usually passed to the constructor;
  unless you're doing something especially unusual, you should rely on the
  default lazily-built return values.

  =over

  =item C<< compiled_check >>

  Coderef to validate a value (C<< $_[0] >>) against the type constraint.
  This coderef is expected to also handle all validation for the parent
  type constraints.

  =item C<< complementary_type >>

  A complementary type for this type. For example, the complementary type
  for an integer type would be all things that are not integers, including
  floating point numbers, but also alphabetic strings, arrayrefs, filehandles,
  etc.

  =item C<< moose_type >>, C<< mouse_type >>

  Objects equivalent to this type constraint, but as a
  L<Moose::Meta::TypeConstraint> or L<Mouse::Meta::TypeConstraint>.

  It should rarely be necessary to obtain a L<Moose::Meta::TypeConstraint>
  object from L<Type::Tiny> because the L<Type::Tiny> object itself should
  be usable pretty much anywhere a L<Moose::Meta::TypeConstraint> is expected.

  =back

  =head2 Methods

  =head3 Predicate methods

  These methods return booleans indicating information about the type
  constraint. They are each tightly associated with a particular attribute.
  (See L</"Attributes">.)

  =over

  =item C<has_parent>, C<has_library>, C<has_inlined>, C<has_constraint_generator>, C<has_inline_generator>, C<has_coercion_generator>, C<has_parameters>, C<has_message>, C<has_deep_explanation>

  Simple Moose-style predicate methods indicating the presence or
  absence of an attribute.

  =item C<has_coercion>

  Predicate method with a little extra DWIM. Returns false if the coercion is
  a no-op.

  =item C<< is_anon >>

  Returns true iff the type constraint does not have a C<name>.

  =item C<< is_parameterized >>, C<< is_parameterizable >>

  Indicates whether a type has been parameterized (e.g. C<< ArrayRef[Int] >>)
  or could potentially be (e.g. C<< ArrayRef >>).

  =back

  =head3 Validation and coercion

  The following methods are used for coercing and validating values
  against a type constraint:

  =over

  =item C<< check($value) >>

  Returns true iff the value passes the type constraint.

  =item C<< validate($value) >>

  Returns the error message for the value; returns an explicit undef if the
  value passes the type constraint.

  =item C<< assert_valid($value) >>

  Like C<< check($value) >> but dies if the value does not pass the type
  constraint.

  Yes, that's three very similar methods. Blame L<Moose::Meta::TypeConstraint>
  whose API I'm attempting to emulate. :-)

  =item C<< assert_return($value) >>

  Like C<< assert_valid($value) >> but returns the value if it passes the type
  constraint.

  This seems a more useful behaviour than C<< assert_valid($value) >>. I would
  have just changed C<< assert_valid($value) >> to do this, except that there
  are edge cases where it could break Moose compatibility.

  =item C<< get_message($value) >>

  Returns the error message for the value; even if the value passes the type
  constraint.

  =item C<< validate_explain($value, $varname) >>

  Like C<validate> but instead of a string error message, returns an arrayref
  of strings explaining the reasoning why the value does not meet the type
  constraint, examining parent types, etc.

  The C<< $varname >> is an optional string like C<< '$foo' >> indicating the
  name of the variable being checked.

  =item C<< coerce($value) >>

  Attempt to coerce C<< $value >> to this type.

  =item C<< assert_coerce($value) >>

  Attempt to coerce C<< $value >> to this type. Throws an exception if this is
  not possible.

  =back

  =head3 Child type constraint creation and parameterization

  These methods generate new type constraint objects that inherit from the
  constraint they are called upon:

  =over

  =item C<< create_child_type(%attributes) >>

  Construct a new Type::Tiny object with this object as its parent.

  =item C<< where($coderef) >>

  Shortcut for creating an anonymous child type constraint. Use it like
  C<< HashRef->where(sub { exists($_->{name}) }) >>. That said, you can
  get a similar result using overloaded C<< & >>:

     HashRef & sub { exists($_->{name}) }

  =item C<< child_type_class >>

  The class that create_child_type will construct by default.

  =item C<< parameterize(@parameters) >>

  Creates a new parameterized type; throws an exception if called on a
  non-parameterizable type.

  =item C<< of(@parameters) >>

  A cute alias for C<parameterize>. Use it like C<< ArrayRef->of(Int) >>.

  =item C<< plus_coercions($type1, $code1, ...) >>

  Shorthand for creating a new child type constraint with the same coercions
  as this one, but then adding some extra coercions (at a higher priority than
  the existing ones).

  =item C<< plus_fallback_coercions($type1, $code1, ...) >>

  Like C<plus_coercions>, but added at a lower priority.

  =item C<< minus_coercions($type1, ...) >>

  Shorthand for creating a new child type constraint with fewer type coercions.

  =item C<< no_coercions >>

  Shorthand for creating a new child type constraint with no coercions at all.

  =back

  =head3 Type relationship introspection methods

  These methods allow you to determine a type constraint's relationship to
  other type constraints in an organised hierarchy:

  =over

  =item C<< equals($other) >>, C<< is_subtype_of($other) >>, C<< is_supertype_of($other) >>, C<< is_a_type_of($other) >>

  Compare two types. See L<Moose::Meta::TypeConstraint> for what these all mean.
  (OK, Moose doesn't define C<is_supertype_of>, but you get the idea, right?)

  Note that these have a slightly DWIM side to them. If you create two
  L<Type::Tiny::Class> objects which test the same class, they're considered
  equal. And:

     my $subtype_of_Num = Types::Standard::Num->create_child_type;
     my $subtype_of_Int = Types::Standard::Int->create_child_type;
     $subtype_of_Int->is_subtype_of( $subtype_of_Num );  # true

  =item C<< strictly_equals($other) >>, C<< is_strictly_subtype_of($other) >>, C<< is_strictly_supertype_of($other) >>, C<< is_strictly_a_type_of($other) >>

  Stricter versions of the type comparison functions. These only care about
  explicit inheritance via C<parent>.

     my $subtype_of_Num = Types::Standard::Num->create_child_type;
     my $subtype_of_Int = Types::Standard::Int->create_child_type;
     $subtype_of_Int->is_strictly_subtype_of( $subtype_of_Num );  # false

  =item C<< parents >>

  Returns a list of all this type constraint's ancestor constraints. For
  example, if called on the C<Str> type constraint would return the list
  C<< (Value, Defined, Item, Any) >>.

  B<< Due to a historical misunderstanding, this differs from the Moose
  implementation of the C<parents> method. In Moose, C<parents> only returns the
  immediate parent type constraints, and because type constraints only have
  one immediate parent, this is effectively an alias for C<parent>. The
  extension module L<MooseX::Meta::TypeConstraint::Intersection> is the only
  place where multiple type constraints are returned; and they are returned
  as an arrayref in violation of the base class' documentation. I'm keeping
  my behaviour as it seems more useful. >>

  =item C<< find_parent($coderef) >>

  Loops through the parent type constraints I<< including the invocant
  itself >> and returns the nearest ancestor type constraint where the
  coderef evaluates to true. Within the coderef the ancestor currently
  being checked is C<< $_ >>. Returns undef if there is no match.

  In list context also returns the number of type constraints which had
  been looped through before the matching constraint was found.

  =item C<< coercibles >>

  Return a type constraint which is the union of type constraints that can be
  coerced to this one (including this one). If this type constraint has no
  coercions, returns itself.

  =item C<< type_parameter >>

  In parameterized type constraints, returns the first item on the list of
  parameters; otherwise returns undef. For example:

     ( ArrayRef[Int] )->type_parameter;    # returns Int
     ( ArrayRef[Int] )->parent;            # returns ArrayRef

  Note that parameterizable type constraints can perfectly legitimately take
  multiple parameters (several off the parameterizable type constraints in
  L<Types::Standard> do). This method only returns the first such parameter.
  L</"Attributes related to parameterizable and parameterized types">
  documents the C<parameters> attribute, which returns an arrayref of all
  the parameters.

  =back

  =head3 Inlining methods

  =for stopwords uated

  The following methods are used to generate strings of Perl code which
  may be pasted into stringy C<eval>uated subs to perform type checks:

  =over

  =item C<< can_be_inlined >>

  Returns boolean indicating if this type can be inlined.

  =item C<< inline_check($varname) >>

  Creates a type constraint check for a particular variable as a string of
  Perl code. For example:

     print( Types::Standard::Num->inline_check('$foo') );

  prints the following output:

     (!ref($foo) && Scalar::Util::looks_like_number($foo))

  For Moose-compat, there is an alias C<< _inline_check >> for this method.

  =item C<< inline_assert($varname) >>

  Much like C<inline_check> but outputs a statement of the form:

     die ... unless ...;

  Note that if this type has a custom error message, the inlined code will
  I<ignore> this custom message!!

  =back

  =head3 Other methods

  =over

  =item C<< qualified_name >>

  For non-anonymous type constraints that have a library, returns a qualified
  C<< "MyLib::MyType" >> sort of name. Otherwise, returns the same as C<name>.

  =item C<< isa($class) >>, C<< can($method) >>, C<< AUTOLOAD(@args) >>

  If Moose is loaded, then the combination of these methods is used to mock
  a Moose::Meta::TypeConstraint.

  If Mouse is loaded, then C<isa> mocks Mouse::Meta::TypeConstraint.

  =item C<< DOES($role) >>

  Overridden to advertise support for various roles.

  See also L<Type::API::Constraint>, etc.

  =item C<< TIESCALAR >>, C<< TIEARRAY >>, C<< TIEHASH >>

  These are provided as hooks that wrap L<Type::Tie>. (Type::Tie is distributed
  separately, and can be used with non-Type::Tiny type constraints too.) They
  allow the following to work:

     use Types::Standard qw(Int);
     tie my @list, Int;
     push @list, 123, 456;   # ok
     push @list, "Hello";    # dies

  =back

  The following methods exist for Moose/Mouse compatibility, but do not do
  anything useful.

  =over

  =item C<< compile_type_constraint >>

  =item C<< hand_optimized_type_constraint >>

  =item C<< has_hand_optimized_type_constraint >>

  =item C<< inline_environment >>

  =item C<< meta >>

  =back

  =head2 Overloading

  =over

  =item *

  Stringification is overloaded to return the qualified name.

  =item *

  Boolification is overloaded to always return true.

  =item *

  Coderefification is overloaded to call C<assert_return>.

  =item *

  On Perl 5.10.1 and above, smart match is overloaded to call C<check>.

  =item *

  The C<< == >> operator is overloaded to call C<equals>.

  =item *

  The C<< < >> and C<< > >> operators are overloaded to call C<is_subtype_of>
  and C<is_supertype_of>.

  =item *

  The C<< ~ >> operator is overloaded to call C<complementary_type>.

  =item *

  The C<< | >> operator is overloaded to build a union of two type constraints.
  See L<Type::Tiny::Union>.

  =item *

  The C<< & >> operator is overloaded to build the intersection of two type
  constraints. See L<Type::Tiny::Intersection>.

  =back

  Previous versions of Type::Tiny would overload the C<< + >> operator to
  call C<plus_coercions> or C<plus_fallback_coercions> as appropriate.
  Support for this was dropped after 0.040.

  =head2 Constants

  =over

  =item C<< Type::Tiny::SUPPORT_SMARTMATCH >>

  Indicates whether the smart match overload is supported on your
  version of Perl.

  =back

  =head2 Package Variables

  =over

  =item C<< $Type::Tiny::DD >>

  This undef by default but may be set to a coderef that Type::Tiny
  and related modules will use to dump data structures in things like
  error messages.

  Otherwise Type::Tiny uses it's own routine to dump data structures.
  C<< $DD >> may then be set to a number to limit the lengths of the
  dumps. (Default limit is 72.)

  This is a package variable (rather than get/set class methods) to allow
  for easy localization.

  =back

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SUPPORT

  B<< IRC: >> support is available through in the I<< #moops >> channel
  on L<irc.perl.org|http://www.irc.perl.org/channels.html>.

  =head1 SEE ALSO

  L<Type::Tiny::Manual>, L<Type::API>.

  L<Type::Library>, L<Type::Utils>, L<Types::Standard>, L<Type::Coercion>.

  L<Type::Tiny::Class>, L<Type::Tiny::Role>, L<Type::Tiny::Duck>,
  L<Type::Tiny::Enum>, L<Type::Tiny::Union>, L<Type::Tiny::Intersection>.

  L<Moose::Meta::TypeConstraint>,
  L<Mouse::Meta::TypeConstraint>.

  L<Type::Params>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 THANKS

  Thanks to Matt S Trout for advice on L<Moo> integration.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

TYPE_TINY

$fatpacked{"Type/Tiny/Class.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TYPE_TINY_CLASS';
  package Type::Tiny::Class;

  use 5.006001;
  use strict;
  use warnings;

  BEGIN {
  	if ($] < 5.008) { require Devel::TypeTiny::Perl56Compat };
  }

  BEGIN {
  	$Type::Tiny::Class::AUTHORITY = 'cpan:TOBYINK';
  	$Type::Tiny::Class::VERSION   = '1.000005';
  }

  use Scalar::Util qw< blessed >;

  sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }

  use Type::Tiny ();
  our @ISA = 'Type::Tiny';

  sub new {
  	my $proto = shift;
  	return $proto->class->new(@_) if blessed $proto; # DWIM

  	my %opts = (@_==1) ? %{$_[0]} : @_;
  	_croak "Class type constraints cannot have a parent constraint passed to the constructor" if exists $opts{parent};
  	_croak "Class type constraints cannot have a constraint coderef passed to the constructor" if exists $opts{constraint};
  	_croak "Class type constraints cannot have a inlining coderef passed to the constructor" if exists $opts{inlined};
  	_croak "Need to supply class name" unless exists $opts{class};

  	if (Type::Tiny::_USE_XS)
  	{
  		my $xsub = Type::Tiny::XS::get_coderef_for("InstanceOf[".$opts{class}."]");
  		$opts{compiled_type_constraint} = $xsub if $xsub;
  	}
  	elsif (Type::Tiny::_USE_MOUSE)
  	{
  		require Mouse::Util::TypeConstraints;
  		my $maker = "Mouse::Util::TypeConstraints"->can("generate_isa_predicate_for");
  		$opts{compiled_type_constraint} = $maker->($opts{class}) if $maker;
  	}

  	return $proto->SUPER::new(%opts);
  }

  sub class       { $_[0]{class} }
  sub inlined     { $_[0]{inlined} ||= $_[0]->_build_inlined }

  sub has_inlined { !!1 }

  sub _build_constraint
  {
  	my $self  = shift;
  	my $class = $self->class;
  	return sub { blessed($_) and $_->isa($class) };
  }

  sub _build_inlined
  {
  	my $self  = shift;
  	my $class = $self->class;

  	if (Type::Tiny::_USE_XS)
  	{
  		my $xsub = Type::Tiny::XS::get_subname_for("InstanceOf[$class]");
  		return sub { my $var = $_[1]; "$xsub\($var\)" } if $xsub;
  	}

  	sub {
  		my $var = $_[1];
  		qq{Scalar::Util::blessed($var) and $var->isa(q[$class])};
  	};
  }

  sub _build_default_message
  {
  	no warnings 'uninitialized';
  	my $self = shift;
  	my $c = $self->class;
  	return sub { sprintf '%s did not pass type constraint (not isa %s)', Type::Tiny::_dd($_[0]), $c } if $self->is_anon;
  	my $name = "$self";
  	return sub { sprintf '%s did not pass type constraint "%s" (not isa %s)', Type::Tiny::_dd($_[0]), $name, $c };
  }

  sub _instantiate_moose_type
  {
  	my $self = shift;
  	my %opts = @_;
  	delete $opts{parent};
  	delete $opts{constraint};
  	delete $opts{inlined};
  	require Moose::Meta::TypeConstraint::Class;
  	return "Moose::Meta::TypeConstraint::Class"->new(%opts, class => $self->class);
  }

  sub plus_constructors
  {
  	my $self = shift;

  	unless (@_)
  	{
  		require Types::Standard;
  		push @_, Types::Standard::HashRef(), "new";
  	}

  	require B;
  	require Types::TypeTiny;

  	my $class = B::perlstring($self->class);

  	my @r;
  	while (@_)
  	{
  		my $source = shift;
  		Types::TypeTiny::TypeTiny->check($source)
  			or _croak "Expected type constraint; got $source";

  		my $constructor = shift;
  		Types::TypeTiny::StringLike->check($constructor)
  			or _croak "Expected string; got $constructor";

  		push @r, $source, sprintf('%s->%s($_)', $class, $constructor);
  	}

  	return $self->plus_coercions(\@r);
  }

  sub has_parent
  {
  	!!1;
  }

  sub parent
  {
  	$_[0]{parent} ||= $_[0]->_build_parent;
  }

  sub _build_parent
  {
  	my $self  = shift;
  	my $class = $self->class;

  	# Some classes (I'm looking at you, Math::BigFloat) include a class in
  	# their @ISA to inherit methods, but then override isa() to return false,
  	# so that they don't appear to be a subclass.
  	#
  	# In these cases, we don't want to list the parent class as a parent
  	# type constraint.
  	#
  	my @isa = grep $class->isa($_), do { no strict "refs"; no warnings; @{"$class\::ISA"} };

  	if (@isa == 0)
  	{
  		require Types::Standard;
  		return Types::Standard::Object();
  	}

  	if (@isa == 1)
  	{
  		return ref($self)->new(class => $isa[0])
  	}

  	require Type::Tiny::Intersection;
  	"Type::Tiny::Intersection"->new(
  		type_constraints => [ map ref($self)->new(class => $_), @isa ],
  	);
  }

  *__get_linear_isa_dfs = eval { require mro }
  	? \&mro::get_linear_isa
  	: sub {
  		no strict 'refs';

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

  		foreach my $parent (@{"$classname\::ISA"})
  		{
  			my $plin = __get_linear_isa_dfs($parent);
  			foreach (@$plin) {
  				next if exists $stored{$_};
  				push(@lin, $_);
  				$stored{$_} = 1;
  			}
  		}

  		return \@lin;
  	};

  sub validate_explain
  {
  	my $self = shift;
  	my ($value, $varname) = @_;
  	$varname = '$_' unless defined $varname;

  	return undef if $self->check($value);
  	return ["Not a blessed reference"] unless blessed($value);

  	my @isa = @{ __get_linear_isa_dfs(ref $value) };

  	my $display_var = $varname eq q{$_} ? '' : sprintf(' (in %s)', $varname);

  	require Type::Utils;
  	return [
  		sprintf('"%s" requires that the reference isa %s', $self, $self->class),
  		sprintf('The reference%s isa %s', $display_var, Type::Utils::english_list(@isa)),
  	];
  }

  1;

  __END__

  =pod

  =encoding utf-8

  =head1 NAME

  Type::Tiny::Class - type constraints based on the "isa" method

  =head1 STATUS

  This module is covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  Type constraints of the general form C<< { $_->isa("Some::Class") } >>.

  This package inherits from L<Type::Tiny>; see that for most documentation.
  Major differences are listed below:

  =head2 Constructor

  =over

  =item C<new>

  When the constructor is called on an I<instance> of Type::Tiny::Class, it
  passes the call through to the constructor of the class for the constraint.
  So for example:

     my $type = Type::Tiny::Class->new(class => "Foo::Bar");
     my $obj  = $type->new(hello => "World");
     say ref($obj);   # prints "Foo::Bar"

  This little bit of DWIM was borrowed from L<MooseX::Types::TypeDecorator>,
  but Type::Tiny doesn't take the idea quite as far.

  =back

  =head2 Attributes

  =over

  =item C<class>

  The class for the constraint.

  =item C<constraint>

  Unlike Type::Tiny, you I<cannot> pass a constraint coderef to the constructor.
  Instead rely on the default.

  =item C<inlined>

  Unlike Type::Tiny, you I<cannot> pass an inlining coderef to the constructor.
  Instead rely on the default.

  =item C<parent>

  Parent is automatically calculated, and cannot be passed to the constructor.

  =back

  =head2 Methods

  =over

  =item C<< plus_constructors($source, $method_name) >>

  Much like C<plus_coercions> but adds coercions that go via a constructor.
  (In fact, this is implemented as a wrapper for C<plus_coercions>.)

  Example:

     package MyApp::Minion;

     use Moose; extends "MyApp::Person";

     use Types::Standard qw( HashRef Str );
     use Type::Utils qw( class_type );

     my $Person = class_type({ class => "MyApp::Person" });

     has boss => (
        is     => "ro",
        isa    => $Person->plus_constructors(
           HashRef,     "new",
           Str,         "_new_from_name",
        ),
        coerce => 1,
     );

     package main;

     MyApp::Minion->new(
        ...,
        boss => "Bob",  ## via MyApp::Person->_new_from_name
     );

     MyApp::Minion->new(
        ...,
        boss => { name => "Bob" },  ## via MyApp::Person->new
     );

  Because coercing C<HashRef> via constructor is a common desire, if
  you call C<plus_constructors> with no arguments at all, this is the
  default.

     $classtype->plus_constructors(Types::Standard::HashRef, "new")
     $classtype->plus_constructors()  ## identical to above

  This is handy for Moose/Mouse/Moo-based classes.

  =back

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Type::Tiny::Manual>.

  L<Type::Tiny>.

  L<Moose::Meta::TypeConstraint::Class>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

TYPE_TINY_CLASS

$fatpacked{"Type/Tiny/Duck.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TYPE_TINY_DUCK';
  package Type::Tiny::Duck;

  use 5.006001;
  use strict;
  use warnings;

  BEGIN {
  	$Type::Tiny::Duck::AUTHORITY = 'cpan:TOBYINK';
  	$Type::Tiny::Duck::VERSION   = '1.000005';
  }

  use Scalar::Util qw< blessed >;

  sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }

  use Type::Tiny ();
  our @ISA = 'Type::Tiny';

  sub new {
  	my $proto = shift;

  	my %opts = (@_==1) ? %{$_[0]} : @_;
  	_croak "Duck type constraints cannot have a parent constraint passed to the constructor" if exists $opts{parent};
  	_croak "Duck type constraints cannot have a constraint coderef passed to the constructor" if exists $opts{constraint};
  	_croak "Duck type constraints cannot have a inlining coderef passed to the constructor" if exists $opts{inlined};
  	_croak "Need to supply list of methods" unless exists $opts{methods};

  	$opts{methods} = [$opts{methods}] unless ref $opts{methods};

  	if (Type::Tiny::_USE_XS)
  	{
  		my $methods = join ",", sort(@{$opts{methods}});
  		my $xsub    = Type::Tiny::XS::get_coderef_for("HasMethods[$methods]");
  		$opts{compiled_type_constraint} = $xsub if $xsub;
  	}
  	elsif (Type::Tiny::_USE_MOUSE)
  	{
  		require Mouse::Util::TypeConstraints;
  		my $maker = "Mouse::Util::TypeConstraints"->can("generate_can_predicate_for");
  		$opts{compiled_type_constraint} = $maker->($opts{methods}) if $maker;
  	}

  	return $proto->SUPER::new(%opts);
  }

  sub methods     { $_[0]{methods} }
  sub inlined     { $_[0]{inlined} ||= $_[0]->_build_inlined }

  sub has_inlined { !!1 }

  sub _build_constraint
  {
  	my $self    = shift;
  	my @methods = @{$self->methods};
  	return sub { blessed($_[0]) and not grep(!$_[0]->can($_), @methods) };
  }

  sub _build_inlined
  {
  	my $self = shift;
  	my @methods = @{$self->methods};

  	if (Type::Tiny::_USE_XS)
  	{
  		my $methods = join ",", sort(@{$self->methods});
  		my $xsub    = Type::Tiny::XS::get_subname_for("HasMethods[$methods]");
  		return sub { my $var = $_[1]; "$xsub\($var\)" } if $xsub;
  	}

  	sub {
  		my $var = $_[1];
  		local $" = q{ };
  		# If $var is $_ or $_->{foo} or $foo{$_} or somesuch, then we
  		# can't use it within the grep expression, so we need to save
  		# it into a temporary variable ($tmp).
  		($var =~ /\$_/)
  			? qq{ Scalar::Util::blessed($var) and not do { my \$tmp = $var; grep(!\$tmp->can(\$_), qw/@methods/) } }
  			: qq{ Scalar::Util::blessed($var) and not grep(!$var->can(\$_), qw/@methods/) };
  	};
  }

  sub _instantiate_moose_type
  {
  	my $self = shift;
  	my %opts = @_;
  	delete $opts{parent};
  	delete $opts{constraint};
  	delete $opts{inlined};

  	require Moose::Meta::TypeConstraint::DuckType;
  	return "Moose::Meta::TypeConstraint::DuckType"->new(%opts, methods => $self->methods);
  }

  sub has_parent
  {
  	!!1;
  }

  sub parent
  {
  	require Types::Standard;
  	Types::Standard::Object();
  }

  sub validate_explain
  {
  	my $self = shift;
  	my ($value, $varname) = @_;
  	$varname = '$_' unless defined $varname;

  	return undef if $self->check($value);
  	return ["Not a blessed reference"] unless blessed($value);

  	require Type::Utils;
  	return [
  		sprintf(
  			'"%s" requires that the reference can %s',
  			$self,
  			Type::Utils::english_list(map qq["$_"], @{$self->methods}),
  		),
  		map  sprintf('The reference cannot "%s"', $_),
  		grep !$value->can($_),
  		@{$self->methods}
  	];
  }

  1;

  __END__

  =pod

  =encoding utf-8

  =head1 NAME

  Type::Tiny::Duck - type constraints based on the "can" method

  =head1 STATUS

  This module is covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  Type constraints of the general form C<< { $_->can("method") } >>.

  This package inherits from L<Type::Tiny>; see that for most documentation.
  Major differences are listed below:

  =head2 Attributes

  =over

  =item C<methods>

  An arrayref of method names.

  =item C<constraint>

  Unlike Type::Tiny, you I<cannot> pass a constraint coderef to the constructor.
  Instead rely on the default.

  =item C<inlined>

  Unlike Type::Tiny, you I<cannot> pass an inlining coderef to the constructor.
  Instead rely on the default.

  =item C<parent>

  Parent is always Types::Standard::Object, and cannot be passed to the
  constructor.

  =back

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Type::Tiny::Manual>.

  L<Type::Tiny>.

  L<Moose::Meta::TypeConstraint::DuckType>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

TYPE_TINY_DUCK

$fatpacked{"Type/Tiny/Enum.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TYPE_TINY_ENUM';
  package Type::Tiny::Enum;

  use 5.006001;
  use strict;
  use warnings;

  BEGIN {
  	$Type::Tiny::Enum::AUTHORITY = 'cpan:TOBYINK';
  	$Type::Tiny::Enum::VERSION   = '1.000005';
  }

  sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }

  use overload q[@{}] => 'values';

  use Type::Tiny ();
  our @ISA = 'Type::Tiny';

  sub new
  {
  	my $proto = shift;

  	my %opts = (@_==1) ? %{$_[0]} : @_;
  	_croak "Enum type constraints cannot have a parent constraint passed to the constructor" if exists $opts{parent};
  	_croak "Enum type constraints cannot have a constraint coderef passed to the constructor" if exists $opts{constraint};
  	_croak "Enum type constraints cannot have a inlining coderef passed to the constructor" if exists $opts{inlined};
  	_croak "Need to supply list of values" unless exists $opts{values};

  	my %tmp =
  		map { $_ => 1 }
  		@{ ref $opts{values} eq "ARRAY" ? $opts{values} : [$opts{values}] };
  	$opts{values} = [sort keys %tmp];

  	if (Type::Tiny::_USE_XS and not grep /[^-\w]/, @{$opts{values}})
  	{
  		my $enum = join ",", @{$opts{values}};
  		my $xsub = Type::Tiny::XS::get_coderef_for("Enum[$enum]");
  		$opts{compiled_type_constraint} = $xsub if $xsub;
  	}

  	return $proto->SUPER::new(%opts);
  }

  sub values      { $_[0]{values} }
  sub constraint  { $_[0]{constraint} ||= $_[0]->_build_constraint }

  sub _build_display_name
  {
  	my $self = shift;
  	sprintf("Enum[%s]", join q[,], @$self);
  }

  sub _build_constraint
  {
  	my $self = shift;

  	my $regexp = join "|", map quotemeta, @$self;
  	return sub { defined and m{\A(?:$regexp)\z} };
  }

  sub can_be_inlined
  {
  	!!1;
  }

  sub inline_check
  {
  	my $self = shift;

  	if (Type::Tiny::_USE_XS)
  	{
  		my $enum = join ",", @{$self->values};
  		my $xsub = Type::Tiny::XS::get_subname_for("Enum[$enum]");
  		return "$xsub\($_[0]\)" if $xsub;
  	}

  	my $regexp = join "|", map quotemeta, @$self;
  	$_[0] eq '$_'
  		? "(defined and !ref and m{\\A(?:$regexp)\\z})"
  		: "(defined($_[0]) and !ref($_[0]) and $_[0] =~ m{\\A(?:$regexp)\\z})";
  }

  sub _instantiate_moose_type
  {
  	my $self = shift;
  	my %opts = @_;
  	delete $opts{parent};
  	delete $opts{constraint};
  	delete $opts{inlined};
  	require Moose::Meta::TypeConstraint::Enum;
  	return "Moose::Meta::TypeConstraint::Enum"->new(%opts, values => $self->values);
  }

  sub has_parent
  {
  	!!1;
  }

  sub parent
  {
  	require Types::Standard;
  	Types::Standard::Str();
  }

  sub validate_explain
  {
  	my $self = shift;
  	my ($value, $varname) = @_;
  	$varname = '$_' unless defined $varname;

  	return undef if $self->check($value);

  	require Type::Utils;
  	!defined($value) ? [
  		sprintf(
  			'"%s" requires that the value is defined',
  			$self,
  		),
  	] :
  	@$self < 13 ? [
  		sprintf(
  			'"%s" requires that the value is equal to %s',
  			$self,
  			Type::Utils::english_list(\"or", map B::perlstring($_), @$self),
  		),
  	] :
  	[
  		sprintf(
  			'"%s" requires that the value is one of an enumerated list of strings',
  			$self,
  		),
  	];
  }


  1;

  __END__

  =pod

  =encoding utf-8

  =head1 NAME

  Type::Tiny::Enum - string enum type constraints

  =head1 STATUS

  This module is covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  Enum type constraints.

  This package inherits from L<Type::Tiny>; see that for most documentation.
  Major differences are listed below:

  =head2 Attributes

  =over

  =item C<values>

  Arrayref of allowable value strings. Non-string values (e.g. objects with
  overloading) will be stringified in the constructor.

  =item C<constraint>

  Unlike Type::Tiny, you I<cannot> pass a constraint coderef to the constructor.
  Instead rely on the default.

  =item C<inlined>

  Unlike Type::Tiny, you I<cannot> pass an inlining coderef to the constructor.
  Instead rely on the default.

  =item C<parent>

  Parent is always Types::Standard::Str, and cannot be passed to the
  constructor.

  =back

  =head2 Overloading

  =over

  =item *

  Arrayrefification calls C<values>.

  =back

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Type::Tiny::Manual>.

  L<Type::Tiny>.

  L<Moose::Meta::TypeConstraint::Enum>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

TYPE_TINY_ENUM

$fatpacked{"Type/Tiny/Intersection.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TYPE_TINY_INTERSECTION';
  package Type::Tiny::Intersection;

  use 5.006001;
  use strict;
  use warnings;

  BEGIN {
  	$Type::Tiny::Intersection::AUTHORITY = 'cpan:TOBYINK';
  	$Type::Tiny::Intersection::VERSION   = '1.000005';
  }

  use Scalar::Util qw< blessed >;
  use Types::TypeTiny ();

  sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }

  use overload q[@{}] => sub { $_[0]{type_constraints} ||= [] };

  use Type::Tiny ();
  our @ISA = 'Type::Tiny';

  sub new {
  	my $proto = shift;

  	my %opts = (@_==1) ? %{$_[0]} : @_;
  	_croak "Intersection type constraints cannot have a parent constraint" if exists $opts{parent};
  	_croak "Intersection type constraints cannot have a constraint coderef passed to the constructor" if exists $opts{constraint};
  	_croak "Intersection type constraints cannot have a inlining coderef passed to the constructor" if exists $opts{inlined};
  	_croak "Need to supply list of type constraints" unless exists $opts{type_constraints};

  	$opts{type_constraints} = [
  		map { $_->isa(__PACKAGE__) ? @$_ : $_ }
  		map Types::TypeTiny::to_TypeTiny($_),
  		@{ ref $opts{type_constraints} eq "ARRAY" ? $opts{type_constraints} : [$opts{type_constraints}] }
  	];

  	if (Type::Tiny::_USE_XS)
  	{
  		my @constraints = @{$opts{type_constraints}};
  		my @known = map {
  			my $known = Type::Tiny::XS::is_known($_->compiled_check);
  			defined($known) ? $known : ();
  		} @constraints;

  		if (@known == @constraints)
  		{
  			my $xsub = Type::Tiny::XS::get_coderef_for(
  				sprintf "AllOf[%s]", join(',', @known)
  			);
  			$opts{compiled_type_constraint} = $xsub if $xsub;
  		}
  	}

  	return $proto->SUPER::new(%opts);
  }

  sub type_constraints { $_[0]{type_constraints} }
  sub constraint       { $_[0]{constraint} ||= $_[0]->_build_constraint }

  sub _build_display_name
  {
  	my $self = shift;
  	join q[&], @$self;
  }

  sub _build_constraint
  {
  	my @checks = map $_->compiled_check, @{+shift};
  	return sub
  	{
  		my $val = $_;
  		$_->($val) || return for @checks;
  		return !!1;
  	}
  }

  sub can_be_inlined
  {
  	my $self = shift;
  	not grep !$_->can_be_inlined, @$self;
  }

  sub inline_check
  {
  	my $self = shift;

  	if (Type::Tiny::_USE_XS and !exists $self->{xs_sub})
  	{
  		$self->{xs_sub} = undef;

  		my @constraints = @{$self->type_constraints};
  		my @known = map {
  			my $known = Type::Tiny::XS::is_known($_->compiled_check);
  			defined($known) ? $known : ();
  		} @constraints;

  		if (@known == @constraints)
  		{
  			$self->{xs_sub} = Type::Tiny::XS::get_subname_for(
  				sprintf "AllOf[%s]", join(',', @known)
  			);
  		}
  	}

  	if (Type::Tiny::_USE_XS and $self->{xs_sub}) {
  		return "$self->{xs_sub}\($_[0]\)";
  	}

  	sprintf '(%s)', join " and ", map $_->inline_check($_[0]), @$self;
  }

  sub has_parent
  {
  	!!@{ $_[0]{type_constraints} };
  }

  sub parent
  {
  	$_[0]{type_constraints}[0];
  }

  sub validate_explain
  {
  	my $self = shift;
  	my ($value, $varname) = @_;
  	$varname = '$_' unless defined $varname;

  	return undef if $self->check($value);

  	require Type::Utils;
  	for my $type (@$self)
  	{
  		my $deep = $type->validate_explain($value, $varname);
  		return [
  			sprintf(
  				'"%s" requires that the value pass %s',
  				$self,
  				Type::Utils::english_list(map qq["$_"], @$self),
  			),
  			@$deep,
  		] if $deep;
  	}

  	# This should never happen...
  	return;  # uncoverable statement
  }


  1;

  __END__

  =pod

  =encoding utf-8

  =head1 NAME

  Type::Tiny::Intersection - intersection type constraints

  =head1 STATUS

  This module is covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  Intersection type constraints.

  This package inherits from L<Type::Tiny>; see that for most documentation.
  Major differences are listed below:

  =head2 Attributes

  =over

  =item C<type_constraints>

  Arrayref of type constraints.

  When passed to the constructor, if any of the type constraints in the
  intersection is itself an intersection type constraint, this is "exploded"
  into the new intersection.

  =item C<constraint>

  Unlike Type::Tiny, you I<cannot> pass a constraint coderef to the constructor.
  Instead rely on the default.

  =item C<inlined>

  Unlike Type::Tiny, you I<cannot> pass an inlining coderef to the constructor.
  Instead rely on the default.

  =item C<parent>

  Unlike Type::Tiny, you I<cannot> pass an inlining coderef to the constructor.
  A parent will instead be automatically calculated.

  (Technically any of the types in the intersection could be treated as a
  parent type; we choose the first arbitrarily.)

  =back

  =head2 Overloading

  =over

  =item *

  Arrayrefification calls C<type_constraints>.

  =back

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Type::Tiny::Manual>.

  L<Type::Tiny>.

  L<MooseX::Meta::TypeConstraint::Intersection>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

TYPE_TINY_INTERSECTION

$fatpacked{"Type/Tiny/Role.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TYPE_TINY_ROLE';
  package Type::Tiny::Role;

  use 5.006001;
  use strict;
  use warnings;

  BEGIN {
  	$Type::Tiny::Role::AUTHORITY = 'cpan:TOBYINK';
  	$Type::Tiny::Role::VERSION   = '1.000005';
  }

  use Scalar::Util qw< blessed weaken >;

  sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }

  require Type::Tiny;
  our @ISA = 'Type::Tiny';

  my %cache;

  sub new {
  	my $proto = shift;

  	my %opts = (@_==1) ? %{$_[0]} : @_;
  	_croak "Role type constraints cannot have a parent constraint passed to the constructor" if exists $opts{parent};
  	_croak "Role type constraints cannot have a constraint coderef passed to the constructor" if exists $opts{constraint};
  	_croak "Role type constraints cannot have a inlining coderef passed to the constructor" if exists $opts{inlined};
  	_croak "Need to supply role name" unless exists $opts{role};

  	return $proto->SUPER::new(%opts);
  }

  sub role        { $_[0]{role} }
  sub inlined     { $_[0]{inlined} ||= $_[0]->_build_inlined }

  sub has_inlined { !!1 }

  sub _build_constraint
  {
  	my $self = shift;
  	my $role = $self->role;
  	return sub { blessed($_) and do { my $method = $_->can('DOES')||$_->can('isa'); $_->$method($role) } };
  }

  sub _build_inlined
  {
  	my $self = shift;
  	my $role = $self->role;
  	sub {
  		my $var = $_[1];
  		qq{Scalar::Util::blessed($var) and do { my \$method = $var->can('DOES')||$var->can('isa'); $var->\$method(q[$role]) }};
  	};
  }

  sub _build_default_message
  {
  	my $self = shift;
  	my $c = $self->role;
  	return sub { sprintf '%s did not pass type constraint (not DOES %s)', Type::Tiny::_dd($_[0]), $c } if $self->is_anon;
  	my $name = "$self";
  	return sub { sprintf '%s did not pass type constraint "%s" (not DOES %s)', Type::Tiny::_dd($_[0]), $name, $c };
  }

  sub has_parent
  {
  	!!1;
  }

  sub parent
  {
  	require Types::Standard;
  	Types::Standard::Object();
  }

  sub validate_explain
  {
  	my $self = shift;
  	my ($value, $varname) = @_;
  	$varname = '$_' unless defined $varname;

  	return undef if $self->check($value);
  	return ["Not a blessed reference"] unless blessed($value);
  	return ["Reference provides no DOES method to check roles"] unless $value->can('DOES');

  	my $display_var = $varname eq q{$_} ? '' : sprintf(' (in %s)', $varname);

  	return [
  		sprintf('"%s" requires that the reference does %s', $self, $self->role),
  		sprintf("The reference%s doesn't %s", $display_var, $self->role),
  	];
  }

  1;

  __END__

  =pod

  =encoding utf-8

  =head1 NAME

  Type::Tiny::Role - type constraints based on the "DOES" method

  =head1 STATUS

  This module is covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  Type constraints of the general form C<< { $_->DOES("Some::Role") } >>.

  This package inherits from L<Type::Tiny>; see that for most documentation.
  Major differences are listed below:

  =head2 Attributes

  =over

  =item C<role>

  The role for the constraint.

  Note that this package doesn't subscribe to any particular flavour of roles
  (L<Moose::Role>, L<Mouse::Role>, L<Moo::Role>, L<Role::Tiny>, etc). It simply
  trusts the object's C<DOES> method (see L<UNIVERSAL>).

  =item C<constraint>

  Unlike Type::Tiny, you I<cannot> pass a constraint coderef to the constructor.
  Instead rely on the default.

  =item C<inlined>

  Unlike Type::Tiny, you I<cannot> pass an inlining coderef to the constructor.
  Instead rely on the default.

  =item C<parent>

  Parent is always Types::Standard::Object, and cannot be passed to the
  constructor.

  =back

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Type::Tiny::Manual>.

  L<Type::Tiny>.

  L<Moose::Meta::TypeConstraint::Role>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

TYPE_TINY_ROLE

$fatpacked{"Type/Tiny/Union.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TYPE_TINY_UNION';
  package Type::Tiny::Union;

  use 5.006001;
  use strict;
  use warnings;

  BEGIN {
  	$Type::Tiny::Union::AUTHORITY = 'cpan:TOBYINK';
  	$Type::Tiny::Union::VERSION   = '1.000005';
  }

  use Scalar::Util qw< blessed >;
  use Types::TypeTiny ();

  sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }

  use overload q[@{}] => sub { $_[0]{type_constraints} ||= [] };

  use Type::Tiny ();
  our @ISA = 'Type::Tiny';

  sub new {
  	my $proto = shift;

  	my %opts = (@_==1) ? %{$_[0]} : @_;
  	_croak "Union type constraints cannot have a parent constraint passed to the constructor" if exists $opts{parent};
  	_croak "Union type constraints cannot have a constraint coderef passed to the constructor" if exists $opts{constraint};
  	_croak "Union type constraints cannot have a inlining coderef passed to the constructor" if exists $opts{inlined};
  	_croak "Need to supply list of type constraints" unless exists $opts{type_constraints};

  	$opts{type_constraints} = [
  		map { $_->isa(__PACKAGE__) ? @$_ : $_ }
  		map Types::TypeTiny::to_TypeTiny($_),
  		@{ ref $opts{type_constraints} eq "ARRAY" ? $opts{type_constraints} : [$opts{type_constraints}] }
  	];

  	if (Type::Tiny::_USE_XS)
  	{
  		my @constraints = @{$opts{type_constraints}};
  		my @known = map {
  			my $known = Type::Tiny::XS::is_known($_->compiled_check);
  			defined($known) ? $known : ();
  		} @constraints;

  		if (@known == @constraints)
  		{
  			my $xsub = Type::Tiny::XS::get_coderef_for(
  				sprintf "AnyOf[%s]", join(',', @known)
  			);
  			$opts{compiled_type_constraint} = $xsub if $xsub;
  		}
  	}

  	my $self = $proto->SUPER::new(%opts);
  	$self->coercion if grep $_->has_coercion, @$self;
  	return $self;
  }

  sub type_constraints { $_[0]{type_constraints} }
  sub constraint       { $_[0]{constraint} ||= $_[0]->_build_constraint }

  sub _build_display_name
  {
  	my $self = shift;
  	join q[|], @$self;
  }

  sub _build_coercion
  {
  	require Type::Coercion::Union;
  	my $self = shift;
  	return "Type::Coercion::Union"->new(type_constraint => $self);
  }

  sub _build_constraint
  {
  	my @checks = map $_->compiled_check, @{+shift};
  	return sub
  	{
  		my $val = $_;
  		$_->($val) && return !!1 for @checks;
  		return;
  	}
  }

  sub can_be_inlined
  {
  	my $self = shift;
  	not grep !$_->can_be_inlined, @$self;
  }

  sub inline_check
  {
  	my $self = shift;

  	if (Type::Tiny::_USE_XS and !exists $self->{xs_sub})
  	{
  		$self->{xs_sub} = undef;

  		my @constraints = @{$self->type_constraints};
  		my @known = map {
  			my $known = Type::Tiny::XS::is_known($_->compiled_check);
  			defined($known) ? $known : ();
  		} @constraints;

  		if (@known == @constraints)
  		{
  			$self->{xs_sub} = Type::Tiny::XS::get_subname_for(
  				sprintf "AnyOf[%s]", join(',', @known)
  			);
  		}
  	}

  	if (Type::Tiny::_USE_XS and $self->{xs_sub}) {
  		return "$self->{xs_sub}\($_[0]\)";
  	}

  	sprintf '(%s)', join " or ", map $_->inline_check($_[0]), @$self;
  }

  sub _instantiate_moose_type
  {
  	my $self = shift;
  	my %opts = @_;
  	delete $opts{parent};
  	delete $opts{constraint};
  	delete $opts{inlined};

  	my @tc = map $_->moose_type, @{$self->type_constraints};

  	require Moose::Meta::TypeConstraint::Union;
  	return "Moose::Meta::TypeConstraint::Union"->new(%opts, type_constraints => \@tc);
  }

  sub has_parent
  {
  	defined(shift->parent);
  }

  sub parent
  {
  	$_[0]{parent} ||= $_[0]->_build_parent;
  }

  sub _build_parent
  {
  	my $self = shift;
  	my ($first, @rest) = @$self;

  	for my $parent ($first, $first->parents)
  	{
  		return $parent unless grep !$_->is_a_type_of($parent), @rest;
  	}

  	return;
  }

  sub find_type_for
  {
  	my @types = @{+shift};
  	for my $type (@types)
  	{
  		return $type if $type->check(@_);
  	}
  	return;
  }

  sub validate_explain
  {
  	my $self = shift;
  	my ($value, $varname) = @_;
  	$varname = '$_' unless defined $varname;

  	return undef if $self->check($value);

  	require Type::Utils;
  	return [
  		sprintf(
  			'"%s" requires that the value pass %s',
  			$self,
  			Type::Utils::english_list(\"or", map qq["$_"], @$self),
  		),
  		map {
  			$_->get_message($value),
  			map("    $_", @{ $_->validate_explain($value) || []}),
  		} @$self
  	];
  }

  1;

  __END__

  =pod

  =encoding utf-8

  =head1 NAME

  Type::Tiny::Union - union type constraints

  =head1 STATUS

  This module is covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  Union type constraints.

  This package inherits from L<Type::Tiny>; see that for most documentation.
  Major differences are listed below:

  =head2 Attributes

  =over

  =item C<type_constraints>

  Arrayref of type constraints.

  When passed to the constructor, if any of the type constraints in the union
  is itself a union type constraint, this is "exploded" into the new union.

  =item C<constraint>

  Unlike Type::Tiny, you I<cannot> pass a constraint coderef to the constructor.
  Instead rely on the default.

  =item C<inlined>

  Unlike Type::Tiny, you I<cannot> pass an inlining coderef to the constructor.
  Instead rely on the default.

  =item C<parent>

  Unlike Type::Tiny, you I<cannot> pass an inlining coderef to the constructor.
  A parent will instead be automatically calculated.

  =item C<coercion>

  You probably do not pass this to the constructor. (It's not currently
  disallowed, as there may be a use for it that I haven't thought of.)

  The auto-generated default will be a L<Type::Coercion::Union> object.

  =back

  =head2 Methods

  =over

  =item C<< find_type_for($value) >>

  Returns the first individual type constraint in the union which
  C<< $value >> passes.

  =back

  =head2 Overloading

  =over

  =item *

  Arrayrefification calls C<type_constraints>.

  =back

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Type::Tiny::Manual>.

  L<Type::Tiny>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

TYPE_TINY_UNION

$fatpacked{"Type/Tiny/_HalfOp.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TYPE_TINY__HALFOP';
  package Type::Tiny::_HalfOp;

  use 5.006001;
  use strict;
  use warnings;

  BEGIN {
  	$Type::Tiny::_HalfOp::AUTHORITY = 'cpan:TOBYINK';
  	$Type::Tiny::_HalfOp::VERSION   = '1.000005';
  }

  use overload ();

  sub new {
  	my ($class, $op, $param, $type) = @_;
  	bless {
  		op    => $op,
  		param => $param,
  		type  => $type,
  	}, $class;
  }

  sub complete {
  	my ($self, $type) = @_;
  	my $complete_type = $type->parameterize(@{$self->{param}});
  	my $method = overload::Method($complete_type, $self->{op});
  	$complete_type->$method($self->{type});
  }

  1;

  __END__

  =pod

  =encoding utf-8

  =for stopwords pragmas

  =head1 NAME

  Type::Tiny::_HalfOp - half-completed overloaded operation

  =head1 STATUS

  This module is considered part of Type-Tiny's internals. It is not
  covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  This is not considered part of Type::Tiny's public API.

  It is a class representing a half-completed overloaded operation.

  =head2 Constructor

  =over

  =item C<< new($operation, $param, $type) >>

  =back

  =head2 Method

  =over

  =item C<< complete($type) >>

  =back

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 AUTHOR

  Graham Knop E<lt>haarg@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2014 by Graham Knop.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

TYPE_TINY__HALFOP

$fatpacked{"Type/Utils.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TYPE_UTILS';
  package Type::Utils;

  use 5.006001;
  use strict;
  use warnings;

  BEGIN {
  	$Type::Utils::AUTHORITY = 'cpan:TOBYINK';
  	$Type::Utils::VERSION   = '1.000005';
  }

  sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }

  use Scalar::Util qw< blessed >;
  use Type::Library;
  use Type::Tiny;
  use Types::TypeTiny qw< TypeTiny to_TypeTiny HashLike StringLike CodeLike >;

  our @EXPORT = qw<
  	declare as where message inline_as
  	class_type role_type duck_type union intersection enum
  	coerce from via
  	declare_coercion to_type
  >;
  our @EXPORT_OK = (
  	@EXPORT,
  	qw<
  		extends type subtype
  		match_on_type compile_match_on_type
  		dwim_type english_list
  		classifier
  	>,
  );

  require Exporter::Tiny;
  our @ISA = 'Exporter::Tiny';

  sub extends
  {
  	_croak "Not a type library" unless caller->isa("Type::Library");
  	my $caller = caller->meta;

  	foreach my $lib (@_)
  	{
  		eval "use $lib; 1" or _croak "Could not load library '$lib': $@";

  		if ($lib->isa("Type::Library") or $lib eq 'Types::TypeTiny')
  		{
  			$caller->add_type( $lib->get_type($_) )
  				for sort $lib->meta->type_names;
  			$caller->add_coercion( $lib->get_coercion($_) )
  				for sort $lib->meta->coercion_names;
  		}
  		elsif ($lib->isa('MooseX::Types::Base'))
  		{
  			require Moose::Util::TypeConstraints;
  			my $types = $lib->type_storage;
  			for my $name (sort keys %$types)
  			{
  				my $moose = Moose::Util::TypeConstraints::find_type_constraint($types->{$name});
  				my $tt    = Types::TypeTiny::to_TypeTiny($moose);
  				$caller->add_type(
  					$tt->create_child_type(library => $caller, name => $name, coercion => $moose->has_coercion ? 1 : 0)
  				);
  			}
  		}
  		elsif ($lib->isa('MouseX::Types::Base'))
  		{
  			require Mouse::Util::TypeConstraints;
  			my $types = $lib->type_storage;
  			for my $name (sort keys %$types)
  			{
  				my $mouse = Mouse::Util::TypeConstraints::find_type_constraint($types->{$name});
  				my $tt    = Types::TypeTiny::to_TypeTiny($mouse);
  				$caller->add_type(
  					$tt->create_child_type(library => $caller, name => $name, coercion => $mouse->has_coercion ? 1 : 0)
  				);
  			}
  		}
  		else
  		{
  			_croak("'$lib' is not a type constraint library");
  		}
  	}
  }

  sub declare
  {
  	my %opts;
  	if (@_ % 2 == 0)
  	{
  		%opts = @_;
  		if (@_==2 and $_[0]=~ /^_*[A-Z]/ and $_[1] =~ /^[0-9]+$/)
  		{
  			require Carp;
  			Carp::carp("Possible missing comma after 'declare $_[0]'");
  		}
  	}
  	else
  	{
  		(my($name), %opts) = @_;
  		_croak "Cannot provide two names for type" if exists $opts{name};
  		$opts{name} = $name;
  	}

  	my $caller = caller($opts{_caller_level} || 0);
  	$opts{library} = $caller;

  	if (defined $opts{parent})
  	{
  		$opts{parent} = to_TypeTiny($opts{parent});

  		unless (TypeTiny->check($opts{parent}))
  		{
  			$caller->isa("Type::Library")
  				or _croak("Parent type cannot be a %s", ref($opts{parent})||'non-reference scalar');
  			$opts{parent} = $caller->meta->get_type($opts{parent})
  				or _croak("Could not find parent type");
  		}
  	}

  	my $type;
  	if (defined $opts{parent})
  	{
  		$type = delete($opts{parent})->create_child_type(%opts);
  	}
  	else
  	{
  		my $bless = delete($opts{bless}) || "Type::Tiny";
  		eval "require $bless";
  		$type = $bless->new(%opts);
  	}

  	if ($caller->isa("Type::Library"))
  	{
  		$caller->meta->add_type($type) unless $type->is_anon;
  	}

  	return $type;
  }

  *subtype = \&declare;
  *type = \&declare;

  sub as (@)
  {
  	parent => @_;
  }

  sub where (&;@)
  {
  	constraint => @_;
  }

  sub message (&;@)
  {
  	message => @_;
  }

  sub inline_as (&;@)
  {
  	inlined => @_;
  }

  sub class_type
  {
  	my $name = ref($_[0]) ? undef : shift;
  	my %opts = %{ shift or {} };

  	if (defined $name)
  	{
  		$opts{name}  = $name unless exists $opts{name};
  		$opts{class} = $name unless exists $opts{class};

  		$opts{name} =~ s/:://g;
  	}

  	$opts{bless} = "Type::Tiny::Class";

  	{ no warnings "numeric"; $opts{_caller_level}++ }
  	declare(%opts);
  }

  sub role_type
  {
  	my $name = ref($_[0]) ? undef : shift;
  	my %opts = %{ shift or {} };

  	if (defined $name)
  	{
  		$opts{name} = $name unless exists $opts{name};
  		$opts{role} = $name unless exists $opts{role};

  		$opts{name} =~ s/:://g;
  	}

  	$opts{bless} = "Type::Tiny::Role";

  	{ no warnings "numeric"; $opts{_caller_level}++ }
  	declare(%opts);
  }

  sub duck_type
  {
  	my $name    = ref($_[0]) ? undef : shift;
  	my @methods = @{ shift or [] };

  	my %opts;
  	$opts{name} = $name if defined $name;
  	$opts{methods} = \@methods;

  	$opts{bless} = "Type::Tiny::Duck";

  	{ no warnings "numeric"; $opts{_caller_level}++ }
  	declare(%opts);
  }

  sub enum
  {
  	my $name   = ref($_[0]) ? undef : shift;
  	my @values = @{ shift or [] };

  	my %opts;
  	$opts{name} = $name if defined $name;
  	$opts{values} = \@values;

  	$opts{bless} = "Type::Tiny::Enum";

  	{ no warnings "numeric"; $opts{_caller_level}++ }
  	declare(%opts);
  }

  sub union
  {
  	my $name = ref($_[0]) ? undef : shift;
  	my @tcs  = @{ shift or [] };

  	my %opts;
  	$opts{name} = $name if defined $name;
  	$opts{type_constraints} = \@tcs;

  	$opts{bless} = "Type::Tiny::Union";

  	{ no warnings "numeric"; $opts{_caller_level}++ }
  	declare(%opts);
  }

  sub intersection
  {
  	my $name = ref($_[0]) ? undef : shift;
  	my @tcs  = @{ shift or [] };

  	my %opts;
  	$opts{name} = $name if defined $name;
  	$opts{type_constraints} = \@tcs;

  	$opts{bless} = "Type::Tiny::Intersection";

  	{ no warnings "numeric"; $opts{_caller_level}++ }
  	declare(%opts);
  }

  sub declare_coercion
  {
  	my %opts;
  	$opts{name} = shift if !ref($_[0]);

  	while (HashLike->check($_[0]) and not TypeTiny->check($_[0]))
  	{
  		%opts = (%opts, %{+shift});
  	}

  	my $caller = caller($opts{_caller_level} || 0);
  	$opts{library} = $caller;

  	my $bless = delete($opts{bless}) || "Type::Coercion";
  	eval "require $bless";
  	my $c = $bless->new(%opts);

  	my @C;

  	if ($caller->isa("Type::Library"))
  	{
  		my $meta = $caller->meta;
  		$meta->add_coercion($c) unless $c->is_anon;
  		while (@_)
  		{
  			push @C, map { ref($_) ? to_TypeTiny($_) : $meta->get_type($_)||$_ } shift;
  			push @C, shift;
  		}
  	}
  	else
  	{
  		@C = @_;
  	}

  	$c->add_type_coercions(@C);

  	return $c->freeze;
  }

  sub coerce
  {
  	if ((scalar caller)->isa("Type::Library"))
  	{
  		my $meta = (scalar caller)->meta;
  		my ($type) = map { ref($_) ? to_TypeTiny($_) : $meta->get_type($_)||$_ } shift;
  		my @opts;
  		while (@_)
  		{
  			push @opts, map { ref($_) ? to_TypeTiny($_) : $meta->get_type($_)||$_ } shift;
  			push @opts, shift;
  		}
  		return $type->coercion->add_type_coercions(@opts);
  	}

  	my ($type, @opts) = @_;
  	$type = to_TypeTiny($type);
  	return $type->coercion->add_type_coercions(@opts);
  }

  sub from (@)
  {
  	return @_;
  }

  sub to_type (@)
  {
  	my $type = shift;
  	unless (TypeTiny->check($type))
  	{
  		caller->isa("Type::Library")
  			or _croak "Target type cannot be a string";
  		$type = caller->meta->get_type($type)
  			or _croak "Could not find target type";
  	}
  	return +{ type_constraint => $type }, @_;
  }

  sub via (&;@)
  {
  	return @_;
  }

  sub match_on_type
  {
  	my $value = shift;

  	while (@_)
  	{
  		my $code;
  		if (@_ == 1)
  		{
  			$code = shift;
  		}
  		else
  		{
  			(my($type), $code) = splice(@_, 0, 2);
  			TypeTiny->($type)->check($value) or next;
  		}

  		if (StringLike->check($code))
  		{
  			local $_ = $value;
  			if (wantarray) {
  				my @r = eval "$code";
  				die $@ if $@;
  				return @r;
  			}
  			if (defined wantarray) {
  				my $r = eval "$code";
  				die $@ if $@;
  				return $r;
  			}
  			eval "$code";
  			die $@ if $@;
  			return;
  		}
  		else
  		{
  			CodeLike->($code);
  			local $_ = $value;
  			return $code->($value);
  		}
  	}

  	_croak("No cases matched for %s", Type::Tiny::_dd($value));
  }

  sub compile_match_on_type
  {
  	my @code = 'sub { local $_ = $_[0]; ';
  	my @checks;
  	my @actions;

  	my $els = '';

  	while (@_)
  	{
  		my ($type, $code);
  		if (@_ == 1)
  		{
  			require Types::Standard;
  			($type, $code) = (Types::Standard::Any(), shift);
  		}
  		else
  		{
  			($type, $code) = splice(@_, 0, 2);
  			TypeTiny->($type);
  		}

  		if ($type->can_be_inlined)
  		{
  			push @code, sprintf('%sif (%s)', $els, $type->inline_check('$_'));
  		}
  		else
  		{
  			push @checks, $type;
  			push @code, sprintf('%sif ($checks[%d]->check($_))', $els, $#checks);
  		}

  		$els = 'els';

  		if (StringLike->check($code))
  		{
  			push @code, sprintf('  { %s }', $code);
  		}
  		else
  		{
  			CodeLike->($code);
  			push @actions, $code;
  			push @code, sprintf('  { $actions[%d]->(@_) }', $#actions);
  		}
  	}

  	push @code, 'else', '  { Type::Utils::_croak("No cases matched for %s", Type::Tiny::_dd($_[0])) }';

  	push @code, '}';  # /sub

  	require Eval::TypeTiny;
  	return Eval::TypeTiny::eval_closure(
  		source      => \@code,
  		environment => {
  			'@actions' => \@actions,
  			'@checks'  => \@checks,
  		},
  	);
  }

  sub classifier
  {
  	my $i;
  	compile_match_on_type(
  		+(
  			map {
  				my $type = $_->[0];
  				$type => sub { $type };
  			}
  			sort { $b->[1] <=> $a->[1] or $a->[2] <=> $b->[2] }
  			map [$_, scalar(my @parents = $_->parents), ++$i],
  			@_
  		),
  		q[ undef ],
  	);
  }

  {
  	package #hide
  	Type::Registry::DWIM;

  	our @ISA = qw(Type::Registry);

  	sub foreign_lookup
  	{
  		my $self = shift;
  		my $r = $self->SUPER::foreign_lookup(@_);
  		return $r if $r;

  		if (defined($self->{"~~assume"})
  		and $_[0] =~ /[A-Z_a-z][0-9A-Z_a-z]*(?:::[0-9A-Z_a-z]+)*/)
  		{
  			my $method = $self->{"~~assume"};
  			return $self->$method(@_);
  		}

  		return;
  	}

  	sub simple_lookup
  	{
  		my $self = shift;
  		my $r;

  		# If the lookup is chained to a class, then the class' own
  		# type registry gets first refusal.
  		#
  		if (defined $self->{"~~chained"})
  		{
  			my $chained = "Type::Registry"->for_class($self->{"~~chained"});
  			$r = eval { $chained->simple_lookup(@_) } unless $self == $chained;
  			return $r if defined $r;
  		}

  		# Fall back to types in Types::Standard.
  		require Types::Standard;
  		return 'Types::Standard'->get_type($_[0]) if 'Types::Standard'->has_type($_[0]);

  		# Only continue any further if we've been called from Type::Parser.
  		return unless $_[1];

  		my $moose_lookup = sub
  		{
  			if ($INC{'Moose.pm'})
  			{
  				require Moose::Util::TypeConstraints;
  				require Types::TypeTiny;
  				$r = Moose::Util::TypeConstraints::find_type_constraint($_[0]);
  				$r = Types::TypeTiny::to_TypeTiny($r) if defined $r;
  			}
  			defined $r;
  		};

  		my $mouse_lookup = sub
  		{
  			if ($INC{'Mouse.pm'})
  			{
  				require Mouse::Util::TypeConstraints;
  				require Types::TypeTiny;
  				$r = Mouse::Util::TypeConstraints::find_type_constraint($_[0]);
  				$r = Types::TypeTiny::to_TypeTiny($r) if defined $r;
  			}
  			defined $r;
  		};

  		my $meta;
  		if (defined $self->{"~~chained"})
  		{
  			$meta ||= Moose::Util::find_meta($self->{"~~chained"}) if $INC{'Moose.pm'};
  			$meta ||= Mouse::Util::find_meta($self->{"~~chained"}) if $INC{'Mouse.pm'};
  		}

  		if ($meta and $meta->isa('Class::MOP::Module'))
  		{
  			$moose_lookup->(@_) and return $r;
  		}
  		elsif ($meta and $meta->isa('Mouse::Meta::Module'))
  		{
  			$mouse_lookup->(@_) and return $r;
  		}
  		else
  		{
  			$moose_lookup->(@_) and return $r;
  			$mouse_lookup->(@_) and return $r;
  		}

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

  our $dwimmer;
  sub dwim_type
  {
  	my ($string, %opts) = @_;
  	$opts{for} = caller unless defined $opts{for};

  	$dwimmer ||= do {
  		require Type::Registry;
  		'Type::Registry::DWIM'->new;
  	};

  	local $dwimmer->{'~~chained'} = $opts{for};
  	local $dwimmer->{'~~assume'}  = $opts{does} ? 'make_role_type' : 'make_class_type';

  	$dwimmer->lookup($string);
  }

  sub english_list
  {
  	my $conjunction = ref($_[0]) eq 'SCALAR' ? ${+shift} : 'and';
  	my @items = sort @_;

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

  	my $tail = pop @items;
  	join(', ', @items, "$conjunction $tail");
  }

  1;

  __END__

  =pod

  =encoding utf-8

  =for stopwords smush smushed

  =head1 NAME

  Type::Utils - utility functions to make defining and using type constraints a little easier

  =head1 SYNOPSIS

     package Types::Mine;

     use Type::Library -base;
     use Type::Utils -all;

     BEGIN { extends "Types::Standard" };

     declare "AllCaps",
        as "Str",
        where { uc($_) eq $_ },
        inline_as { my $varname = $_[1]; "uc($varname) eq $varname" };

     coerce "AllCaps",
        from "Str", via { uc($_) };

  =head1 STATUS

  This module is covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  This module provides utility functions to make defining and using type
  constraints a little easier.

  =head2 Type declaration functions

  Many of the following are similar to the similarly named functions described
  in L<Moose::Util::TypeConstraints>.

  =over

  =item C<< declare $name, %options >>

  =item C<< declare %options >>

  Declare a named or anonymous type constraint. Use C<as> and C<where> to
  specify the parent type (if any) and (possibly) refine its definition.

     declare EvenInt, as Int, where { $_ % 2 == 0 };

     my $EvenInt = declare as Int, where { $_ % 2 == 0 };

  B<< NOTE: >>
  If the caller package inherits from L<Type::Library> then any non-anonymous
  types declared in the package will be automatically installed into the
  library.

  Hidden gem: if you're inheriting from a type constraint that includes some
  coercions, you can include C<< coercion => 1 >> in the C<< %options >> hash
  to inherit the coercions.

  =item C<< subtype $name, %options >>

  =item C<< subtype %options >>

  Declare a named or anonymous type constraint which is descended from an
  existing type constraint. Use C<as> and C<where> to specify the parent
  type and refine its definition.

  Actually, you should use C<declare> instead; this is just an alias.

  This function is not exported by default.

  =item C<< type $name, %options >>

  =item C<< type %options >>

  Declare a named or anonymous type constraint which is not descended from
  an existing type constraint. Use C<where> to provide a coderef that
  constrains values.

  Actually, you should use C<declare> instead; this is just an alias.

  This function is not exported by default.

  =item C<< as $parent >>

  Used with C<declare> to specify a parent type constraint:

     declare EvenInt, as Int, where { $_ % 2 == 0 };

  =item C<< where { BLOCK } >>

  Used with C<declare> to provide the constraint coderef:

     declare EvenInt, as Int, where { $_ % 2 == 0 };

  The coderef operates on C<< $_ >>, which is the value being tested.

  =item C<< message { BLOCK } >>

  Generate a custom error message when a value fails validation.

     declare EvenInt,
        as Int,
        where { $_ % 2 == 0 },
        message {
           Int->validate($_) or "$_ is not divisible by two";
        };

  Without a custom message, the messages generated by Type::Tiny are along
  the lines of I<< Value "33" did not pass type constraint "EvenInt" >>,
  which is usually reasonable.

  =item C<< inline_as { BLOCK } >>

  Generate a string of Perl code that can be used to inline the type check into
  other functions. If your type check is being used within a L<Moose> or L<Moo>
  constructor or accessor methods, or used by L<Type::Params>, this can lead to
  significant performance improvements.

     declare EvenInt,
        as Int,
        where { $_ % 2 == 0 },
        inline_as {
           my ($constraint, $varname) = @_;
           my $perlcode =
              $constraint->parent->inline_check($varname)
              . "&& ($varname % 2 == 0)";
           return $perlcode;
        };

     warn EvenInt->inline_check('$xxx');  # demonstration

  B<Experimental:> your C<inline_as> block can return a list, in which case
  these will be smushed together with "&&". The first item on the list may
  be undef, in which case the undef will be replaced by the inlined parent
  type constraint. (And will throw an exception if there is no parent.)

     declare EvenInt,
        as Int,
        where { $_ % 2 == 0 },
        inline_as {
           return (undef, "($_ % 2 == 0)");
        };

  Returning a list like this is considered experimental, is not tested very
  much, and I offer no guarantees that it will necessarily work with
  Moose/Mouse/Moo.

  =item C<< class_type $name, { class => $package, %options } >>

  =item C<< class_type { class => $package, %options } >>

  =item C<< class_type $name >>

  Shortcut for declaring a L<Type::Tiny::Class> type constraint.

  If C<< $package >> is omitted, is assumed to be the same as C<< $name >>.
  If C<< $name >> contains "::" (which would be an invalid name as far as
  L<Type::Tiny> is concerned), this will be removed.

  So for example, C<< class_type("Foo::Bar") >> declares a L<Type::Tiny::Class>
  type constraint named "FooBar" which constrains values to objects blessed
  into the "Foo::Bar" package.

  =item C<< role_type $name, { role => $package, %options } >>

  =item C<< role_type { role => $package, %options } >>

  =item C<< role_type $name >>

  Shortcut for declaring a L<Type::Tiny::Role> type constraint.

  If C<< $package >> is omitted, is assumed to be the same as C<< $name >>.
  If C<< $name >> contains "::" (which would be an invalid name as far as
  L<Type::Tiny> is concerned), this will be removed.

  =item C<< duck_type $name, \@methods >>

  =item C<< duck_type \@methods >>

  Shortcut for declaring a L<Type::Tiny::Duck> type constraint.

  =item C<< union $name, \@constraints >>

  =item C<< union \@constraints >>

  Shortcut for declaring a L<Type::Tiny::Union> type constraint.

  =item C<< enum $name, \@values >>

  =item C<< enum \@values >>

  Shortcut for declaring a L<Type::Tiny::Enum> type constraint.

  =item C<< intersection $name, \@constraints >>

  =item C<< intersection \@constraints >>

  Shortcut for declaring a L<Type::Tiny::Intersection> type constraint.

  =back

  =head2 Coercion declaration functions

  Many of the following are similar to the similarly named functions described
  in L<Moose::Util::TypeConstraints>.

  =over

  =item C<< coerce $target, @coercions >>

  Add coercions to the target type constraint. The list of coercions is a
  list of type constraint, conversion code pairs. Conversion code can be
  either a string of Perl code or a coderef; in either case the value to
  be converted is C<< $_ >>.

  =item C<< from $source >>

  Sugar to specify a type constraint in a list of coercions:

     coerce EvenInt, from Int, via { $_ * 2 };  # As a coderef...
     coerce EvenInt, from Int, q { $_ * 2 };    # or as a string!

  =item C<< via { BLOCK } >>

  Sugar to specify a coderef in a list of coercions.

  =item C<< declare_coercion $name, \%opts, $type1, $code1, ... >>

  =item C<< declare_coercion \%opts, $type1, $code1, ... >>

  Declares a coercion that is not explicitly attached to any type in the
  library. For example:

     declare_coercion "ArrayRefFromAny", from "Any", via { [$_] };

  This coercion will be exportable from the library as a L<Type::Coercion>
  object, but the ArrayRef type exported by the library won't automatically
  use it.

  Coercions declared this way are immutable (frozen).

  =item C<< to_type $type >>

  Used with C<declare_coercion> to declare the target type constraint for
  a coercion, but still without explicitly attaching the coercion to the
  type constraint:

     declare_coercion "ArrayRefFromAny",
        to_type "ArrayRef",
        from "Any", via { [$_] };

  You should pretty much always use this when declaring an unattached
  coercion because it's exceedingly useful for a type coercion to know what
  it will coerce to - this allows it to skip coercion when no coercion is
  needed (e.g. avoiding coercing C<< [] >> to C<< [ [] ] >>) and allows
  C<assert_coerce> to work properly.

  =back

  =head2 Type library management

  =over

  =item C<< extends @libraries >>

  Indicates that this type library extends other type libraries, importing
  their type constraints.

  Should usually be executed in a C<< BEGIN >> block.

  This is not exported by default because it's not fun to export it to Moo,
  Moose or Mouse classes! C<< use Type::Utils -all >> can be used to import
  it into your type library.

  =back

  =head2 Other

  =over

  =item C<< match_on_type $value => ($type => \&action, ..., \&default?) >>

  Something like a C<switch>/C<case> or C<given>/C<when> construct. Dispatches
  along different code paths depending on the type of the incoming value.
  Example blatantly stolen from the Moose documentation:

     sub to_json
     {
        my $value = shift;

        return match_on_type $value => (
           HashRef() => sub {
              my $hash = shift;
              '{ '
                 . (
                 join ", " =>
                 map { '"' . $_ . '" : ' . to_json( $hash->{$_} ) }
                 sort keys %$hash
              ) . ' }';
           },
           ArrayRef() => sub {
              my $array = shift;
              '[ '.( join ", " => map { to_json($_) } @$array ).' ]';
           },
           Num()   => q {$_},
           Str()   => q { '"' . $_ . '"' },
           Undef() => q {'null'},
           => sub { die "$_ is not acceptable json type" },
        );
     }

  Note that unlike Moose, code can be specified as a string instead of a
  coderef. (e.g. for C<Num>, C<Str> and C<Undef> above.)

  For improved performance, try C<compile_match_on_type>.

  This function is not exported by default.

  =item C<< my $coderef = compile_match_on_type($type => \&action, ..., \&default?) >>

  Compile a C<match_on_type> block into a coderef. The following JSON
  converter is about two orders of magnitude faster than the previous
  example:

     sub to_json;
     *to_json = compile_match_on_type(
        HashRef() => sub {
           my $hash = shift;
           '{ '
              . (
              join ", " =>
              map { '"' . $_ . '" : ' . to_json( $hash->{$_} ) }
              sort keys %$hash
           ) . ' }';
        },
        ArrayRef() => sub {
           my $array = shift;
           '[ '.( join ", " => map { to_json($_) } @$array ).' ]';
        },
        Num()   => q {$_},
        Str()   => q { '"' . $_ . '"' },
        Undef() => q {'null'},
        => sub { die "$_ is not acceptable json type" },
     );

  Remember to store the coderef somewhere fairly permanent so that you
  don't compile it over and over. C<state> variables (in Perl >= 5.10)
  are good for this. (Same sort of idea as L<Type::Params>.)

  This function is not exported by default.

  =item C<< my $coderef = classifier(@types) >>

  Returns a coderef that can be used to classify values according to their
  type constraint. The coderef, when passed a value, returns a type
  constraint which the value satisfies.

     use feature qw( say );
     use Type::Utils qw( classifier );
     use Types::Standard qw( Int Num Str Any );

     my $classifier = classifier(Str, Int, Num, Any);

     say $classifier->( "42"  )->name;   # Int
     say $classifier->( "4.2" )->name;   # Num
     say $classifier->( []    )->name;   # Any

  Note that, for example, "42" satisfies Int, but it would satisfy the
  type constraints Num, Str, and Any as well. In this case, the
  classifier has picked the most specific type constraint that "42"
  satisfies.

  If no type constraint is satisfied by the value, then the classifier
  will return undef.

  =item C<< dwim_type($string, %options) >>

  Given a string like "ArrayRef[Int|CodeRef]", turns it into a type constraint
  object, hopefully doing what you mean.

  It uses the syntax of L<Type::Parser>. Firstly the L<Type::Registry>
  for the caller package is consulted; if that doesn't have a match,
  L<Types::Standard> is consulted for type constraint names; and if
  there's still no match, then if a type constraint looks like a class
  name, a new L<Type::Tiny::Class> object is created for it.

  Somewhere along the way, it also checks Moose/Mouse's type constraint
  registries if they are loaded.

  You can specify an alternative for the caller using the C<for> option.
  If you'd rather create a L<Type::Tiny::Role> object, set the C<does>
  option to true.

     # An arrayref of objects, each of which must do role Foo.
     my $type = dwim_type("ArrayRef[Foo]", does => 1);

     Type::Registry->for_me->add_types("-Standard");
     Type::Registry->for_me->alias_type("Int" => "Foo");

     # An arrayref of integers.
     my $type = dwim_type("ArrayRef[Foo]", does => 1);

  While it's probably better overall to use the proper L<Type::Registry>
  interface for resolving type constraint strings, this function often does
  what you want.

  It should never die if it fails to find a type constraint (but may die
  if the type constraint string is syntactically malformed), preferring to
  return undef.

  This function is not exported by default.

  =item C<< english_list(\$conjunction, @items) >>

  Joins the items with commas, placing a conjunction before the final item.
  The conjunction is optional, defaulting to "and".

     english_list(qw/foo bar baz/);       # "foo, bar, and baz"
     english_list(\"or", qw/quux quuux/); # "quux or quuux"

  This function is not exported by default.

  =back

  =head1 EXPORT

  By default, all of the functions documented above are exported, except
  C<subtype> and C<type> (prefer C<declare> instead), C<extends>, C<dwim_type>,
  C<match_on_type>/C<compile_match_on_type>, C<classifier>, and
  C<english_list>.

  This module uses L<Exporter::Tiny>; see the documentation of that module
  for tips and tricks importing from Type::Utils.

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Type::Tiny::Manual>.

  L<Type::Tiny>, L<Type::Library>, L<Types::Standard>, L<Type::Coercion>.

  L<Type::Tiny::Class>, L<Type::Tiny::Role>, L<Type::Tiny::Duck>,
  L<Type::Tiny::Enum>, L<Type::Tiny::Union>.

  L<Moose::Util::TypeConstraints>,
  L<Mouse::Util::TypeConstraints>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

TYPE_UTILS

$fatpacked{"Types/Common/Numeric.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TYPES_COMMON_NUMERIC';
  package Types::Common::Numeric;

  use 5.006001;
  use strict;
  use warnings;

  BEGIN {
  	if ($] < 5.008) { require Devel::TypeTiny::Perl56Compat };
  }

  BEGIN {
  	$Types::Common::Numeric::AUTHORITY = 'cpan:TOBYINK';
  	$Types::Common::Numeric::VERSION   = '1.000005';
  }

  use Type::Library -base, -declare => qw(
  	PositiveNum PositiveOrZeroNum
  	PositiveInt PositiveOrZeroInt
  	NegativeNum NegativeOrZeroNum
  	NegativeInt NegativeOrZeroInt
  	SingleDigit
  );

  use Type::Tiny ();
  use Types::Standard qw( Num Int );

  my $meta = __PACKAGE__->meta;

  $meta->add_type(
  	name       => 'PositiveNum',
  	parent     => Num,
  	constraint => sub { $_ > 0 },
  	inlined    => sub { undef, qq($_ > 0) },
  	message    => sub { "Must be a positive number" },
  );

  $meta->add_type(
  	name       => 'PositiveOrZeroNum',
  	parent     => Num,
  	constraint => sub { $_ >= 0 },
  	inlined    => sub { undef, qq($_ >= 0) },
  	message    => sub { "Must be a number greater than or equal to zero" },
  );

  my ($pos_int, $posz_int);
  if (Type::Tiny::_USE_XS) {
  	$pos_int  = Type::Tiny::XS::get_coderef_for('PositiveInt');
  	$posz_int = Type::Tiny::XS::get_coderef_for('PositiveOrZeroInt');
  }

  $meta->add_type(
  	name       => 'PositiveInt',
  	parent     => Int,
  	constraint => sub { $_ > 0 },
  	inlined    => sub {
  		if ($pos_int) {
  			my $xsub = Type::Tiny::XS::get_subname_for($_[0]->name);
  			return "$xsub($_[1])" if $xsub;
  		}
  		undef, qq($_ > 0);
  	},
  	message    => sub { "Must be a positive integer" },
  	$pos_int ? ( compiled_type_constraint => $pos_int ) : (),
  );

  $meta->add_type(
  	name       => 'PositiveOrZeroInt',
  	parent     => Int,
  	constraint => sub { $_ >= 0 },
  	inlined    => sub {
  		if ($posz_int) {
  			my $xsub = Type::Tiny::XS::get_subname_for($_[0]->name);
  			return "$xsub($_[1])" if $xsub;
  		}
  		undef, qq($_ >= 0);
  	},
  	message    => sub { "Must be an integer greater than or equal to zero" },
  	$posz_int ? ( compiled_type_constraint => $posz_int ) : (),
  );

  $meta->add_type(
  	name       => 'NegativeNum',
  	parent     => Num,
  	constraint => sub { $_ < 0 },
  	inlined    => sub { undef, qq($_ < 0) },
  	message    => sub { "Must be a negative number" },
  );

  $meta->add_type(
  	name       => 'NegativeOrZeroNum',
  	parent     => Num,
  	constraint => sub { $_ <= 0 },
  	inlined    => sub { undef, qq($_ <= 0) },
  	message    => sub { "Must be a number less than or equal to zero" },
  );

  $meta->add_type(
  	name       => 'NegativeInt',
  	parent     => Int,
  	constraint => sub { $_ < 0 },
  	inlined    => sub { undef, qq($_ < 0) },
  	message    => sub { "Must be a negative integer" },
  );

  $meta->add_type(
  	name       => 'NegativeOrZeroInt',
  	parent     => Int,
  	constraint => sub { $_ <= 0 },
  	inlined    => sub { undef, qq($_ <= 0) },
  	message    => sub { "Must be an integer less than or equal to zero" },
  );

  $meta->add_type(
  	name       => 'SingleDigit',
  	parent     => Int,
  	constraint => sub { $_ >= -9 and $_ <= 9 },
  	inlined    => sub { undef, qq($_ >= -9), qq($_ <= 9) },
  	message    => sub { "Must be a single digit" },
  );

  __PACKAGE__->meta->make_immutable;

  1;

  __END__

  =pod

  =encoding utf-8

  =head1 NAME

  Types::Common::Numeric - drop-in replacement for MooseX::Types::Common::Numeric

  =head1 STATUS

  This module is covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  A drop-in replacement for L<MooseX::Types::Common::Numeric>.

  =head2 Types

  The following types are similar to those described in
  L<MooseX::Types::Common::Numeric>.

  =over

  =item C<PositiveNum>

  =item C<PositiveOrZeroNum>

  =item C<PositiveInt>

  =item C<PositiveOrZeroInt>

  =item C<NegativeNum>

  =item C<NegativeOrZeroNum>

  =item C<NegativeInt>

  =item C<NegativeOrZeroInt>

  =item C<SingleDigit>

  =back

  C<SingleDigit> interestingly accepts the numbers -9 to -1; not
  just 0 to 9.

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Types::Standard>, L<Types::Common::String>.

  L<MooseX::Types::Common>,
  L<MooseX::Types::Common::Numeric>,
  L<MooseX::Types::Common::String>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

TYPES_COMMON_NUMERIC

$fatpacked{"Types/Common/String.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TYPES_COMMON_STRING';
  package Types::Common::String;

  use 5.006001;
  use strict;
  use warnings;
  use utf8;

  BEGIN {
  	if ($] < 5.008) { require Devel::TypeTiny::Perl56Compat };
  }

  BEGIN {
  	$Types::Common::String::AUTHORITY = 'cpan:TOBYINK';
  	$Types::Common::String::VERSION   = '1.000005';
  }

  use Type::Library -base, -declare => qw(
  	SimpleStr
  	NonEmptySimpleStr
  	NumericCode
  	LowerCaseSimpleStr
  	UpperCaseSimpleStr
  	Password
  	StrongPassword
  	NonEmptyStr
  	LowerCaseStr
  	UpperCaseStr
  );

  use Type::Tiny ();
  use Types::Standard qw( Str );

  my $meta = __PACKAGE__->meta;

  $meta->add_type(
  	name       => SimpleStr,
  	parent     => Str,
  	constraint => sub { length($_) <= 255 and not /\n/ },
  	inlined    => sub { undef, qq(length($_) <= 255), qq($_ !~ /\\n/) },
  	message    => sub { "Must be a single line of no more than 255 chars" },
  );

  $meta->add_type(
  	name       => NonEmptySimpleStr,
  	parent     => SimpleStr,
  	constraint => sub { length($_) > 0 },
  	inlined    => sub { undef, qq(length($_) > 0) },
  	message    => sub { "Must be a non-empty single line of no more than 255 chars" },
  );

  $meta->add_type(
  	name       => NumericCode,
  	parent     => NonEmptySimpleStr,
  	constraint => sub { /^[0-9]+$/ },
  	inlined    => sub { SimpleStr->inline_check($_), qq($_ =~ m/^[0-9]+\$/) },
  	message    => sub {
  		'Must be a non-empty single line of no more than 255 chars that consists '
  			. 'of numeric characters only'
  	},
  );

  NumericCode->coercion->add_type_coercions(
  	NonEmptySimpleStr, q[ do { (my $code = $_) =~ s/[[:punct:]]//g; $code } ],
  );

  $meta->add_type(
  	name       => Password,
  	parent     => NonEmptySimpleStr,
  	constraint => sub { length($_) > 3 },
  	inlined    => sub { SimpleStr->inline_check($_), qq(length($_) > 3) },
  	message    => sub { "Must be between 4 and 255 chars" },
  );

  $meta->add_type(
  	name       => StrongPassword,
  	parent     => Password,
  	constraint => sub { length($_) > 7 and /[^a-zA-Z]/ },
  	inlined    => sub { SimpleStr()->inline_check($_), qq(length($_) > 7), qq($_ =~ /[^a-zA-Z]/) },
  	message    => sub { "Must be between 8 and 255 chars, and contain a non-alpha char" },
  );

  my ($nestr);
  if (Type::Tiny::_USE_XS) {
  	$nestr = Type::Tiny::XS::get_coderef_for('NonEmptyStr');
  }

  $meta->add_type(
  	name       => NonEmptyStr,
  	parent     => Str,
  	constraint => sub { length($_) > 0 },
  	inlined    => sub {
  		if ($nestr) {
  			my $xsub = Type::Tiny::XS::get_subname_for($_[0]->name);
  			return "$xsub($_[1])" if $xsub;
  		}
  		undef, qq(length($_) > 0);
  	},
  	message    => sub { "Must not be empty" },
  	$nestr ? ( compiled_type_constraint => $nestr ) : (),
  );

  $meta->add_type(
  	name       => LowerCaseStr,
  	parent     => NonEmptyStr,
  	constraint => sub { !/\p{Upper}/ms },
  	inlined    => sub { undef, qq($_ !~ /\\p{Upper}/ms) },
  	message    => sub { "Must not contain upper case letters" },
  );

  LowerCaseStr->coercion->add_type_coercions(
  	NonEmptyStr, q[ lc($_) ],
  );

  $meta->add_type(
  	name       => UpperCaseStr,
  	parent     => NonEmptyStr,
  	constraint => sub { !/\p{Lower}/ms },
  	inlined    => sub { undef, qq($_ !~ /\\p{Lower}/ms) },
  	message    => sub { "Must not contain lower case letters" },
  );

  UpperCaseStr->coercion->add_type_coercions(
  	NonEmptyStr, q[ uc($_) ],
  );

  $meta->add_type(
  	name       => LowerCaseSimpleStr,
  	parent     => NonEmptySimpleStr,
  	constraint => sub { !/\p{Upper}/ms },
  	inlined    => sub { undef, qq($_ !~ /\\p{Upper}/ms) },
  	message    => sub { "Must not contain pper case letters" },
  );

  LowerCaseSimpleStr->coercion->add_type_coercions(
  	NonEmptySimpleStr, q[ lc($_) ],
  );

  $meta->add_type(
  	name       => UpperCaseSimpleStr,
  	parent     => NonEmptySimpleStr,
  	constraint => sub { !/\p{Lower}/ms },
  	inlined    => sub { undef, qq($_ !~ /\\p{Lower}/ms) },
  	message    => sub { "Must not contain lower case letters" },
  );

  UpperCaseSimpleStr->coercion->add_type_coercions(
  	NonEmptySimpleStr, q[ uc($_) ],
  );

  __PACKAGE__->meta->make_immutable;

  1;

  __END__

  =pod

  =encoding utf-8

  =head1 NAME

  Types::Common::String - drop-in replacement for MooseX::Types::Common::String

  =head1 STATUS

  This module is covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  A drop-in replacement for L<MooseX::Types::Common::String>.

  =head2 Types

  The following types are similar to those described in
  L<MooseX::Types::Common::String>.

  =over

  =item C<SimpleStr>

  =item C<NonEmptySimpleStr>

  =item C<NumericCode>

  =item C<LowerCaseSimpleStr>

  =item C<UpperCaseSimpleStr>

  =item C<Password>

  =item C<StrongPassword>

  =item C<NonEmptyStr>

  =item C<LowerCaseStr>

  =item C<UpperCaseStr>

  =back

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Types::Standard>, L<Types::Common::Numeric>.

  L<MooseX::Types::Common>,
  L<MooseX::Types::Common::Numeric>,
  L<MooseX::Types::Common::String>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

TYPES_COMMON_STRING

$fatpacked{"Types/Standard.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TYPES_STANDARD';
  package Types::Standard;

  use 5.006001;
  use strict;
  use warnings;

  BEGIN {
  	eval { require re };
  	if ($] < 5.008) { require Devel::TypeTiny::Perl56Compat };
  	if ($] < 5.010) { require Devel::TypeTiny::Perl58Compat };
  }

  BEGIN {
  	$Types::Standard::AUTHORITY = 'cpan:TOBYINK';
  	$Types::Standard::VERSION   = '1.000005';
  }

  use Type::Library -base;

  our @EXPORT_OK = qw( slurpy );

  use Scalar::Util qw( blessed looks_like_number );
  use Type::Tiny ();
  use Types::TypeTiny ();

  BEGIN {
  	*_is_class_loaded = Type::Tiny::_USE_XS
  		? \&Type::Tiny::XS::Util::is_class_loaded
  		: sub {
  			return !!0 if ref $_[0];
  			return !!0 if not $_[0];
  			my $stash = do { no strict 'refs'; \%{"$_[0]\::"} };
  			return !!1 if exists $stash->{'ISA'};
  			return !!1 if exists $stash->{'VERSION'};
  			foreach my $globref (values %$stash) {
  				return !!1 if *{$globref}{CODE};
  			}
  			return !!0;
  		};
  };

  my $add_core_type = sub {
  	my $meta = shift;
  	my ($typedef) = @_;

  	my $name = $typedef->{name};
  	my ($xsub, $xsubname);

  	# We want Map and Tuple to be XSified, even if they're not
  	# really core.
  	$typedef->{_is_core} = 1
  		unless $name eq 'Map' || $name eq 'Tuple';

  	if ( Type::Tiny::_USE_XS
  	and not ($name eq 'RegexpRef') ) {
  		$xsub     = Type::Tiny::XS::get_coderef_for($name);
  		$xsubname = Type::Tiny::XS::get_subname_for($name);
  	}

  	elsif ( Type::Tiny::_USE_MOUSE
  	and not ($name eq 'RegexpRef' or $name eq 'Int' or $name eq 'Object') ) {
  		require Mouse::Util::TypeConstraints;
  		$xsub     = "Mouse::Util::TypeConstraints"->can($name);
  		$xsubname = "Mouse::Util::TypeConstraints::$name" if $xsub;
  	}

  	$typedef->{compiled_type_constraint} = $xsub if $xsub;

  	$typedef->{inlined} = sub { "$xsubname\($_[1])" }
  		if defined($xsubname) and (
  			# These should be faster than their normal inlined
  			# equivalents
  			$name eq 'Str' or
  			$name eq 'Bool' or
  			$name eq 'ClassName' or
  			$name eq 'RegexpRef' or
  			$name eq 'FileHandle'
  		);

  	$meta->add_type($typedef);
  };

  sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }

  my $meta = __PACKAGE__->meta;

  # Stringable and LazyLoad are optimizations that complicate
  # this module somewhat, but they have led to performance
  # improvements. If Types::Standard wasn't such a key type
  # library, I wouldn't use them. I strongly discourage anybody
  # from using them in their own code. If you're looking for
  # examples of how to write a type library sanely, you're
  # better off looking at the code for Types::Common::Numeric
  # and Types::Common::String.

  sub Stringable (&)
  {
  	package #private
  	Types::Standard::_Stringable;
  	use overload q[""] => sub { $_[0]{text} ||= $_[0]{code}->() }, fallback => 1;
  	bless +{ code => $_[0] };
  }

  sub LazyLoad ($$)
  {
  	package #private
  	Types::Standard::LazyLoad;
  	use overload fallback => 1, q[&{}] => sub {
  		my ($typename, $function) = @{$_[0]};
  		my $type  = $meta->get_type($typename);
  		my $class = "Types::Standard::$typename";
  		eval "require $class; 1" or die($@);
  		# Majorly break encapsulation for Type::Tiny :-O
  		for my $key (keys %$type)
  		{
  			next unless ref($type->{$key}) eq __PACKAGE__;
  			my $f = $type->{$key}[1];
  			$type->{$key} = $class->can("__$f");
  		}
  		return $class->can("__$function");
  	};
  	bless \@_;
  }

  no warnings;

  BEGIN { *STRICTNUM = $ENV{PERL_TYPES_STANDARD_STRICTNUM} ? sub(){!!1} : sub(){!!0} };

  my $_any = $meta->$add_core_type({
  	name       => "Any",
  	inlined    => sub { "!!1" },
  });

  my $_item = $meta->$add_core_type({
  	name       => "Item",
  	inlined    => sub { "!!1" },
  	parent     => $_any,
  });

  $meta->$add_core_type({
  	name       => "Bool",
  	parent     => $_item,
  	constraint => sub { !defined $_ or $_ eq q() or $_ eq '0' or $_ eq '1' },
  	inlined    => sub { "!defined $_[1] or $_[1] eq q() or $_[1] eq '0' or $_[1] eq '1'" },
  });

  my $_undef = $meta->$add_core_type({
  	name       => "Undef",
  	parent     => $_item,
  	constraint => sub { !defined $_ },
  	inlined    => sub { "!defined($_[1])" },
  });

  my $_def = $meta->$add_core_type({
  	name       => "Defined",
  	parent     => $_item,
  	constraint => sub { defined $_ },
  	inlined    => sub { "defined($_[1])" },
  });

  my $_val = $meta->$add_core_type({
  	name       => "Value",
  	parent     => $_def,
  	constraint => sub { not ref $_ },
  	inlined    => sub { "defined($_[1]) and not ref($_[1])" },
  });

  my $_str = $meta->$add_core_type({
  	name       => "Str",
  	parent     => $_val,
  	constraint => sub { ref(\$_) eq 'SCALAR' or ref(\(my $val = $_)) eq 'SCALAR' },
  	inlined    => sub {
  		"defined($_[1]) and do { ref(\\$_[1]) eq 'SCALAR' or ref(\\(my \$val = $_[1])) eq 'SCALAR' }"
  	},
  });

  my $_laxnum = $meta->add_type({
  	name       => "LaxNum",
  	parent     => $_str,
  	constraint => sub { looks_like_number $_ },
  	inlined    => sub { "defined($_[1]) && !ref($_[1]) && Scalar::Util::looks_like_number($_[1])" },
  });

  my $_strictnum = $meta->add_type({
  	name       => "StrictNum",
  	parent     => $_str,
  	constraint => sub {
  		my $val = $_;
  		($val =~ /\A[+-]?[0-9]+\z/) ||
  		( $val =~ /\A(?:[+-]?)                #matches optional +- in the beginning
  		(?=[0-9]|\.[0-9])                     #matches previous +- only if there is something like 3 or .3
  		[0-9]*                                #matches 0-9 zero or more times
  		(?:\.[0-9]+)?                         #matches optional .89 or nothing
  		(?:[Ee](?:[+-]?[0-9]+))?              #matches E1 or e1 or e-1 or e+1 etc
  		\z/x );
  	},
  	inlined    => sub {
  		'my $val = '.$_[1].';'.
  		Value()->inline_check('$val')
  		.' && ( $val =~ /\A[+-]?[0-9]+\z/ || '
  		. '$val =~ /\A(?:[+-]?)              # matches optional +- in the beginning
  			(?=[0-9]|\.[0-9])                 # matches previous +- only if there is something like 3 or .3
  			[0-9]*                            # matches 0-9 zero or more times
  			(?:\.[0-9]+)?                     # matches optional .89 or nothing
  			(?:[Ee](?:[+-]?[0-9]+))?          # matches E1 or e1 or e-1 or e+1 etc
  		\z/x ); '
  	},
  });

  my $_num = $meta->add_type({
  	name       => "Num",
  	parent     => (STRICTNUM ? $_strictnum : $_laxnum),
  });

  $meta->$add_core_type({
  	name       => "Int",
  	parent     => $_num,
  	constraint => sub { /\A-?[0-9]+\z/ },
  	inlined    => sub { "defined $_[1] and $_[1] =~ /\\A-?[0-9]+\\z/" },
  });

  my $_classn = $meta->add_type({
  	name       => "ClassName",
  	parent     => $_str,
  	constraint => \&_is_class_loaded,
  	inlined    => sub { "Types::Standard::_is_class_loaded(do { my \$tmp = $_[1] })" },
  });

  $meta->add_type({
  	name       => "RoleName",
  	parent     => $_classn,
  	constraint => sub { not $_->can("new") },
  	inlined    => sub { "Types::Standard::_is_class_loaded(do { my \$tmp = $_[1] }) and not $_[1]\->can('new')" },
  });

  my $_ref = $meta->$add_core_type({
  	name       => "Ref",
  	parent     => $_def,
  	constraint => sub { ref $_ },
  	inlined    => sub { "!!ref($_[1])" },
  	constraint_generator => sub
  	{
  		return $meta->get_type('Ref') unless @_;

  		my $reftype = shift;
  		Types::TypeTiny::StringLike->check($reftype)
  			or _croak("Parameter to Ref[`a] expected to be string; got $reftype");

  		$reftype = "$reftype";
  		return sub {
  			ref($_[0]) and Scalar::Util::reftype($_[0]) eq $reftype;
  		}
  	},
  	inline_generator => sub
  	{
  		my $reftype = shift;
  		return sub {
  			my $v = $_[1];
  			"ref($v) and Scalar::Util::reftype($v) eq q($reftype)";
  		};
  	},
  	deep_explanation => sub {
  		require B;
  		my ($type, $value, $varname) = @_;
  		my $param = $type->parameters->[0];
  		return if $type->check($value);
  		my $reftype = Scalar::Util::reftype($value);
  		return [
  			sprintf('"%s" constrains reftype(%s) to be equal to %s', $type, $varname, B::perlstring($param)),
  			sprintf('reftype(%s) is %s', $varname, defined($reftype) ? B::perlstring($reftype) : "undef"),
  		];
  	},
  });

  $meta->$add_core_type({
  	name       => "CodeRef",
  	parent     => $_ref,
  	constraint => sub { ref $_ eq "CODE" },
  	inlined    => sub { "ref($_[1]) eq 'CODE'" },
  });

  $meta->$add_core_type({
  	name       => "RegexpRef",
  	parent     => $_ref,
  	constraint => sub { ref($_) && !!re::is_regexp($_) },
  	inlined    => sub { "ref($_[1]) && !!re::is_regexp($_[1])" },
  });

  $meta->$add_core_type({
  	name       => "GlobRef",
  	parent     => $_ref,
  	constraint => sub { ref $_ eq "GLOB" },
  	inlined    => sub { "ref($_[1]) eq 'GLOB'" },
  });

  $meta->$add_core_type({
  	name       => "FileHandle",
  	parent     => $_ref,
  	constraint => sub {
  		(ref($_) eq "GLOB" && Scalar::Util::openhandle($_))
  		or (blessed($_) && $_->isa("IO::Handle"))
  	},
  	inlined    => sub {
  		"(ref($_[1]) eq \"GLOB\" && Scalar::Util::openhandle($_[1])) ".
  		"or (Scalar::Util::blessed($_[1]) && $_[1]\->isa(\"IO::Handle\"))"
  	},
  });

  my $_arr = $meta->$add_core_type({
  	name       => "ArrayRef",
  	parent     => $_ref,
  	constraint => sub { ref $_ eq "ARRAY" },
  	inlined    => sub { "ref($_[1]) eq 'ARRAY'" },
  	constraint_generator => LazyLoad(ArrayRef => 'constraint_generator'),
  	inline_generator     => LazyLoad(ArrayRef => 'inline_generator'),
  	deep_explanation     => LazyLoad(ArrayRef => 'deep_explanation'),
  	coercion_generator   => LazyLoad(ArrayRef => 'coercion_generator'),
  });

  my $_hash = $meta->$add_core_type({
  	name       => "HashRef",
  	parent     => $_ref,
  	constraint => sub { ref $_ eq "HASH" },
  	inlined    => sub { "ref($_[1]) eq 'HASH'" },
  	constraint_generator => LazyLoad(HashRef => 'constraint_generator'),
  	inline_generator     => LazyLoad(HashRef => 'inline_generator'),
  	deep_explanation     => LazyLoad(HashRef => 'deep_explanation'),
  	coercion_generator   => LazyLoad(HashRef => 'coercion_generator'),
  	my_methods => {
  		hashref_allows_key => sub {
  			my $self = shift;
  			Str()->check($_[0]);
  		},
  		hashref_allows_value => sub {
  			my $self = shift;
  			my ($key, $value) = @_;

  			return !!0 unless $self->my_hashref_allows_key($key);
  			return !!1 if $self==HashRef();

  			my $href  = $self->find_parent(sub { $_->has_parent && $_->parent==HashRef() });
  			my $param = $href->type_parameter;

  			Str()->check($key) and $param->check($value);
  		},
  	},
  });

  $meta->$add_core_type({
  	name       => "ScalarRef",
  	parent     => $_ref,
  	constraint => sub { ref $_ eq "SCALAR" or ref $_ eq "REF" },
  	inlined    => sub { "ref($_[1]) eq 'SCALAR' or ref($_[1]) eq 'REF'" },
  	constraint_generator => LazyLoad(ScalarRef => 'constraint_generator'),
  	inline_generator     => LazyLoad(ScalarRef => 'inline_generator'),
  	deep_explanation     => LazyLoad(ScalarRef => 'deep_explanation'),
  	coercion_generator   => LazyLoad(ScalarRef => 'coercion_generator'),
  });

  my $_obj = $meta->$add_core_type({
  	name       => "Object",
  	parent     => $_ref,
  	constraint => sub { blessed $_ },
  	inlined    => sub { "Scalar::Util::blessed($_[1])" },
  });

  $meta->$add_core_type({
  	name       => "Maybe",
  	parent     => $_item,
  	constraint_generator => sub
  	{
  		return $meta->get_type('Maybe') unless @_;

  		my $param = Types::TypeTiny::to_TypeTiny(shift);
  		Types::TypeTiny::TypeTiny->check($param)
  			or _croak("Parameter to Maybe[`a] expected to be a type constraint; got $param");

  		my $param_compiled_check = $param->compiled_check;
  		my @xsub;
  		if (Type::Tiny::_USE_XS)
  		{
  			my $paramname = Type::Tiny::XS::is_known($param_compiled_check);
  			push @xsub, Type::Tiny::XS::get_coderef_for("Maybe[$paramname]")
  				if $paramname;
  		}
  		elsif (Type::Tiny::_USE_MOUSE and $param->_has_xsub)
  		{
  			require Mouse::Util::TypeConstraints;
  			my $maker = "Mouse::Util::TypeConstraints"->can("_parameterize_Maybe_for");
  			push @xsub, $maker->($param) if $maker;
  		}

  		return(
  			sub
  			{
  				my $value = shift;
  				return !!1 unless defined $value;
  				return $param->check($value);
  			},
  			@xsub,
  		);
  	},
  	inline_generator => sub {
  		my $param = shift;

  		my $param_compiled_check = $param->compiled_check;
  		if (Type::Tiny::_USE_XS)
  		{
  			my $paramname = Type::Tiny::XS::is_known($param_compiled_check);
  			my $xsubname  = Type::Tiny::XS::get_subname_for("Maybe[$paramname]");
  			return sub { "$xsubname\($_[1]\)" } if $xsubname;
  		}

  		return unless $param->can_be_inlined;
  		return sub {
  			my $v = $_[1];
  			my $param_check = $param->inline_check($v);
  			"!defined($v) or $param_check";
  		};
  	},
  	deep_explanation => sub {
  		my ($type, $value, $varname) = @_;
  		my $param = $type->parameters->[0];

  		return [
  			sprintf('%s is defined', Type::Tiny::_dd($value)),
  			sprintf('"%s" constrains the value with "%s" if it is defined', $type, $param),
  			@{ $param->validate_explain($value, $varname) },
  		];
  	},
  	coercion_generator => sub
  	{
  		my ($parent, $child, $param) = @_;
  		return unless $param->has_coercion;
  		return $param->coercion;
  	},
  });

  my $_map = $meta->$add_core_type({
  	name       => "Map",
  	parent     => $_hash,
  	constraint_generator => LazyLoad(Map => 'constraint_generator'),
  	inline_generator     => LazyLoad(Map => 'inline_generator'),
  	deep_explanation     => LazyLoad(Map => 'deep_explanation'),
  	coercion_generator   => LazyLoad(Map => 'coercion_generator'),
  	my_methods => {
  		hashref_allows_key => sub {
  			my $self = shift;
  			my ($key) = @_;

  			return Str()->check($key) if $self==Map();

  			my $map = $self->find_parent(sub { $_->has_parent && $_->parent==Map() });
  			my ($kcheck, $vcheck) = @{ $map->parameters };

  			($kcheck or Any())->check($key);
  		},
  		hashref_allows_value => sub {
  			my $self = shift;
  			my ($key, $value) = @_;

  			return !!0 unless $self->my_hashref_allows_key($key);
  			return !!1 if $self==Map();

  			my $map = $self->find_parent(sub { $_->has_parent && $_->parent==Map() });
  			my ($kcheck, $vcheck) = @{ $map->parameters };

  			($kcheck or Any())->check($key)
  				and ($vcheck or Any())->check($value);
  		},
  	},
  });

  my $_Optional = $meta->add_type({
  	name       => "Optional",
  	parent     => $_item,
  	constraint_generator => sub
  	{
  		return $meta->get_type('Optional') unless @_;

  		my $param = Types::TypeTiny::to_TypeTiny(shift);
  		Types::TypeTiny::TypeTiny->check($param)
  			or _croak("Parameter to Optional[`a] expected to be a type constraint; got $param");

  		sub { $param->check($_[0]) }
  	},
  	inline_generator => sub {
  		my $param = shift;
  		return unless $param->can_be_inlined;
  		return sub {
  			my $v = $_[1];
  			$param->inline_check($v);
  		};
  	},
  	deep_explanation => sub {
  		my ($type, $value, $varname) = @_;
  		my $param = $type->parameters->[0];

  		return [
  			sprintf('%s exists', $varname),
  			sprintf('"%s" constrains %s with "%s" if it exists', $type, $varname, $param),
  			@{ $param->validate_explain($value, $varname) },
  		];
  	},
  	coercion_generator => sub
  	{
  		my ($parent, $child, $param) = @_;
  		return unless $param->has_coercion;
  		return $param->coercion;
  	},
  });

  sub slurpy {
  	my $t = shift;
  	wantarray ? (+{ slurpy => $t }, @_) : +{ slurpy => $t };
  }

  $meta->$add_core_type({
  	name       => "Tuple",
  	parent     => $_arr,
  	name_generator => sub
  	{
  		my ($s, @a) = @_;
  		sprintf('%s[%s]', $s, join q[,], map { ref($_) eq "HASH" ? sprintf("slurpy %s", $_->{slurpy}) : $_ } @a);
  	},
  	constraint_generator => LazyLoad(Tuple => 'constraint_generator'),
  	inline_generator     => LazyLoad(Tuple => 'inline_generator'),
  	deep_explanation     => LazyLoad(Tuple => 'deep_explanation'),
  	coercion_generator   => LazyLoad(Tuple => 'coercion_generator'),
  });

  $meta->add_type({
  	name       => "Dict",
  	parent     => $_hash,
  	name_generator => sub
  	{
  		my ($s, @p) = @_;
  		my $l = ref($p[-1]) eq q(HASH) ? pop(@p)->{slurpy} : undef;
  		my %a = @p;
  		sprintf('%s[%s%s]', $s, join(q[,], map sprintf("%s=>%s", $_, $a{$_}), sort keys %a), $l ? ",slurpy $l" : '');
  	},
  	constraint_generator => LazyLoad(Dict => 'constraint_generator'),
  	inline_generator     => LazyLoad(Dict => 'inline_generator'),
  	deep_explanation     => LazyLoad(Dict => 'deep_explanation'),
  	coercion_generator   => LazyLoad(Dict => 'coercion_generator'),
  	my_methods => {
  		dict_is_slurpy => sub
  		{
  			my $self = shift;

  			return !!0 if $self==Dict();

  			my $dict = $self->find_parent(sub { $_->has_parent && $_->parent==Dict() });
  			ref($dict->parameters->[-1]) eq q(HASH)
  				? $dict->parameters->[-1]{slurpy}
  				: !!0
  		},
  		hashref_allows_key => sub
  		{
  			my $self = shift;
  			my ($key) = @_;

  			return Str()->check($key) if $self==Dict();

  			my $dict = $self->find_parent(sub { $_->has_parent && $_->parent==Dict() });
  			my %params;
  			my $slurpy = $dict->my_dict_is_slurpy;
  			if ($slurpy)
  			{
  				my @args = @{$dict->parameters};
  				pop @args;
  				%params = @args;
  			}
  			else
  			{
  				%params = @{ $dict->parameters }
  			}

  			return !!1
  				if exists($params{$key});
  			return !!0
  				if !$slurpy;
  			return Str()->check($key)
  				if $slurpy==Any() || $slurpy==Item() || $slurpy==Defined() || $slurpy==Ref();
  			return $slurpy->my_hashref_allows_key($key)
  				if $slurpy->is_a_type_of(HashRef());
  			return !!0;
  		},
  		hashref_allows_value => sub
  		{
  			my $self = shift;
  			my ($key, $value) = @_;

  			return !!0 unless $self->my_hashref_allows_key($key);
  			return !!1 if $self==Dict();

  			my $dict = $self->find_parent(sub { $_->has_parent && $_->parent==Dict() });
  			my %params;
  			my $slurpy = $dict->my_dict_is_slurpy;
  			if ($slurpy)
  			{
  				my @args = @{$dict->parameters};
  				pop @args;
  				%params = @args;
  			}
  			else
  			{
  				%params = @{ $dict->parameters }
  			}

  			return !!1
  				if exists($params{$key}) && $params{$key}->check($value);
  			return !!0
  				if !$slurpy;
  			return !!1
  				if $slurpy==Any() || $slurpy==Item() || $slurpy==Defined() || $slurpy==Ref();
  			return $slurpy->my_hashref_allows_value($key, $value)
  				if $slurpy->is_a_type_of(HashRef());
  			return !!0;
  		},
  	},
  });

  use overload ();
  $meta->add_type({
  	name       => "Overload",
  	parent     => $_obj,
  	constraint => sub { overload::Overloaded($_) },
  	inlined    => sub { "Scalar::Util::blessed($_[1]) and overload::Overloaded($_[1])" },
  	constraint_generator => sub
  	{
  		return $meta->get_type('Overload') unless @_;

  		my @operations = map {
  			Types::TypeTiny::StringLike->check($_)
  				? "$_"
  				: _croak("Parameters to Overload[`a] expected to be a strings; got $_");
  		} @_;

  		return sub {
  			my $value = shift;
  			for my $op (@operations) {
  				return unless overload::Method($value, $op);
  			}
  			return !!1;
  		}
  	},
  	inline_generator => sub {
  		my @operations = @_;
  		return sub {
  			my $v = $_[1];
  			join " and ",
  				"Scalar::Util::blessed($v)",
  				map "overload::Method($v, q[$_])", @operations;
  		};
  	},
  });

  our %_StrMatch;
  $meta->add_type({
  	name       => "StrMatch",
  	parent     => $_str,
  	constraint_generator => sub
  	{
  		return $meta->get_type('StrMatch') unless @_;

  		my ($regexp, $checker) = @_;

  		ref($regexp) eq 'Regexp'
  			or _croak("First parameter to StrMatch[`a] expected to be a Regexp; got $regexp");

  		if (@_ > 1)
  		{
  			$checker = Types::TypeTiny::to_TypeTiny($checker);
  			Types::TypeTiny::TypeTiny->check($checker)
  				or _croak("Second parameter to StrMatch[`a] expected to be a type constraint; got $checker")
  		}

  		$checker
  			? sub {
  				my $value = shift;
  				return if ref($value);
  				my @m = ($value =~ $regexp);
  				$checker->check(\@m);
  			}
  			: sub {
  				my $value = shift;
  				!ref($value) and $value =~ $regexp;
  			}
  		;
  	},
  	inline_generator => sub
  	{
  		require B;
  		my ($regexp, $checker) = @_;
  		my $regexp_string = "$regexp";
  		$_StrMatch{$regexp_string} = $regexp;
  		if ($checker)
  		{
  			return unless $checker->can_be_inlined;
  			return sub
  			{
  				my $v = $_[1];
  				sprintf
  					"!ref($v) and do { my \$m = [$v =~ \$Types::Standard::_StrMatch{%s}]; %s }",
  					B::perlstring($regexp_string),
  					$checker->inline_check('$m'),
  				;
  			};
  		}
  		else
  		{
  			return sub
  			{
  				my $v = $_[1];
  				sprintf
  					"!ref($v) and $v =~ \$Types::Standard::_StrMatch{%s}",
  					B::perlstring($regexp_string),
  				;
  			};
  		}
  	},
  });

  $meta->add_type({
  	name       => "OptList",
  	parent     => $_arr,
  	constraint => sub {
  		for my $inner (@$_) {
  			return unless ref($inner) eq q(ARRAY);
  			return unless @$inner == 2;
  			return unless is_Str($inner->[0]);
  		}
  		return !!1;
  	},
  	inlined     => sub {
  		my ($self, $var) = @_;
  		my $Str_check = Str()->inline_check('$inner->[0]');
  		my @code = 'do { my $ok = 1; ';
  		push @code,   sprintf('for my $inner (@{%s}) { no warnings; ', $var);
  		push @code,   sprintf('($ok=0) && last unless ref($inner) eq q(ARRAY) && @$inner == 2 && (%s); ', $Str_check);
  		push @code,   '} ';
  		push @code, '$ok }';
  		return (undef, join(q( ), @code));
  	},
  });

  $meta->add_type({
  	name       => "Tied",
  	parent     => $_ref,
  	constraint => sub {
  		!!tied(Scalar::Util::reftype($_) eq 'HASH' ?  %{$_} : Scalar::Util::reftype($_) eq 'ARRAY' ?  @{$_} :  ${$_})
  	},
  	inlined    => sub {
  		my ($self, $var) = @_;
  		$self->parent->inline_check($var)
  		. " and !!tied(Scalar::Util::reftype($var) eq 'HASH' ? \%{$var} : Scalar::Util::reftype($var) eq 'ARRAY' ? \@{$var} : \${$var})"
  	},
  	name_generator => sub
  	{
  		my $self  = shift;
  		my $param = Types::TypeTiny::to_TypeTiny(shift);
  		unless (Types::TypeTiny::TypeTiny->check($param))
  		{
  			Types::TypeTiny::StringLike->check($param)
  				or _croak("Parameter to Tied[`a] expected to be a class name; got $param");
  			require B;
  			return sprintf("%s[%s]", $self, B::perlstring($param));
  		}
  		return sprintf("%s[%s]", $self, $param);
  	},
  	constraint_generator => sub
  	{
  		return $meta->get_type('Tied') unless @_;

  		my $param = Types::TypeTiny::to_TypeTiny(shift);
  		unless (Types::TypeTiny::TypeTiny->check($param))
  		{
  			Types::TypeTiny::StringLike->check($param)
  				or _croak("Parameter to Tied[`a] expected to be a class name; got $param");
  			require Type::Tiny::Class;
  			$param = "Type::Tiny::Class"->new(class => "$param");
  		}

  		my $check = $param->compiled_check;
  		return sub {
  			$check->(tied(Scalar::Util::reftype($_) eq 'HASH' ?  %{$_} : Scalar::Util::reftype($_) eq 'ARRAY' ?  @{$_} :  ${$_}));
  		};
  	},
  	inline_generator => sub {
  		my $param = Types::TypeTiny::to_TypeTiny(shift);
  		unless (Types::TypeTiny::TypeTiny->check($param))
  		{
  			Types::TypeTiny::StringLike->check($param)
  				or _croak("Parameter to Tied[`a] expected to be a class name; got $param");
  			require Type::Tiny::Class;
  			$param = "Type::Tiny::Class"->new(class => "$param");
  		}
  		return unless $param->can_be_inlined;

  		return sub {
  			require B;
  			my $var = $_[1];
  			sprintf(
  				"%s and do { my \$TIED = tied(Scalar::Util::reftype($var) eq 'HASH' ? \%{$var} : Scalar::Util::reftype($var) eq 'ARRAY' ? \@{$var} : \${$var}); %s }",
  				Ref()->inline_check($var),
  				$param->inline_check('$TIED')
  			);
  		};
  	},
  });

  $meta->add_type({
  	name       => "InstanceOf",
  	parent     => $_obj,
  	constraint_generator => sub {
  		return $meta->get_type('InstanceOf') unless @_;
  		require Type::Tiny::Class;
  		my @classes = map {
  			Types::TypeTiny::TypeTiny->check($_)
  				? $_
  				: "Type::Tiny::Class"->new(class => $_, display_name => sprintf('InstanceOf[%s]', B::perlstring($_)))
  		} @_;
  		return $classes[0] if @classes == 1;

  		require B;
  		require Type::Tiny::Union;
  		return "Type::Tiny::Union"->new(
  			type_constraints => \@classes,
  			display_name     => sprintf('InstanceOf[%s]', join q[,], map B::perlstring($_->class), @classes),
  		);
  	},
  });

  $meta->add_type({
  	name       => "ConsumerOf",
  	parent     => $_obj,
  	constraint_generator => sub {
  		return $meta->get_type('ConsumerOf') unless @_;
  		require B;
  		require Type::Tiny::Role;
  		my @roles = map {
  			Types::TypeTiny::TypeTiny->check($_)
  				? $_
  				: "Type::Tiny::Role"->new(role => $_, display_name => sprintf('ConsumerOf[%s]', B::perlstring($_)))
  		} @_;
  		return $roles[0] if @roles == 1;

  		require Type::Tiny::Intersection;
  		return "Type::Tiny::Intersection"->new(
  			type_constraints => \@roles,
  			display_name     => sprintf('ConsumerOf[%s]', join q[,], map B::perlstring($_->role), @roles),
  		);
  	},
  });

  $meta->add_type({
  	name       => "HasMethods",
  	parent     => $_obj,
  	constraint_generator => sub {
  		return $meta->get_type('HasMethods') unless @_;
  		require B;
  		require Type::Tiny::Duck;
  		return "Type::Tiny::Duck"->new(
  			methods      => \@_,
  			display_name => sprintf('HasMethods[%s]', join q[,], map B::perlstring($_), @_),
  		);
  	},
  });

  $meta->add_type({
  	name       => "Enum",
  	parent     => $_str,
  	constraint_generator => sub {
  		return $meta->get_type('Enum') unless @_;
  		require B;
  		require Type::Tiny::Enum;
  		return "Type::Tiny::Enum"->new(
  			values       => \@_,
  			display_name => sprintf('Enum[%s]', join q[,], map B::perlstring($_), @_),
  		);
  	},
  });

  $meta->add_coercion({
  	name               => "MkOpt",
  	type_constraint    => $meta->get_type("OptList"),
  	type_coercion_map  => [
  		$_arr,    q{ Exporter::Tiny::mkopt($_) },
  		$_hash,   q{ Exporter::Tiny::mkopt($_) },
  		$_undef,  q{ [] },
  	],
  });

  $meta->add_coercion({
  	name               => "Join",
  	type_constraint    => $_str,
  	coercion_generator => sub {
  		my ($self, $target, $sep) = @_;
  		Types::TypeTiny::StringLike->check($sep)
  			or _croak("Parameter to Join[`a] expected to be a string; got $sep");
  		require B;
  		$sep = B::perlstring($sep);
  		return (ArrayRef(), qq{ join($sep, \@\$_) });
  	},
  });

  $meta->add_coercion({
  	name               => "Split",
  	type_constraint    => $_arr,
  	coercion_generator => sub {
  		my ($self, $target, $re) = @_;
  		ref($re) eq q(Regexp)
  			or _croak("Parameter to Split[`a] expected to be a regular expresssion; got $re");
  		my $regexp_string = "$re";
  		$regexp_string =~ s/\\\//\\\\\//g; # toothpicks
  		return (Str(), qq{ [split /$regexp_string/, \$_] });
  	},
  });

  __PACKAGE__->meta->make_immutable;

  1;

  __END__

  =pod

  =for stopwords booleans vstrings typeglobs

  =encoding utf-8

  =for stopwords datetimes

  =head1 NAME

  Types::Standard - bundled set of built-in types for Type::Tiny

  =head1 STATUS

  This module is covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  L<Type::Tiny> bundles a few types which seem to be useful.

  =head2 Moose-like

  The following types are similar to those described in
  L<Moose::Util::TypeConstraints>.

  =over

  =item C<< Any >>

  Absolutely any value passes this type constraint (even undef).

  =item C<< Item >>

  Essentially the same as C<Any>. All other type constraints in this library
  inherit directly or indirectly from C<Item>.

  =item C<< Bool >>

  Values that are reasonable booleans. Accepts 1, 0, the empty string and
  undef.

  =item C<< Maybe[`a] >>

  Given another type constraint, also accepts undef. For example,
  C<< Maybe[Int] >> accepts all integers plus undef.

  =item C<< Undef >>

  Only undef passes this type constraint.

  =item C<< Defined >>

  Only undef fails this type constraint.

  =item C<< Value >>

  Any defined, non-reference value.

  =item C<< Str >>

  Any string.

  (The only difference between C<Value> and C<Str> is that the former accepts
  typeglobs and vstrings.)

  Other customers also bought: C<< StringLike >> from L<Types::TypeTiny>.

  =item C<< Num >>

  See C<LaxNum> and C<StrictNum> below.

  =item C<< Int >>

  An integer; that is a string of digits 0 to 9, optionally prefixed with a
  hyphen-minus character.

  =item C<< ClassName >>

  The name of a loaded package. The package must have C<< @ISA >> or
  C<< $VERSION >> defined, or must define at least one sub to be considered
  a loaded package.

  =item C<< RoleName >>

  Like C<< ClassName >>, but the package must I<not> define a method called
  C<new>. This is subtly different from Moose's type constraint of the same
  name; let me know if this causes you any problems. (I can't promise I'll
  change anything though.)

  =item C<< Ref[`a] >>

  Any defined reference value, including blessed objects.

  Unlike Moose, C<Ref> is a parameterized type, allowing Scalar::Util::reftype
  checks, a la

     Ref["HASH"]  # hashrefs, including blessed hashrefs

  =item C<< ScalarRef[`a] >>

  A value where C<< ref($value) eq "SCALAR" or ref($value) eq "REF" >>.

  If parameterized, the referred value must pass the additional constraint.
  For example, C<< ScalarRef[Int] >> must be a reference to a scalar which
  holds an integer value.

  =item C<< ArrayRef[`a] >>

  A value where C<< ref($value) eq "ARRAY" >>.

  If parameterized, the elements of the array must pass the additional
  constraint. For example, C<< ArrayRef[Num] >> must be a reference to an
  array of numbers.

  Other customers also bought: C<< ArrayLike >> from L<Types::TypeTiny>.

  =item C<< HashRef[`a] >>

  A value where C<< ref($value) eq "HASH" >>.

  If parameterized, the values of the hash must pass the additional
  constraint. For example, C<< HashRef[Num] >> must be a reference to an
  hash where the values are numbers. The hash keys are not constrained,
  but Perl limits them to strings; see C<Map> below if you need to further
  constrain the hash values.

  Other customers also bought: C<< HashLike >> from L<Types::TypeTiny>.

  =item C<< CodeRef >>

  A value where C<< ref($value) eq "CODE" >>.

  Other customers also bought: C<< CodeLike >> from L<Types::TypeTiny>.

  =item C<< RegexpRef >>

  A value where C<< ref($value) eq "Regexp" >>.

  =item C<< GlobRef >>

  A value where C<< ref($value) eq "GLOB" >>.

  =item C<< FileHandle >>

  A file handle.

  =item C<< Object >>

  A blessed object.

  (This also accepts regexp refs.)

  =back

  =head2 Structured

  OK, so I stole some ideas from L<MooseX::Types::Structured>.

  =over

  =item C<< Map[`k, `v] >>

  Similar to C<HashRef> but parameterized with type constraints for both the
  key and value. The constraint for keys would typically be a subtype of
  C<Str>.

  =item C<< Tuple[...] >>

  Subtype of C<ArrayRef>, accepting an list of type constraints for
  each slot in the array.

  C<< Tuple[Int, HashRef] >> would match C<< [1, {}] >> but not C<< [{}, 1] >>.

  =item C<< Dict[...] >>

  Subtype of C<HashRef>, accepting an list of type constraints for
  each slot in the hash.

  For example C<< Dict[name => Str, id => Int] >> allows
  C<< { name => "Bob", id => 42 } >>.

  =item C<< Optional[`a] >>

  Used in conjunction with C<Dict> and C<Tuple> to specify slots that are
  optional and may be omitted (but not necessarily set to an explicit undef).

  C<< Dict[name => Str, id => Optional[Int]] >> allows C<< { name => "Bob" } >>
  but not C<< { name => "Bob", id => "BOB" } >>.

  Note that any use of C<< Optional[`a] >> outside the context of
  parameterized C<Dict> and C<Tuple> type constraints makes little sense,
  and its behaviour is undefined. (An exception: it is used by
  L<Type::Params> for a similar purpose to how it's used in C<Tuple>.)

  =back

  This module also exports a C<slurpy> function, which can be used as
  follows.

  It can cause additional trailing values in a C<Tuple> to be slurped
  into a structure and validated. For example, slurping into an ArrayRef:

     my $type = Tuple[Str, slurpy ArrayRef[Int]];

     $type->( ["Hello"] );                # ok
     $type->( ["Hello", 1, 2, 3] );       # ok
     $type->( ["Hello", [1, 2, 3]] );     # not ok

  Or into a hashref:

     my $type2 = Tuple[Str, slurpy Map[Int, RegexpRef]];

     $type2->( ["Hello"] );                               # ok
     $type2->( ["Hello", 1, qr/one/i, 2, qr/two/] );      # ok

  It can cause additional values in a C<Dict> to be slurped into a
  hashref and validated:

     my $type3 = Dict[ values => ArrayRef, slurpy HashRef[Str] ];

     $type3->( { values => [] } );                        # ok
     $type3->( { values => [], name => "Foo" } );         # ok
     $type3->( { values => [], name => [] } );            # not ok

  In either C<Tuple> or C<Dict>, C<< slurpy Any >> can be used to indicate
  that additional values are acceptable, but should not be constrained in
  any way. (C<< slurpy Any >> is an optimized code path.)

  =begin trustme

  =item slurpy

  =end trustme

  =head2 Objects

  OK, so I stole some ideas from L<MooX::Types::MooseLike::Base>.

  =over

  =item C<< InstanceOf[`a] >>

  Shortcut for a union of L<Type::Tiny::Class> constraints.

  C<< InstanceOf["Foo", "Bar"] >> allows objects blessed into the C<Foo>
  or C<Bar> classes, or subclasses of those.

  Given no parameters, just equivalent to C<Object>.

  =item C<< ConsumerOf[`a] >>

  Shortcut for an intersection of L<Type::Tiny::Role> constraints.

  C<< ConsumerOf["Foo", "Bar"] >> allows objects where C<< $o->DOES("Foo") >>
  and C<< $o->DOES("Bar") >> both return true.

  Given no parameters, just equivalent to C<Object>.

  =item C<< HasMethods[`a] >>

  Shortcut for a L<Type::Tiny::Duck> constraint.

  C<< HasMethods["foo", "bar"] >> allows objects where C<< $o->can("foo") >>
  and C<< $o->can("bar") >> both return true.

  Given no parameters, just equivalent to C<Object>.

  =back

  =head2 More

  There are a few other types exported by this function:

  =over

  =item C<< Overload[`a] >>

  With no parameters, checks that the value is an overloaded object. Can
  be given one or more string parameters, which are specific operations
  to check are overloaded. For example, the following checks for objects
  which overload addition and subtraction.

     Overload["+", "-"]

  =item C<< Tied[`a] >>

  A reference to a tied scalar, array or hash.

  Can be parameterized with a type constraint which will be applied to
  the object returned by the C<< tied() >> function. As a convenience,
  can also be parameterized with a string, which will be inflated to a
  L<Type::Tiny::Class>.

     use Types::Standard qw(Tied);
     use Type::Utils qw(class_type);

     my $My_Package = class_type { class => "My::Package" };

     tie my %h, "My::Package";
     \%h ~~ Tied;                   # true
     \%h ~~ Tied[ $My_Package ];    # true
     \%h ~~ Tied["My::Package"];    # true

     tie my $s, "Other::Package";
     \$s ~~ Tied;                   # true
     $s  ~~ Tied;                   # false !!

  If you need to check that something is specifically a reference to
  a tied hash, use an intersection:

     use Types::Standard qw( Tied HashRef );

     my $TiedHash = (Tied) & (HashRef);

     tie my %h, "My::Package";
     tie my $s, "Other::Package";

     \%h ~~ $TiedHash;     # true
     \$s ~~ $TiedHash;     # false

  =item C<< StrMatch[`a] >>

  A string that matches a regular expression:

     declare "Distance",
        as StrMatch[ qr{^([0-9]+)\s*(mm|cm|m|km)$} ];

  You can optionally provide a type constraint for the array of subexpressions:

     declare "Distance",
        as StrMatch[
           qr{^([0-9]+)\s*(.+)$},
           Tuple[
              Int,
              enum(DistanceUnit => [qw/ mm cm m km /]),
           ],
        ];

  =item C<< Enum[`a] >>

  As per MooX::Types::MooseLike::Base:

     has size => (is => "ro", isa => Enum[qw( S M L XL XXL )]);

  =item C<< OptList >>

  An arrayref of arrayrefs in the style of L<Data::OptList> output.

  =item C<< LaxNum >>, C<< StrictNum >>

  In Moose 2.09, the C<Num> type constraint implementation was changed from
  being a wrapper around L<Scalar::Util>'s C<looks_like_number> function to
  a stricter regexp (which disallows things like "-Inf" and "Nan").

  Types::Standard provides I<both> implementations. C<LaxNum> is measurably
  faster.

  The C<Num> type constraint is currently an alias for C<LaxNum> unless you
  set the C<PERL_TYPES_STANDARD_STRICTNUM> environment variable to true before
  loading Types::Standard, in which case it becomes an alias for C<StrictNum>.
  The constant C<< Types::Standard::STRICTNUM >> can be used to check if
  C<Num> is being strict.

  Most people should probably use C<Num> or C<StrictNum>. Don't explicitly
  use C<LaxNum> unless you specifically need an attribute which will accept
  things like "Inf".

  =back

  =head2 Coercions

  None of the types in this type library have any coercions by default.
  However some standalone coercions may be exported. These can be combined
  with type constraints using the C<< plus_coercions >> method.

  =over

  =item C<< MkOpt >>

  A coercion from C<ArrayRef>, C<HashRef> or C<Undef> to C<OptList>. Example
  usage in a Moose attribute:

     use Types::Standard qw( OptList MkOpt );

     has options => (
        is     => "ro",
        isa    => OptList->plus_coercions( MkOpt ),
        coerce => 1,
     );

  =item C<< Split[`a] >>

  Split a string on a regexp.

     use Types::Standard qw( ArrayRef Str Split );

     has name => (
        is     => "ro",
        isa    => (ArrayRef[Str])->plus_coercions(Split[qr/\s/]),
        coerce => 1,
     );

  =item C<< Join[`a] >>

  Join an array of strings with a delimiter.

     use Types::Standard qw( Str Join );

     my $FileLines = Str->plus_coercions(Join["\n"]);

     has file_contents => (
        is     => "ro",
        isa    => $FileLines,
        coerce => 1,
     );

  =back

  =head2 Constants

  =over

  =item C<< Types::Standard::STRICTNUM >>

  Indicates whether C<Num> is an alias for C<StrictNum>. (It is usually an
  alias for C<LaxNum>.)

  =back

  =begin private

  =item Stringable

  =item LazyLoad

  =end private

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Type::Tiny::Manual>.

  L<Type::Tiny>, L<Type::Library>, L<Type::Utils>, L<Type::Coercion>.

  L<Moose::Util::TypeConstraints>,
  L<Mouse::Util::TypeConstraints>,
  L<MooseX::Types::Structured>.

  L<Types::XSD> provides some type constraints based on XML Schema's data
  types; this includes constraints for ISO8601-formatted datetimes, integer
  ranges (e.g. C<< PositiveInteger[maxInclusive=>10] >> and so on.

  L<Types::Encodings> provides C<Bytes> and C<Chars> type constraints that
  were formerly found in Types::Standard.

  L<Types::Common::Numeric> and L<Types::Common::String> provide replacements
  for L<MooseX::Types::Common>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

TYPES_STANDARD

$fatpacked{"Types/Standard/ArrayRef.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TYPES_STANDARD_ARRAYREF';
  package Types::Standard::ArrayRef;

  use 5.006001;
  use strict;
  use warnings;

  BEGIN {
  	$Types::Standard::ArrayRef::AUTHORITY = 'cpan:TOBYINK';
  	$Types::Standard::ArrayRef::VERSION   = '1.000005';
  }

  use Type::Tiny ();
  use Types::Standard ();
  use Types::TypeTiny ();

  sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }

  no warnings;

  sub __constraint_generator
  {
  	return Types::Standard::ArrayRef unless @_;

  	my $param = Types::TypeTiny::to_TypeTiny(shift);
  	Types::TypeTiny::TypeTiny->check($param)
  		or _croak("Parameter to ArrayRef[`a] expected to be a type constraint; got $param");

  	my $param_compiled_check = $param->compiled_check;
  	my $xsub;
  	if (Type::Tiny::_USE_XS)
  	{
  		my $paramname = Type::Tiny::XS::is_known($param_compiled_check);
  		$xsub = Type::Tiny::XS::get_coderef_for("ArrayRef[$paramname]")
  			if $paramname;
  	}
  	elsif (Type::Tiny::_USE_MOUSE and $param->_has_xsub)
  	{
  		require Mouse::Util::TypeConstraints;
  		my $maker = "Mouse::Util::TypeConstraints"->can("_parameterize_ArrayRef_for");
  		$xsub = $maker->($param) if $maker;
  	}

  	return (
  		sub
  		{
  			my $array = shift;
  			$param->check($_) || return for @$array;
  			return !!1;
  		},
  		$xsub,
  	);
  }

  sub __inline_generator
  {
  	my $param = shift;

  	my $param_compiled_check = $param->compiled_check;
  	if (Type::Tiny::_USE_XS)
  	{
  		my $paramname = Type::Tiny::XS::is_known($param_compiled_check);
  		my $xsubname  = Type::Tiny::XS::get_subname_for("ArrayRef[$paramname]");
  		return sub { "$xsubname\($_[1]\)" } if $xsubname;
  	}

  	return unless $param->can_be_inlined;
  	my $param_check = $param->inline_check('$i');
  	return sub {
  		my $v = $_[1];
  		"ref($v) eq 'ARRAY' and do { "
  		.  "my \$ok = 1; "
  		.  "for my \$i (\@{$v}) { "
  		.    "(\$ok = 0, last) unless $param_check "
  		.  "}; "
  		.  "\$ok "
  		."}"
  	};
  }

  sub __deep_explanation
  {
  	my ($type, $value, $varname) = @_;
  	my $param = $type->parameters->[0];

  	for my $i (0 .. $#$value)
  	{
  		my $item = $value->[$i];
  		next if $param->check($item);
  		return [
  			sprintf('"%s" constrains each value in the array with "%s"', $type, $param),
  			@{ $param->validate_explain($item, sprintf('%s->[%d]', $varname, $i)) },
  		]
  	}

  	# This should never happen...
  	return;  # uncoverable statement
  }

  sub __coercion_generator
  {
  	my ($parent, $child, $param) = @_;
  	return unless $param->has_coercion;

  	my $coercable_item = $param->coercion->_source_type_union;
  	my $C = "Type::Coercion"->new(type_constraint => $child);

  	if ($param->coercion->can_be_inlined and $coercable_item->can_be_inlined)
  	{
  		$C->add_type_coercions($parent => Types::Standard::Stringable {
  			my @code;
  			push @code, 'do { my ($orig, $return_orig, @new) = ($_, 0);';
  			push @code,    'for (@$orig) {';
  			push @code, sprintf('++$return_orig && last unless (%s);', $coercable_item->inline_check('$_'));
  			push @code, sprintf('push @new, (%s);', $param->coercion->inline_coercion('$_'));
  			push @code,    '}';
  			push @code,    '$return_orig ? $orig : \\@new';
  			push @code, '}';
  			"@code";
  		});
  	}
  	else
  	{
  		$C->add_type_coercions(
  			$parent => sub {
  				my $value = @_ ? $_[0] : $_;
  				my @new;
  				for my $item (@$value)
  				{
  					return $value unless $coercable_item->check($item);
  					push @new, $param->coerce($item);
  				}
  				return \@new;
  			},
  		);
  	}

  	return $C;
  }

  1;

  __END__

  =pod

  =encoding utf-8

  =head1 NAME

  Types::Standard::ArrayRef - internals for the Types::Standard ArrayRef type constraint

  =head1 STATUS

  This module is considered part of Type-Tiny's internals. It is not
  covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  This file contains some of the guts for L<Types::Standard>.
  It will be loaded on demand. You may ignore its presence.

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Types::Standard>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

TYPES_STANDARD_ARRAYREF

$fatpacked{"Types/Standard/Dict.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TYPES_STANDARD_DICT';
  package Types::Standard::Dict;

  use 5.006001;
  use strict;
  use warnings;

  BEGIN {
  	$Types::Standard::Dict::AUTHORITY = 'cpan:TOBYINK';
  	$Types::Standard::Dict::VERSION   = '1.000005';
  }

  use Types::Standard ();
  use Types::TypeTiny ();

  sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }

  my $_optional = Types::Standard::Optional;
  my $_hash     = Types::Standard::HashRef;
  my $_map      = Types::Standard::Map;
  my $_any      = Types::Standard::Any;

  no warnings;

  sub __constraint_generator
  {
  	my $slurpy = ref($_[-1]) eq q(HASH) ? pop(@_)->{slurpy} : undef;
  	my %constraints = @_;
  	my %is_optional;

  	while (my ($k, $v) = each %constraints)
  	{
  		$constraints{$k} = Types::TypeTiny::to_TypeTiny($v);
  		$is_optional{$k} = !!$constraints{$k}->is_strictly_a_type_of($_optional);
  		Types::TypeTiny::TypeTiny->check($v)
  			or _croak("Parameter to Dict[`a] for key '$k' expected to be a type constraint; got $v");
  	}

  	return sub
  	{
  		my $value = $_[0];
  		if ($slurpy)
  		{
  			my %tmp = map {
  				exists($constraints{$_}) ? () : ($_ => $value->{$_})
  			} keys %$value;
  			return unless $slurpy->check(\%tmp);
  		}
  		else
  		{
  			exists($constraints{$_}) || return for sort keys %$value;
  		}
  		for my $k (sort keys %constraints) {
  			exists($value->{$k}) or ($is_optional{$k} ? next : return);
  			$constraints{$k}->check($value->{$k}) or return;
  		}
  		return !!1;
  	};
  }

  sub __inline_generator
  {
  	# We can only inline a parameterized Dict if all the
  	# constraints inside can be inlined.

  	my $slurpy = ref($_[-1]) eq q(HASH) ? pop(@_)->{slurpy} : undef;
  	return if $slurpy && !$slurpy->can_be_inlined;

  	# Is slurpy a very loose type constraint?
  	# i.e. Any, Item, Defined, Ref, or HashRef
  	my $slurpy_is_any = $slurpy && $_hash->is_a_type_of( $slurpy );

  	# Is slurpy a parameterized Map, or expressable as a parameterized Map?
  	my $slurpy_is_map = $slurpy
  		&& $slurpy->is_parameterized
  		&& ((
  			$slurpy->parent->strictly_equals($_map)
  			&& $slurpy->parameters
  		)||(
  			$slurpy->parent->strictly_equals($_hash)
  			&& [ $_any, $slurpy->parameters->[0] ]
  		));

  	my %constraints = @_;
  	for my $c (values %constraints)
  	{
  		next if $c->can_be_inlined;
  		return;
  	}

  	my $regexp = join "|", map quotemeta, sort keys %constraints;
  	return sub
  	{
  		require B;
  		my $h = $_[1];
  		join " and ",
  			"ref($h) eq 'HASH'",
  			( $slurpy_is_any ? ()
  			: $slurpy_is_map ? do {
  				'(not grep {'
  				."my \$v = ($h)->{\$_};"
  				.sprintf(
  					'not((/\\A(?:%s)\\z/) or ((%s) and (%s)))',
  					$regexp,
  					$slurpy_is_map->[0]->inline_check('$_'),
  					$slurpy_is_map->[1]->inline_check('$v'),
  				) ."} keys \%{$h})"
  			}
  			: $slurpy ? do {
  				'do {'
  				. "my \$slurpy_tmp = +{ map /\\A(?:$regexp)\\z/ ? () : (\$_ => ($h)->{\$_}), keys \%{$h} };"
  				. $slurpy->inline_check('$slurpy_tmp')
  				. '}'
  			}
  			: "not(grep !/\\A(?:$regexp)\\z/, keys \%{$h})" ),
  			( map {
  				my $k = B::perlstring($_);
  				$constraints{$_}->is_strictly_a_type_of( $_optional )
  					? sprintf('(!exists %s->{%s} or %s)', $h, $k, $constraints{$_}->inline_check("$h\->{$k}"))
  					: ( "exists($h\->{$k})", $constraints{$_}->inline_check("$h\->{$k}") )
  			} sort keys %constraints ),
  	}
  }

  sub __deep_explanation
  {
  	require B;
  	my ($type, $value, $varname) = @_;
  	my @params = @{ $type->parameters };

  	my $slurpy = ref($params[-1]) eq q(HASH) ? pop(@params)->{slurpy} : undef;
  	my %constraints = @params;

  	for my $k (sort keys %constraints)
  	{
  		next if $constraints{$k}->parent == Types::Standard::Optional && !exists $value->{$k};
  		next if $constraints{$k}->check($value->{$k});

  		return [
  			sprintf('"%s" requires key %s to appear in hash', $type, B::perlstring($k))
  		] unless exists $value->{$k};

  		return [
  			sprintf('"%s" constrains value at key %s of hash with "%s"', $type, B::perlstring($k), $constraints{$k}),
  			@{ $constraints{$k}->validate_explain($value->{$k}, sprintf('%s->{%s}', $varname, B::perlstring($k))) },
  		];
  	}

  	if ($slurpy)
  	{
  		my %tmp = map {
  			exists($constraints{$_}) ? () : ($_ => $value->{$_})
  		} keys %$value;

  		my $explain = $slurpy->validate_explain(\%tmp, '$slurpy');
  		return [
  			sprintf('"%s" requires the hashref of additional key/value pairs to conform to "%s"', $type, $slurpy),
  			@$explain,
  		] if $explain;
  	}
  	else
  	{
  		for my $k (sort keys %$value)
  		{
  			return [
  				sprintf('"%s" does not allow key %s to appear in hash', $type, B::perlstring($k))
  			] unless exists $constraints{$k};
  		}
  	}

  	# This should never happen...
  	return;  # uncoverable statement
  }

  my $label_counter = 0;
  our ($keycheck_counter, @KEYCHECK) = -1;
  sub __coercion_generator
  {
  	my $slurpy = ref($_[-1]) eq q(HASH) ? pop(@_)->{slurpy} : undef;
  	my ($parent, $child, %dict) = @_;
  	my $C = "Type::Coercion"->new(type_constraint => $child);

  	my $all_inlinable = 1;
  	for my $tc (values %dict)
  	{
  		$all_inlinable = 0 if !$tc->can_be_inlined;
  		$all_inlinable = 0 if $tc->has_coercion && !$tc->coercion->can_be_inlined;
  		last if!$all_inlinable;
  	}
  	$all_inlinable = 0 if $slurpy && !$slurpy->can_be_inlined;
  	$all_inlinable = 0 if $slurpy && $slurpy->has_coercion && !$slurpy->coercion->can_be_inlined;

  	if ($all_inlinable)
  	{
  		$C->add_type_coercions($parent => Types::Standard::Stringable {
  			require B;

  			my $keycheck = join "|", map quotemeta, sort { length($b) <=> length($a) or $a cmp $b } keys %dict;
  			$keycheck = $KEYCHECK[++$keycheck_counter] = qr{^($keycheck)$}ms; # regexp for legal keys

  			my $label = sprintf("DICTLABEL%d", ++$label_counter);
  			my @code;
  			push @code, 'do { my ($orig, $return_orig, $tmp, %new) = ($_, 0);';
  			push @code,       "$label: {";
  			if ($slurpy)
  			{
  				push @code, sprintf('my $slurped = +{ map +($_=~$%s::KEYCHECK[%d])?():($_=>$orig->{$_}), keys %%$orig };', __PACKAGE__, $keycheck_counter);
  				if ($slurpy->has_coercion)
  				{
  					push @code, sprintf('my $coerced = %s;', $slurpy->coercion->inline_coercion('$slurped'));
  					push @code, sprintf('((%s)&&(%s))?(%%new=%%$coerced):(($return_orig = 1), last %s);', $_hash->inline_check('$coerced'), $slurpy->inline_check('$coerced'), $label);
  				}
  				else
  				{
  					push @code, sprintf('(%s)?(%%new=%%$slurped):(($return_orig = 1), last %s);', $slurpy->inline_check('$slurped'), $label);
  				}
  			}
  			else
  			{
  				push @code, sprintf('($_ =~ $%s::KEYCHECK[%d])||(($return_orig = 1), last %s) for sort keys %%$orig;', __PACKAGE__, $keycheck_counter, $label);
  			}
  			for my $k (keys %dict)
  			{
  				my $ct = $dict{$k};
  				my $ct_coerce   = $ct->has_coercion;
  				my $ct_optional = $ct->is_a_type_of($_optional);
  				my $K = B::perlstring($k);

  				push @code, sprintf(
  					'if (exists $orig->{%s}) { $tmp = %s; (%s) ? ($new{%s}=$tmp) : ($return_orig=1 and last %s) }',
  					$K,
  					$ct_coerce
  						? $ct->coercion->inline_coercion("\$orig->{$K}")
  						: "\$orig->{$K}",
  					$ct->inline_check('$tmp'),
  					$K,
  					$label,
  				);
  			}
  			push @code,       '}';
  			push @code,    '$return_orig ? $orig : \\%new';
  			push @code, '}';
  			#warn "CODE:: @code";
  			"@code";
  		});
  	}

  	else
  	{
  		my %is_optional = map {
  			; $_ => !!$dict{$_}->is_strictly_a_type_of($_optional)
  		} sort keys %dict;
  		$C->add_type_coercions(
  			$parent => sub {
  				my $value = @_ ? $_[0] : $_;
  				my %new;

  				if ($slurpy)
  				{
  					my %slurped = map exists($dict{$_}) ? () : ($_ => $value->{$_}), keys %$value;

  					if ($slurpy->check(\%slurped))
  					{
  						%new = %slurped;
  					}
  					elsif ($slurpy->has_coercion)
  					{
  						my $coerced = $slurpy->coerce(\%slurped);
  						$slurpy->check($coerced) ? (%new = %$coerced) : (return $value);
  					}
  					else
  					{
  						return $value;
  					}
  				}
  				else
  				{
  					for my $k (keys %$value)
  					{
  						return $value unless exists $dict{$k};
  					}
  				}

  				for my $k (keys %dict)
  				{
  					next if $is_optional{$k} and not exists $value->{$k};

  					my $ct = $dict{$k};
  					my $x  = $ct->has_coercion ? $ct->coerce($value->{$k}) : $value->{$k};

  					return $value unless $ct->check($x);

  					$new{$k} = $x;
  				}

  				return \%new;
  			},
  		);
  	}

  	return $C;
  }

  1;

  __END__

  =pod

  =encoding utf-8

  =head1 NAME

  Types::Standard::Dict - internals for the Types::Standard Dict type constraint

  =head1 STATUS

  This module is considered part of Type-Tiny's internals. It is not
  covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  This file contains some of the guts for L<Types::Standard>.
  It will be loaded on demand. You may ignore its presence.

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Types::Standard>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

TYPES_STANDARD_DICT

$fatpacked{"Types/Standard/HashRef.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TYPES_STANDARD_HASHREF';
  package Types::Standard::HashRef;

  use 5.006001;
  use strict;
  use warnings;

  BEGIN {
  	$Types::Standard::HashRef::AUTHORITY = 'cpan:TOBYINK';
  	$Types::Standard::HashRef::VERSION   = '1.000005';
  }

  use Type::Tiny ();
  use Types::Standard ();
  use Types::TypeTiny ();

  sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }

  no warnings;

  sub __constraint_generator
  {
  	return Types::Standard::HashRef unless @_;

  	my $param = Types::TypeTiny::to_TypeTiny(shift);
  	Types::TypeTiny::TypeTiny->check($param)
  		or _croak("Parameter to HashRef[`a] expected to be a type constraint; got $param");

  	my $param_compiled_check = $param->compiled_check;
  	my $xsub;
  	if (Type::Tiny::_USE_XS)
  	{
  		my $paramname = Type::Tiny::XS::is_known($param_compiled_check);
  		$xsub = Type::Tiny::XS::get_coderef_for("HashRef[$paramname]")
  			if $paramname;
  	}
  	elsif (Type::Tiny::_USE_MOUSE and $param->_has_xsub)
  	{
  		require Mouse::Util::TypeConstraints;
  		my $maker = "Mouse::Util::TypeConstraints"->can("_parameterize_HashRef_for");
  		$xsub = $maker->($param) if $maker;
  	}

  	return (
  		sub
  		{
  			my $hash = shift;
  			$param->check($_) || return for values %$hash;
  			return !!1;
  		},
  		$xsub,
  	);
  }

  sub __inline_generator
  {
  	my $param = shift;

  	my $compiled = $param->compiled_check;
  	if (Type::Tiny::_USE_XS)
  	{
  		my $paramname = Type::Tiny::XS::is_known($compiled);
  		my $xsubname  = Type::Tiny::XS::get_subname_for("HashRef[$paramname]");
  		return sub { "$xsubname\($_[1]\)" } if $xsubname;
  	}

  	return unless $param->can_be_inlined;
  	my $param_check = $param->inline_check('$i');
  	return sub {
  		my $v = $_[1];
  		"ref($v) eq 'HASH' and do { "
  		.  "my \$ok = 1; "
  		.  "for my \$i (values \%{$v}) { "
  		.    "(\$ok = 0, last) unless $param_check "
  		.  "}; "
  		.  "\$ok "
  		."}"
  	};
  }

  sub __deep_explanation
  {
  	require B;
  	my ($type, $value, $varname) = @_;
  	my $param = $type->parameters->[0];

  	for my $k (sort keys %$value)
  	{
  		my $item = $value->{$k};
  		next if $param->check($item);
  		return [
  			sprintf('"%s" constrains each value in the hash with "%s"', $type, $param),
  			@{ $param->validate_explain($item, sprintf('%s->{%s}', $varname, B::perlstring($k))) },
  		];
  	}

  	# This should never happen...
  	return;  # uncoverable statement
  }

  sub __coercion_generator
  {
  	my ($parent, $child, $param) = @_;
  	return unless $param->has_coercion;

  	my $coercable_item = $param->coercion->_source_type_union;
  	my $C = "Type::Coercion"->new(type_constraint => $child);

  	if ($param->coercion->can_be_inlined and $coercable_item->can_be_inlined)
  	{
  		$C->add_type_coercions($parent => Types::Standard::Stringable {
  			my @code;
  			push @code, 'do { my ($orig, $return_orig, %new) = ($_, 0);';
  			push @code,    'for (keys %$orig) {';
  			push @code, sprintf('$return_orig++ && last unless (%s);', $coercable_item->inline_check('$orig->{$_}'));
  			push @code, sprintf('$new{$_} = (%s);', $param->coercion->inline_coercion('$orig->{$_}'));
  			push @code,    '}';
  			push @code,    '$return_orig ? $orig : \\%new';
  			push @code, '}';
  			"@code";
  		});
  	}
  	else
  	{
  		$C->add_type_coercions(
  			$parent => sub {
  				my $value = @_ ? $_[0] : $_;
  				my %new;
  				for my $k (keys %$value)
  				{
  					return $value unless $coercable_item->check($value->{$k});
  					$new{$k} = $param->coerce($value->{$k});
  				}
  				return \%new;
  			},
  		);
  	}

  	return $C;
  }

  1;

  __END__

  =pod

  =encoding utf-8

  =head1 NAME

  Types::Standard::HashRef - internals for the Types::Standard HashRef type constraint

  =head1 STATUS

  This module is considered part of Type-Tiny's internals. It is not
  covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  This file contains some of the guts for L<Types::Standard>.
  It will be loaded on demand. You may ignore its presence.

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Types::Standard>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

TYPES_STANDARD_HASHREF

$fatpacked{"Types/Standard/Map.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TYPES_STANDARD_MAP';
  package Types::Standard::Map;

  use 5.006001;
  use strict;
  use warnings;

  BEGIN {
  	$Types::Standard::Map::AUTHORITY = 'cpan:TOBYINK';
  	$Types::Standard::Map::VERSION   = '1.000005';
  }

  use Type::Tiny ();
  use Types::Standard ();
  use Types::TypeTiny ();

  sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }

  my $meta = Types::Standard->meta;

  no warnings;

  sub __constraint_generator
  {
  	return $meta->get_type('Map') unless @_;

  	my ($keys, $values) = map Types::TypeTiny::to_TypeTiny($_), @_;
  	Types::TypeTiny::TypeTiny->check($keys)
  		or _croak("First parameter to Map[`k,`v] expected to be a type constraint; got $keys");
  	Types::TypeTiny::TypeTiny->check($values)
  		or _croak("Second parameter to Map[`k,`v] expected to be a type constraint; got $values");

  	my @xsub;
  	if (Type::Tiny::_USE_XS)
  	{
  		my @known = map {
  			my $known = Type::Tiny::XS::is_known($_->compiled_check);
  			defined($known) ? $known : ();
  		} ($keys, $values);

  		if (@known == 2)
  		{
  			my $xsub = Type::Tiny::XS::get_coderef_for(
  				sprintf "Map[%s,%s]", @known
  			);
  			push @xsub, $xsub if $xsub;
  		}
  	}

  	sub
  	{
  		my $hash = shift;
  		$keys->check($_)   || return for keys %$hash;
  		$values->check($_) || return for values %$hash;
  		return !!1;
  	}, @xsub;
  }

  sub __inline_generator
  {
  	my ($k, $v) = @_;
  	return unless $k->can_be_inlined && $v->can_be_inlined;

  	if (Type::Tiny::_USE_XS)
  	{
  		my @known = map {
  			my $known = Type::Tiny::XS::is_known($_->compiled_check);
  			defined($known) ? $known : ();
  		} ($k, $v);

  		if (@known == 2)
  		{
  			my $xsub = Type::Tiny::XS::get_subname_for(
  				sprintf "Map[%s,%s]", @known
  			);
  			return sub { my $var = $_[1]; "$xsub\($var\)" } if $xsub;
  		}
  	}

  	my $k_check = $k->inline_check('$k');
  	my $v_check = $v->inline_check('$v');
  	return sub {
  		my $h = $_[1];
  		"ref($h) eq 'HASH' and do { "
  		.  "my \$ok = 1; "
  		.  "for my \$v (values \%{$h}) { "
  		.    "(\$ok = 0, last) unless $v_check "
  		.  "}; "
  		.  "for my \$k (keys \%{$h}) { "
  		.    "(\$ok = 0, last) unless $k_check "
  		.  "}; "
  		.  "\$ok "
  		."}"
  	};
  }

  sub __deep_explanation
  {
  	require B;
  	my ($type, $value, $varname) = @_;
  	my ($kparam, $vparam) = @{ $type->parameters };

  	for my $k (sort keys %$value)
  	{
  		unless ($kparam->check($k))
  		{
  			return [
  				sprintf('"%s" constrains each key in the hash with "%s"', $type, $kparam),
  				@{ $kparam->validate_explain($k, sprintf('key %s->{%s}', $varname, B::perlstring($k))) },
  			];
  		}

  		unless ($vparam->check($value->{$k}))
  		{
  			return [
  				sprintf('"%s" constrains each value in the hash with "%s"', $type, $vparam),
  				@{ $vparam->validate_explain($value->{$k}, sprintf('%s->{%s}', $varname, B::perlstring($k))) },
  			];
  		}
  	}

  	# This should never happen...
  	return;  # uncoverable statement
  }

  sub __coercion_generator
  {
  	my ($parent, $child, $kparam, $vparam) = @_;
  	return unless $kparam->has_coercion || $vparam->has_coercion;

  	my $kcoercable_item = $kparam->has_coercion ? $kparam->coercion->_source_type_union : $kparam;
  	my $vcoercable_item = $vparam->has_coercion ? $vparam->coercion->_source_type_union : $vparam;
  	my $C = "Type::Coercion"->new(type_constraint => $child);

  	if ((!$kparam->has_coercion or $kparam->coercion->can_be_inlined)
  	and (!$vparam->has_coercion or $vparam->coercion->can_be_inlined)
  	and $kcoercable_item->can_be_inlined
  	and $vcoercable_item->can_be_inlined)
  	{
  		$C->add_type_coercions($parent => Types::Standard::Stringable {
  			my @code;
  			push @code, 'do { my ($orig, $return_orig, %new) = ($_, 0);';
  			push @code,    'for (keys %$orig) {';
  			push @code, sprintf('++$return_orig && last unless (%s);', $kcoercable_item->inline_check('$_'));
  			push @code, sprintf('++$return_orig && last unless (%s);', $vcoercable_item->inline_check('$orig->{$_}'));
  			push @code, sprintf('$new{(%s)} = (%s);',
  				$kparam->has_coercion ? $kparam->coercion->inline_coercion('$_') : '$_',
  				$vparam->has_coercion ? $vparam->coercion->inline_coercion('$orig->{$_}') : '$orig->{$_}',
  			);
  			push @code,    '}';
  			push @code,    '$return_orig ? $orig : \\%new';
  			push @code, '}';
  			"@code";
  		});
  	}
  	else
  	{
  		$C->add_type_coercions(
  			$parent => sub {
  				my $value = @_ ? $_[0] : $_;
  				my %new;
  				for my $k (keys %$value)
  				{
  					return $value unless $kcoercable_item->check($k) && $vcoercable_item->check($value->{$k});
  					$new{$kparam->has_coercion ? $kparam->coerce($k) : $k} =
  						$vparam->has_coercion ? $vparam->coerce($value->{$k}) : $value->{$k};
  				}
  				return \%new;
  			},
  		);
  	}

  	return $C;
  }

  1;

  __END__

  =pod

  =encoding utf-8

  =head1 NAME

  Types::Standard::Map - internals for the Types::Standard Map type constraint

  =head1 STATUS

  This module is considered part of Type-Tiny's internals. It is not
  covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  This file contains some of the guts for L<Types::Standard>.
  It will be loaded on demand. You may ignore its presence.

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Types::Standard>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

TYPES_STANDARD_MAP

$fatpacked{"Types/Standard/ScalarRef.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TYPES_STANDARD_SCALARREF';
  package Types::Standard::ScalarRef;

  use 5.006001;
  use strict;
  use warnings;

  BEGIN {
  	$Types::Standard::ScalarRef::AUTHORITY = 'cpan:TOBYINK';
  	$Types::Standard::ScalarRef::VERSION   = '1.000005';
  }

  use Types::Standard ();
  use Types::TypeTiny ();

  sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }

  no warnings;

  sub __constraint_generator
  {
  	return Types::Standard::ScalarRef unless @_;

  	my $param = Types::TypeTiny::to_TypeTiny(shift);
  	Types::TypeTiny::TypeTiny->check($param)
  		or _croak("Parameter to ScalarRef[`a] expected to be a type constraint; got $param");

  	return sub
  	{
  		my $ref = shift;
  		$param->check($$ref) || return;
  		return !!1;
  	};
  }

  sub __inline_generator
  {
  	my $param = shift;
  	return unless $param->can_be_inlined;
  	return sub {
  		my $v = $_[1];
  		my $param_check = $param->inline_check("\${$v}");
  		"(ref($v) eq 'SCALAR' or ref($v) eq 'REF') and $param_check";
  	};
  }

  sub __deep_explanation
  {
  	my ($type, $value, $varname) = @_;
  	my $param = $type->parameters->[0];

  	for my $item ($$value)
  	{
  		next if $param->check($item);
  		return [
  			sprintf('"%s" constrains the referenced scalar value with "%s"', $type, $param),
  			@{ $param->validate_explain($item, sprintf('${%s}', $varname)) },
  		];
  	}

  	# This should never happen...
  	return;  # uncoverable statement
  }

  sub __coercion_generator
  {
  	my ($parent, $child, $param) = @_;
  	return unless $param->has_coercion;

  	my $coercable_item = $param->coercion->_source_type_union;
  	my $C = "Type::Coercion"->new(type_constraint => $child);

  	if ($param->coercion->can_be_inlined and $coercable_item->can_be_inlined)
  	{
  		$C->add_type_coercions($parent => Types::Standard::Stringable {
  			my @code;
  			push @code, 'do { my ($orig, $return_orig, $new) = ($_, 0);';
  			push @code,    'for ($$orig) {';
  			push @code, sprintf('++$return_orig && last unless (%s);', $coercable_item->inline_check('$_'));
  			push @code, sprintf('$new = (%s);', $param->coercion->inline_coercion('$_'));
  			push @code,    '}';
  			push @code,    '$return_orig ? $orig : \\$new';
  			push @code, '}';
  			"@code";
  		});
  	}
  	else
  	{
  		$C->add_type_coercions(
  			$parent => sub {
  				my $value = @_ ? $_[0] : $_;
  				my $new;
  				for my $item ($$value)
  				{
  					return $value unless $coercable_item->check($item);
  					$new = $param->coerce($item);
  				}
  				return \$new;
  			},
  		);
  	}

  	return $C;
  }

  1;

  __END__

  =pod

  =encoding utf-8

  =head1 NAME

  Types::Standard::ScalarRef - internals for the Types::Standard ScalarRef type constraint

  =head1 STATUS

  This module is considered part of Type-Tiny's internals. It is not
  covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  This file contains some of the guts for L<Types::Standard>.
  It will be loaded on demand. You may ignore its presence.

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Types::Standard>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

TYPES_STANDARD_SCALARREF

$fatpacked{"Types/Standard/Tuple.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TYPES_STANDARD_TUPLE';
  package Types::Standard::Tuple;

  use 5.006001;
  use strict;
  use warnings;

  BEGIN {
  	$Types::Standard::Tuple::AUTHORITY = 'cpan:TOBYINK';
  	$Types::Standard::Tuple::VERSION   = '1.000005';
  }

  use Type::Tiny ();
  use Types::Standard ();
  use Types::TypeTiny ();

  sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }

  my $_Optional = Types::Standard::Optional;

  no warnings;

  sub __constraint_generator
  {
  	my @constraints = @_;
  	my $slurpy;
  	if (exists $constraints[-1] and ref $constraints[-1] eq "HASH")
  	{
  		$slurpy = Types::TypeTiny::to_TypeTiny(pop(@constraints)->{slurpy});
  		Types::TypeTiny::TypeTiny->check($slurpy)
  			or _croak("Slurpy parameter to Tuple[...] expected to be a type constraint; got $slurpy");
  	}

  	@constraints = map Types::TypeTiny::to_TypeTiny($_), @constraints;
  	for (@constraints)
  	{
  		Types::TypeTiny::TypeTiny->check($_)
  			or _croak("Parameters to Tuple[...] expected to be type constraints; got $_");
  	}

  	# By god, the Type::Tiny::XS API is currently horrible
  	my @xsub;
  	if (Type::Tiny::_USE_XS and !$slurpy)
  	{
  		my @known = map {
  			my $known;
  			$known = Type::Tiny::XS::is_known($_->compiled_check)
  				unless $_->is_strictly_a_type_of($_Optional);
  			defined($known) ? $known : ();
  		} @constraints;

  		if (@known == @constraints)
  		{
  			my $xsub = Type::Tiny::XS::get_coderef_for(
  				sprintf "Tuple[%s]", join(',', @known)
  			);
  			push @xsub, $xsub if $xsub;
  		}
  	}

  	my @is_optional = map !!$_->is_strictly_a_type_of($_Optional), @constraints;
  	my $slurp_hash  = $slurpy && $slurpy->is_a_type_of(Types::Standard::HashRef);
  	my $slurp_any   = $slurpy && $slurpy->equals(Types::Standard::Any);

  	sub
  	{
  		my $value = $_[0];
  		if ($#constraints < $#$value)
  		{
  			return !!0 unless $slurpy;
  			my $tmp;
  			if ($slurp_hash)
  			{
  				($#$value - $#constraints+1) % 2 or return;
  				$tmp = +{@$value[$#constraints+1 .. $#$value]};
  				$slurpy->check($tmp) or return;
  			}
  			elsif (not $slurp_any)
  			{
  				$tmp = +[@$value[$#constraints+1 .. $#$value]];
  				$slurpy->check($tmp) or return;
  			}
  		}
  		for my $i (0 .. $#constraints)
  		{
  			($i > $#$value)
  				and return !!$is_optional[$i];

  			$constraints[$i]->check($value->[$i])
  				or return !!0;
  		}
  		return !!1;
  	}, @xsub;
  }

  sub __inline_generator
  {
  	my @constraints = @_;
  	my $slurpy;
  	if (exists $constraints[-1] and ref $constraints[-1] eq "HASH")
  	{
  		$slurpy = pop(@constraints)->{slurpy};
  	}

  	return if grep { not $_->can_be_inlined } @constraints;
  	return if defined $slurpy && !$slurpy->can_be_inlined;

  	if (Type::Tiny::_USE_XS and !$slurpy)
  	{
  		my @known = map {
  			my $known;
  			$known = Type::Tiny::XS::is_known($_->compiled_check)
  				unless $_->is_strictly_a_type_of($_Optional);
  			defined($known) ? $known : ();
  		} @constraints;

  		if (@known == @constraints)
  		{
  			my $xsub = Type::Tiny::XS::get_subname_for(
  				sprintf "Tuple[%s]", join(',', @known)
  			);
  			return sub { my $var = $_[1]; "$xsub\($var\)" } if $xsub;
  		}
  	}

  	my $tmpl = "do { my \$tmp = +[\@{%s}[%d..\$#{%s}]]; %s }";
  	my $slurpy_any;
  	if (defined $slurpy)
  	{
  		$tmpl = 'do { my ($orig, $from, $to) = (%s, %d, $#{%s});'
  			.    '($to-$from % 2) and do { my $tmp = +{@{$orig}[$from..$to]}; %s }'
  			.    '}'
  			if $slurpy->is_a_type_of(Types::Standard::HashRef);
  		$slurpy_any = 1
  			if $slurpy->equals(Types::Standard::Any);
  	}

  	my @is_optional = map !!$_->is_strictly_a_type_of($_Optional), @constraints;
  	my $min         = 0 + grep !$_, @is_optional;

  	return sub
  	{
  		my $v = $_[1];
  		join " and ",
  			"ref($v) eq 'ARRAY'",
  			"scalar(\@{$v}) >= $min",
  			(
  				$slurpy_any
  					? ()
  					: (
  						$slurpy
  							? sprintf($tmpl, $v, $#constraints+1, $v, $slurpy->inline_check('$tmp'))
  							: sprintf("\@{$v} <= %d", scalar @constraints)
  					)
  			),
  			map {
  				my $inline = $constraints[$_]->inline_check("$v\->[$_]");
  				$is_optional[$_]
  					? sprintf('(@{%s} <= %d or %s)', $v, $_, $inline)
  					: $inline;
  			} 0 .. $#constraints;
  	};
  }

  sub __deep_explanation
  {
  	my ($type, $value, $varname) = @_;

  	my @constraints = @{ $type->parameters };
  	my $slurpy;
  	if (exists $constraints[-1] and ref $constraints[-1] eq "HASH")
  	{
  		$slurpy = Types::TypeTiny::to_TypeTiny(pop(@constraints)->{slurpy});
  	}
  	@constraints = map Types::TypeTiny::to_TypeTiny($_), @constraints;

  	if (@constraints < @$value and not $slurpy)
  	{
  		return [
  			sprintf('"%s" expects at most %d values in the array', $type, scalar(@constraints)),
  			sprintf('%d values found; too many', scalar(@$value)),
  		];
  	}

  	for my $i (0 .. $#constraints)
  	{
  		next if $constraints[$i]->is_strictly_a_type_of( Types::Standard::Optional ) && $i > $#$value;
  		next if $constraints[$i]->check($value->[$i]);

  		return [
  			sprintf('"%s" constrains value at index %d of array with "%s"', $type, $i, $constraints[$i]),
  			@{ $constraints[$i]->validate_explain($value->[$i], sprintf('%s->[%s]', $varname, $i)) },
  		];
  	}

  	if (defined($slurpy))
  	{
  		my $tmp = $slurpy->is_a_type_of(Types::Standard::HashRef)
  			? +{@$value[$#constraints+1 .. $#$value]}
  			: +[@$value[$#constraints+1 .. $#$value]];
  		$slurpy->check($tmp) or return [
  			sprintf(
  				'Array elements from index %d are slurped into a %s which is constrained with "%s"',
  				$#constraints+1,
  				$slurpy->is_a_type_of(Types::Standard::HashRef) ? 'hashref' : 'arrayref',
  				$slurpy,
  			),
  			@{ $slurpy->validate_explain($tmp, '$SLURPY') },
  		];
  	}

  	# This should never happen...
  	return;  # uncoverable statement
  }

  my $label_counter = 0;
  sub __coercion_generator
  {
  	my ($parent, $child, @tuple) = @_;
  	my $C = "Type::Coercion"->new(type_constraint => $child);

  	my $slurpy;
  	if (exists $tuple[-1] and ref $tuple[-1] eq "HASH")
  	{
  		$slurpy = pop(@tuple)->{slurpy};
  	}

  	my $all_inlinable = 1;
  	for my $tc (@tuple, ($slurpy ? $slurpy : ()))
  	{
  		$all_inlinable = 0 if !$tc->can_be_inlined;
  		$all_inlinable = 0 if $tc->has_coercion && !$tc->coercion->can_be_inlined;
  		last if!$all_inlinable;
  	}

  	if ($all_inlinable)
  	{
  		$C->add_type_coercions($parent => Types::Standard::Stringable {
  			my $label = sprintf("TUPLELABEL%d", ++$label_counter);
  			my @code;
  			push @code, 'do { my ($orig, $return_orig, $tmp, @new) = ($_, 0);';
  			push @code,       "$label: {";
  			push @code,       sprintf('(($return_orig = 1), last %s) if @$orig > %d;', $label, scalar @tuple) unless $slurpy;
  			for my $i (0 .. $#tuple)
  			{
  				my $ct = $tuple[$i];
  				my $ct_coerce   = $ct->has_coercion;
  				my $ct_optional = $ct->is_a_type_of(Types::Standard::Optional);

  				push @code, sprintf(
  					'if (@$orig > %d) { $tmp = %s; (%s) ? ($new[%d]=$tmp) : ($return_orig=1 and last %s) }',
  					$i,
  					$ct_coerce
  						? $ct->coercion->inline_coercion("\$orig->[$i]")
  						: "\$orig->[$i]",
  					$ct->inline_check('$tmp'),
  					$i,
  					$label,
  				);
  			}
  			if ($slurpy)
  			{
  				my $size = @tuple;
  				push @code, sprintf('if (@$orig > %d) {', $size);
  				push @code, sprintf('my $tail = [ @{$orig}[%d .. $#$orig] ];', $size);
  				push @code, $slurpy->has_coercion
  					? sprintf('$tail = %s;', $slurpy->coercion->inline_coercion('$tail'))
  					: q();
  				push @code, sprintf(
  					'(%s) ? push(@new, @$tail) : ($return_orig++);',
  					$slurpy->inline_check('$tail'),
  				);
  				push @code, '}';
  			}
  			push @code,       '}';
  			push @code,    '$return_orig ? $orig : \\@new';
  			push @code, '}';
  			"@code";
  		});
  	}

  	else
  	{
  		my @is_optional = map !!$_->is_strictly_a_type_of($_Optional), @tuple;

  		$C->add_type_coercions(
  			$parent => sub {
  				my $value = @_ ? $_[0] : $_;

  				if (!$slurpy and @$value > @tuple)
  				{
  					return $value;
  				}

  				my @new;
  				for my $i (0 .. $#tuple)
  				{
  					return \@new if $i > $#$value and $is_optional[$i];

  					my $ct = $tuple[$i];
  					my $x  = $ct->has_coercion ? $ct->coerce($value->[$i]) : $value->[$i];

  					return $value unless $ct->check($x);

  					$new[$i] = $x;
  				}

  				if ($slurpy and @$value > @tuple)
  				{
  					my $tmp = $slurpy->has_coercion
  						? $slurpy->coerce([ @{$value}[@tuple .. $#$value] ])
  						: [ @{$value}[@tuple .. $#$value] ];
  					$slurpy->check($tmp) ? push(@new, @$tmp) : return($value);
  				}

  				return \@new;
  			},
  		);
  	};

  	return $C;
  }

  1;

  __END__

  =pod

  =encoding utf-8

  =head1 NAME

  Types::Standard::Tuple - internals for the Types::Standard Tuple type constraint

  =head1 STATUS

  This module is considered part of Type-Tiny's internals. It is not
  covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  This file contains some of the guts for L<Types::Standard>.
  It will be loaded on demand. You may ignore its presence.

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Types::Standard>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

TYPES_STANDARD_TUPLE

$fatpacked{"Types/TypeTiny.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TYPES_TYPETINY';
  package Types::TypeTiny;

  use strict;
  use warnings;

  our $AUTHORITY = 'cpan:TOBYINK';
  our $VERSION   = '1.000005';

  use Scalar::Util qw< blessed refaddr weaken >;

  our @EXPORT_OK = ( __PACKAGE__->type_names, qw/to_TypeTiny/ );

  my %cache;

  sub import
  {
  	# do the shuffle!
  	no warnings "redefine";
  	our @ISA = qw( Exporter::Tiny );
  	require Exporter::Tiny;
  	my $next = \&Exporter::Tiny::import;
  	*import = $next;
  	my $class = shift;
  	my $opts  = { ref($_[0]) ? %{+shift} : () };
  	$opts->{into} ||= scalar(caller);
  	return $class->$next($opts, @_);
  }

  sub meta
  {
  	return $_[0];
  }

  sub type_names
  {
  	qw( CodeLike StringLike TypeTiny HashLike ArrayLike );
  }

  sub has_type
  {
  	my %has = map +($_ => 1), shift->type_names;
  	!!$has{ $_[0] };
  }

  sub get_type
  {
  	my $self = shift;
  	return unless $self->has_type(@_);
  	no strict qw(refs);
  	&{$_[0]}();
  }

  sub coercion_names
  {
  	qw();
  }

  sub has_coercion
  {
  	my %has = map +($_ => 1), shift->coercion_names;
  	!!$has{ $_[0] };
  }

  sub get_coercion
  {
  	my $self = shift;
  	return unless $self->has_coercion(@_);
  	no strict qw(refs);
  	&{$_[0]}();  # uncoverable statement
  }

  sub StringLike ()
  {
  	require Type::Tiny;
  	$cache{StringLike} ||= "Type::Tiny"->new(
  		name       => "StringLike",
  		constraint => sub {    defined($_   ) && !ref($_   ) or Scalar::Util::blessed($_   ) && overload::Method($_   , q[""])  },
  		inlined    => sub { qq/defined($_[1]) && !ref($_[1]) or Scalar::Util::blessed($_[1]) && overload::Method($_[1], q[""])/ },
  		library    => __PACKAGE__,
  	);
  }

  sub HashLike ()
  {
  	require Type::Tiny;
  	$cache{HashLike} ||= "Type::Tiny"->new(
  		name       => "HashLike",
  		constraint => sub {    ref($_   ) eq q[HASH] or Scalar::Util::blessed($_   ) && overload::Method($_   , q[%{}])  },
  		inlined    => sub { qq/ref($_[1]) eq q[HASH] or Scalar::Util::blessed($_[1]) && overload::Method($_[1], q[\%{}])/ },
  		library    => __PACKAGE__,
  	);
  }

  sub ArrayLike ()
  {
  	require Type::Tiny;
  	$cache{ArrayLike} ||= "Type::Tiny"->new(
  		name       => "ArrayLike",
  		constraint => sub {    ref($_   ) eq q[ARRAY] or Scalar::Util::blessed($_   ) && overload::Method($_   , q[@{}])  },
  		inlined    => sub { qq/ref($_[1]) eq q[ARRAY] or Scalar::Util::blessed($_[1]) && overload::Method($_[1], q[\@{}])/ },
  		library    => __PACKAGE__,
  	);
  }

  sub CodeLike ()
  {
  	require Type::Tiny;
  	$cache{CodeLike} ||= "Type::Tiny"->new(
  		name       => "CodeLike",
  		constraint => sub {    ref($_   ) eq q[CODE] or Scalar::Util::blessed($_   ) && overload::Method($_   , q[&{}])  },
  		inlined    => sub { qq/ref($_[1]) eq q[CODE] or Scalar::Util::blessed($_[1]) && overload::Method($_[1], q[\&{}])/ },
  		library    => __PACKAGE__,
  	);
  }

  sub TypeTiny ()
  {
  	require Type::Tiny;
  	$cache{TypeTiny} ||= "Type::Tiny"->new(
  		name       => "TypeTiny",
  		constraint => sub {  Scalar::Util::blessed($_   ) && $_   ->isa(q[Type::Tiny])  },
  		inlined    => sub { my $var = $_[1]; "Scalar::Util::blessed($var) && $var\->isa(q[Type::Tiny])" },
  		library    => __PACKAGE__,
  	);
  }

  my %ttt_cache;

  sub to_TypeTiny
  {
  	my $t = $_[0];

  	return $t unless (my $ref = ref $t);
  	return $t if $ref =~ /^Type::Tiny\b/;

  	return $ttt_cache{ refaddr($t) } if $ttt_cache{ refaddr($t) };

  	if (my $class = blessed $t)
  	{
  		return $t                               if $class->isa("Type::Tiny");
  		return _TypeTinyFromMoose($t)           if $class->isa("Moose::Meta::TypeConstraint");
  		return _TypeTinyFromMoose($t)           if $class->isa("MooseX::Types::TypeDecorator");
  		return _TypeTinyFromValidationClass($t) if $class->isa("Validation::Class::Simple");
  		return _TypeTinyFromValidationClass($t) if $class->isa("Validation::Class");
  		return _TypeTinyFromGeneric($t)         if $t->can("check") && $t->can("get_message"); # i.e. Type::API::Constraint
  	}

  	return _TypeTinyFromCodeRef($t) if $ref eq q(CODE);

  	$t;
  }

  sub _TypeTinyFromMoose
  {
  	my $t = $_[0];

  	if (ref $t->{"Types::TypeTiny::to_TypeTiny"})
  	{
  		return $t->{"Types::TypeTiny::to_TypeTiny"};
  	}

  	if ($t->name ne '__ANON__')
  	{
  		require Types::Standard;
  		my $ts = 'Types::Standard'->get_type($t->name);
  		return $ts if $ts->{_is_core};
  	}

  	my %opts;
  	$opts{display_name} = $t->name;
  	$opts{constraint}   = $t->constraint;
  	$opts{parent}       = to_TypeTiny($t->parent)              if $t->has_parent;
  	$opts{inlined}      = sub { shift; $t->_inline_check(@_) } if $t->can_be_inlined;
  	$opts{message}      = sub { $t->get_message($_) }          if $t->has_message;
  	$opts{moose_type}   = $t;

  	require Type::Tiny;
  	my $new = 'Type::Tiny'->new(%opts);
  	$ttt_cache{ refaddr($t) } = $new;
  	weaken($ttt_cache{ refaddr($t) });

  	$new->{coercion} = do {
  		require Type::Coercion::FromMoose;
  		'Type::Coercion::FromMoose'->new(
  			type_constraint => $new,
  			moose_coercion  => $t->coercion,
  		);
  	} if $t->has_coercion;

  	return $new;
  }

  sub _TypeTinyFromValidationClass
  {
  	my $t = $_[0];

  	require Type::Tiny;
  	require Types::Standard;

  	my %opts = (
  		parent            => Types::Standard::HashRef(),
  		_validation_class => $t,
  	);

  	if ($t->VERSION >= "7.900048")
  	{
  		$opts{constraint} = sub {
  			$t->params->clear;
  			$t->params->add(%$_);
  			my $f = $t->filtering; $t->filtering('off');
  			my $r = eval { $t->validate };
  			$t->filtering($f || 'pre');
  			return $r;
  		};
  		$opts{message} = sub {
  			$t->params->clear;
  			$t->params->add(%$_);
  			my $f = $t->filtering; $t->filtering('off');
  			my $r = (eval { $t->validate } ? "OK" : $t->errors_to_string);
  			$t->filtering($f || 'pre');
  			return $r;
  		};
  	}
  	else  # need to use hackish method
  	{
  		$opts{constraint} = sub {
  			$t->params->clear;
  			$t->params->add(%$_);
  			no warnings "redefine";
  			local *Validation::Class::Directive::Filters::execute_filtering = sub { $_[0] };
  			eval { $t->validate };
  		};
  		$opts{message} = sub {
  			$t->params->clear;
  			$t->params->add(%$_);
  			no warnings "redefine";
  			local *Validation::Class::Directive::Filters::execute_filtering = sub { $_[0] };
  			eval { $t->validate } ? "OK" : $t->errors_to_string;
  		};
  	}

  	require Type::Tiny;
  	my $new = "Type::Tiny"->new(%opts);

  	$new->coercion->add_type_coercions(
  		Types::Standard::HashRef() => sub {
  			my %params = %$_;
  			for my $k (keys %params)
  				{ delete $params{$_} unless $t->get_fields($k) };
  			$t->params->clear;
  			$t->params->add(%params);
  			eval { $t->validate };
  			$t->get_hash;
  		},
  	);

  	$ttt_cache{ refaddr($t) } = $new;
  	weaken($ttt_cache{ refaddr($t) });
  	return $new;
  }

  sub _TypeTinyFromGeneric
  {
  	my $t = $_[0];

  	# XXX - handle inlining??

  	my %opts = (
  		constraint => sub { $t->check(@_ ? @_ : $_) },
  		message    => sub { $t->get_message(@_ ? @_ : $_) },
  	);

  	$opts{display_name} = $t->name if $t->can("name");

  	$opts{coercion} = sub { $t->coerce(@_ ? @_ : $_) }
  		if $t->can("has_coercion") && $t->has_coercion && $t->can("coerce");

  	require Type::Tiny;
  	my $new = "Type::Tiny"->new(%opts);
  	$ttt_cache{ refaddr($t) } = $new;
  	weaken($ttt_cache{ refaddr($t) });
  	return $new;
  }

  my $QFS;
  sub _TypeTinyFromCodeRef
  {
  	my $t = $_[0];

  	my %opts = (
  		constraint => sub {
  			return !!eval { $t->($_) };
  		},
  		message => sub {
  			local $@;
  			eval { $t->($_); 1 } or do { chomp $@; return $@ if $@ };
  			return sprintf('%s did not pass type constraint', Type::Tiny::_dd($_));
  		},
  	);

  	if ($QFS ||= "Sub::Quote"->can("quoted_from_sub"))
  	{
  		my (undef, $perlstring, $captures) = @{ $QFS->($t) || [] };
  		if ($perlstring)
  		{
  			$perlstring = "!!eval{ $perlstring }";
  			$opts{inlined} = sub
  			{
  				my $var = $_[1];
  				Sub::Quote::inlinify(
  					$perlstring,
  					$var,
  					$var eq q($_) ? '' : "local \$_ = $var;",
  					1,
  				);
  			} if $perlstring && !$captures;
  		}
  	}

  	require Type::Tiny;
  	my $new = "Type::Tiny"->new(%opts);
  	$ttt_cache{ refaddr($t) } = $new;
  	weaken($ttt_cache{ refaddr($t) });
  	return $new;
  }

  1;

  __END__

  =pod

  =encoding utf-8

  =for stopwords arrayfication hashification

  =head1 NAME

  Types::TypeTiny - type constraints used internally by Type::Tiny

  =head1 STATUS

  This module is covered by the
  L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.

  =head1 DESCRIPTION

  Dogfooding.

  This isn't a real Type::Library-based type library; that would involve
  too much circularity. But it exports some type constraints which, while
  designed for use within Type::Tiny, may be more generally useful.

  =head2 Types

  =over

  =item C<< StringLike >>

  Accepts strings and objects overloading stringification.

  =item C<< HashLike >>

  Accepts hashrefs and objects overloading hashification.

  =item C<< ArrayLike >>

  Accepts arrayrefs and objects overloading arrayfication.

  =item C<< CodeLike >>

  Accepts coderefs and objects overloading codification.

  =item C<< TypeTiny >>

  Accepts blessed L<Type::Tiny> objects.

  =back

  =head2 Coercion Functions

  =over

  =item C<< to_TypeTiny($constraint) >>

  Promotes (or "demotes" if you prefer) a Moose::Meta::TypeConstraint object
  to a Type::Tiny object.

  Can also handle L<Validation::Class> objects. Type constraints built from
  Validation::Class objects deliberately I<ignore> field filters when they
  do constraint checking (and go to great lengths to do so); using filters for
  coercion only. (The behaviour of C<coerce> if we don't do that is just too
  weird!)

  Can also handle any object providing C<check> and C<get_message> methods.
  (This includes L<Mouse::Meta::TypeConstraint> objects.) If the object also
  provides C<has_coercion> and C<coerce> methods, these will be used too.

  Can also handle coderefs (but not blessed coderefs or objects overloading
  C<< &{} >>). Coderefs are expected to return true iff C<< $_ >> passes the
  constraint. If C<< $_ >> fails the type constraint, they may either return
  false, or die with a helpful error message.

  =back

  =head2 Methods

  These are implemented so that C<< Types::TypeTiny->meta->get_type($foo) >>
  works, for rough compatibility with a real L<Type::Library> type library.

  =over

  =item C<< meta >>

  =item C<< type_names >>

  =item C<< get_type($name) >>

  =item C<< has_type($name) >>

  =item C<< coercion_names >>

  =item C<< get_coercion($name) >>

  =item C<< has_coercion($name) >>

  =back

  =head1 BUGS

  Please report any bugs to
  L<http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.

  =head1 SEE ALSO

  L<Type::Tiny>.

  =head1 AUTHOR

  Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

  =head1 COPYRIGHT AND LICENCE

  This software is copyright (c) 2013-2014 by Toby Inkster.

  This is free software; you can redistribute it and/or modify it under
  the same terms as the Perl 5 programming language system itself.

  =head1 DISCLAIMER OF WARRANTIES

  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

TYPES_TYPETINY

$fatpacked{"namespace/clean.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'NAMESPACE_CLEAN';
  package namespace::clean;

  use warnings;
  use strict;

  our $VERSION = '0.27';
  $VERSION = eval $VERSION if $VERSION =~ /_/; # numify for warning-free dev releases

  our $STORAGE_VAR = '__NAMESPACE_CLEAN_STORAGE';

  use B::Hooks::EndOfScope 'on_scope_end';

  # FIXME This is a crock of shit, needs to go away
  # currently here to work around https://rt.cpan.org/Ticket/Display.html?id=74151
  # kill with fire when PS::XS is *finally* fixed
  BEGIN {
    my $provider;

    if ( "$]" < 5.008007 ) {
      require Package::Stash::PP;
      $provider = 'Package::Stash::PP';
    }
    else {
      require Package::Stash;
      $provider = 'Package::Stash';
    }
    eval <<"EOS" or die $@;

  sub stash_for (\$) {
    $provider->new(\$_[0]);
  }

  1;

  EOS
  }

  use namespace::clean::_Util qw( DEBUGGER_NEEDS_CV_RENAME DEBUGGER_NEEDS_CV_PIVOT );

  # Built-in debugger CV-retrieval fixups necessary before perl 5.15.5:
  # since we are deleting the glob where the subroutine was originally
  # defined, the assumptions below no longer hold.
  #
  # In 5.8.9 ~ 5.13.5 (inclusive) the debugger assumes that a CV can
  # always be found under sub_fullname($sub)
  # Workaround: use sub naming to properly name the sub hidden in the package's
  # deleted-stash
  #
  # In the rest of the range ( ... ~ 5.8.8 and 5.13.6 ~ 5.15.4 ) the debugger
  # assumes the name of the glob passed to entersub can be used to find the CV
  # Workaround: realias the original glob to the deleted-stash slot
  #
  # While the errors manifest themselves inside perl5db.pl, they are caused by
  # problems inside the interpreter.  If enabled ($^P & 0x01) and existent,
  # the DB::sub sub will be called by the interpreter for any sub call rather
  # that call the sub directly.  It is provided the real sub to call in $DB::sub,
  # but the value given has the issues described above.  We only have to enable
  # the workaround if DB::sub will be used.
  #
  # Can not tie constants to the current value of $^P directly,
  # as the debugger can be enabled during runtime (kinda dubious)
  #

  my $RemoveSubs = sub {
      my $cleanee = shift;
      my $store   = shift;
      my $cleanee_stash = stash_for($cleanee);
      my $deleted_stash;

    SYMBOL:
      for my $f (@_) {

          # ignore already removed symbols
          next SYMBOL if $store->{exclude}{ $f };

          my $sub = $cleanee_stash->get_symbol("&$f")
            or next SYMBOL;

          my $need_debugger_fixup =
            ( DEBUGGER_NEEDS_CV_RENAME or DEBUGGER_NEEDS_CV_PIVOT )
              &&
            $^P & 0x01
              &&
            defined &DB::sub
              &&
            ref(my $globref = \$cleanee_stash->namespace->{$f}) eq 'GLOB'
              &&
           ( $deleted_stash ||= stash_for("namespace::clean::deleted::$cleanee") )
          ;

          # convince the Perl debugger to work
          # see the comment on top
          if ( DEBUGGER_NEEDS_CV_RENAME and $need_debugger_fixup ) {
            #
            # Note - both get_subname and set_subname are only compiled when CV_RENAME
            # is true ( the 5.8.9 ~ 5.12 range ). On other perls this entire block is
            # constant folded away, and so are the definitions in ::_Util
            #
            # Do not be surprised that they are missing without DEBUGGER_NEEDS_CV_RENAME
            #
            namespace::clean::_Util::get_subname( $sub ) eq  ( $cleanee_stash->name . "::$f" )
              and
            $deleted_stash->add_symbol(
              "&$f",
              namespace::clean::_Util::set_subname( $deleted_stash->name . "::$f", $sub ),
            );
          }
          elsif ( DEBUGGER_NEEDS_CV_PIVOT and $need_debugger_fixup ) {
            $deleted_stash->add_symbol("&$f", $sub);
          }

          my @symbols = map {
              my $name = $_ . $f;
              my $def = $cleanee_stash->get_symbol($name);
              defined($def) ? [$name, $def] : ()
          } '$', '@', '%', '';

          $cleanee_stash->remove_glob($f);

          # if this perl needs no renaming trick we need to
          # rename the original glob after the fact
          DEBUGGER_NEEDS_CV_PIVOT
            and
          $need_debugger_fixup
            and
          *$globref = $deleted_stash->namespace->{$f};

          $cleanee_stash->add_symbol(@$_) for @symbols;
      }
  };

  sub clean_subroutines {
      my ($nc, $cleanee, @subs) = @_;
      $RemoveSubs->($cleanee, {}, @subs);
  }

  sub import {
      my ($pragma, @args) = @_;

      my (%args, $is_explicit);

    ARG:
      while (@args) {

          if ($args[0] =~ /^\-/) {
              my $key = shift @args;
              my $value = shift @args;
              $args{ $key } = $value;
          }
          else {
              $is_explicit++;
              last ARG;
          }
      }

      my $cleanee = exists $args{ -cleanee } ? $args{ -cleanee } : scalar caller;
      if ($is_explicit) {
          on_scope_end {
              $RemoveSubs->($cleanee, {}, @args);
          };
      }
      else {

          # calling class, all current functions and our storage
          my $functions = $pragma->get_functions($cleanee);
          my $store     = $pragma->get_class_store($cleanee);
          my $stash     = stash_for($cleanee);

          # except parameter can be array ref or single value
          my %except = map {( $_ => 1 )} (
              $args{ -except }
              ? ( ref $args{ -except } eq 'ARRAY' ? @{ $args{ -except } } : $args{ -except } )
              : ()
          );

          # register symbols for removal, if they have a CODE entry
          for my $f (keys %$functions) {
              next if     $except{ $f };
              next unless $stash->has_symbol("&$f");
              $store->{remove}{ $f } = 1;
          }

          on_scope_end {
              $RemoveSubs->($cleanee, $store, keys %{ $store->{remove} });
          };

          return 1;
      }
  }

  sub unimport {
      my ($pragma, %args) = @_;

      # the calling class, the current functions and our storage
      my $cleanee   = exists $args{ -cleanee } ? $args{ -cleanee } : scalar caller;
      my $functions = $pragma->get_functions($cleanee);
      my $store     = $pragma->get_class_store($cleanee);

      # register all unknown previous functions as excluded
      for my $f (keys %$functions) {
          next if $store->{remove}{ $f }
               or $store->{exclude}{ $f };
          $store->{exclude}{ $f } = 1;
      }

      return 1;
  }

  sub get_class_store {
      my ($pragma, $class) = @_;
      my $stash = stash_for($class);
      my $var = "%$STORAGE_VAR";
      $stash->add_symbol($var, {})
          unless $stash->has_symbol($var);
      return $stash->get_symbol($var);
  }

  sub get_functions {
      my ($pragma, $class) = @_;

      my $stash = stash_for($class);
      return {
          map { $_ => $stash->get_symbol("&$_") }
              $stash->list_all_symbols('CODE')
      };
  }

  'Danger! Laws of Thermodynamics may not apply.'

  __END__

  =head1 NAME

  namespace::clean - Keep imports and functions out of your namespace

  =head1 SYNOPSIS

    package Foo;
    use warnings;
    use strict;

    use Carp qw(croak);   # 'croak' will be removed

    sub bar { 23 }        # 'bar' will be removed

    # remove all previously defined functions
    use namespace::clean;

    sub baz { bar() }     # 'baz' still defined, 'bar' still bound

    # begin to collection function names from here again
    no namespace::clean;

    sub quux { baz() }    # 'quux' will be removed

    # remove all functions defined after the 'no' unimport
    use namespace::clean;

    # Will print: 'No', 'No', 'Yes' and 'No'
    print +(__PACKAGE__->can('croak') ? 'Yes' : 'No'), "\n";
    print +(__PACKAGE__->can('bar')   ? 'Yes' : 'No'), "\n";
    print +(__PACKAGE__->can('baz')   ? 'Yes' : 'No'), "\n";
    print +(__PACKAGE__->can('quux')  ? 'Yes' : 'No'), "\n";

    1;

  =head1 DESCRIPTION

  =head2 Keeping packages clean

  When you define a function, or import one, into a Perl package, it will
  naturally also be available as a method. This does not per se cause
  problems, but it can complicate subclassing and, for example, plugin
  classes that are included via multiple inheritance by loading them as
  base classes.

  The C<namespace::clean> pragma will remove all previously declared or
  imported symbols at the end of the current package's compile cycle.
  Functions called in the package itself will still be bound by their
  name, but they won't show up as methods on your class or instances.

  By unimporting via C<no> you can tell C<namespace::clean> to start
  collecting functions for the next C<use namespace::clean;> specification.

  You can use the C<-except> flag to tell C<namespace::clean> that you
  don't want it to remove a certain function or method. A common use would
  be a module exporting an C<import> method along with some functions:

    use ModuleExportingImport;
    use namespace::clean -except => [qw( import )];

  If you just want to C<-except> a single sub, you can pass it directly.
  For more than one value you have to use an array reference.

  =head3 Late binding caveat

  Note that the L<technique used by this module|/IMPLEMENTATION DETAILS> relies
  on perl having resolved all names to actual code references during the
  compilation of a scope. While this is almost always what the interpreter does,
  there are some exceptions, notably the L<sort SUBNAME|perlfunc/sort> style of
  the C<sort> built-in invocation. The following example will not work, because
  C<sort> does not try to resolve the function name to an actual code reference
  until B<runtime>.

   use MyApp::Utils 'my_sorter';
   use namespace::clean;

   my @sorted = sort my_sorter @list;

  You need to work around this by forcing a compile-time resolution like so:

   use MyApp::Utils 'my_sorter';
   use namespace::clean;

   my $my_sorter_cref = \&my_sorter;

   my @sorted = sort $my_sorter_cref @list;

  =head2 Explicitly removing functions when your scope is compiled

  It is also possible to explicitly tell C<namespace::clean> what packages
  to remove when the surrounding scope has finished compiling. Here is an
  example:

    package Foo;
    use strict;

    # blessed NOT available

    sub my_class {
        use Scalar::Util qw( blessed );
        use namespace::clean qw( blessed );

        # blessed available
        return blessed shift;
    }

    # blessed NOT available

  =head2 Moose

  When using C<namespace::clean> together with L<Moose> you want to keep
  the installed C<meta> method. So your classes should look like:

    package Foo;
    use Moose;
    use namespace::clean -except => 'meta';
    ...

  Same goes for L<Moose::Role>.

  =head2 Cleaning other packages

  You can tell C<namespace::clean> that you want to clean up another package
  instead of the one importing. To do this you have to pass in the C<-cleanee>
  option like this:

    package My::MooseX::namespace::clean;
    use strict;

    use namespace::clean (); # no cleanup, just load

    sub import {
        namespace::clean->import(
          -cleanee => scalar(caller),
          -except  => 'meta',
        );
    }

  If you don't care about C<namespace::clean>s discover-and-C<-except> logic, and
  just want to remove subroutines, try L</clean_subroutines>.

  =head1 METHODS

  =head2 clean_subroutines

  This exposes the actual subroutine-removal logic.

    namespace::clean->clean_subroutines($cleanee, qw( subA subB ));

  will remove C<subA> and C<subB> from C<$cleanee>. Note that this will remove the
  subroutines B<immediately> and not wait for scope end. If you want to have this
  effect at a specific time (e.g. C<namespace::clean> acts on scope compile end)
  it is your responsibility to make sure it runs at that time.

  =head2 import

  Makes a snapshot of the current defined functions and installs a
  L<B::Hooks::EndOfScope> hook in the current scope to invoke the cleanups.


  =head2 unimport

  This method will be called when you do a

    no namespace::clean;

  It will start a new section of code that defines functions to clean up.

  =head2 get_class_store

  This returns a reference to a hash in a passed package containing
  information about function names included and excluded from removal.

  =head2 get_functions

  Takes a class as argument and returns all currently defined functions
  in it as a hash reference with the function name as key and a typeglob
  reference to the symbol as value.

  =head1 IMPLEMENTATION DETAILS

  This module works through the effect that a

    delete $SomePackage::{foo};

  will remove the C<foo> symbol from C<$SomePackage> for run time lookups
  (e.g., method calls) but will leave the entry alive to be called by
  already resolved names in the package itself. C<namespace::clean> will
  restore and therefor in effect keep all glob slots that aren't C<CODE>.

  A test file has been added to the perl core to ensure that this behaviour
  will be stable in future releases.

  Just for completeness sake, if you want to remove the symbol completely,
  use C<undef> instead.

  =head1 SEE ALSO

  L<B::Hooks::EndOfScope>

  =head1 THANKS

  Many thanks to Matt S Trout for the inspiration on the whole idea.

  =head1 AUTHORS

  =over

  =item *

  Robert 'phaylon' Sedlacek <rs@474.at>

  =item *

  Florian Ragwitz <rafl@debian.org>

  =item *

  Jesse Luehrs <doy@tozt.net>

  =item *

  Peter Rabbitson <ribasushi@cpan.org>

  =item *

  Father Chrysostomos <sprout@cpan.org>

  =back

  =head1 COPYRIGHT AND LICENSE

  This software is copyright (c) 2011 by L</AUTHORS>

  This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
NAMESPACE_CLEAN

$fatpacked{"namespace/clean/_Util.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'NAMESPACE_CLEAN__UTIL';
  ###       !!!ACHTUNG!!!
  #
  # This module is to be loaded at configure time straight from the Makefile.PL
  # in order to get access to some of the constants / utils
  # None of the dependencies will be available yet at this point, so make
  # sure to never use anything beyond what the minimum supported perl came with
  # (no, relying on configure_requires is not ok)

  package # hide from the pauses
    namespace::clean::_Util;

  use warnings;
  use strict;

  use base 'Exporter';
  our @EXPORT_OK = qw( DEBUGGER_NEEDS_CV_RENAME DEBUGGER_NEEDS_CV_PIVOT );

  use constant DEBUGGER_NEEDS_CV_RENAME => ( ( "$]" > 5.008_008 ) and ( "$]" < 5.013_006 ) );
  use constant DEBUGGER_NEEDS_CV_PIVOT => ( ( ! DEBUGGER_NEEDS_CV_RENAME ) and ( "$]" < 5.015_005 ) );

  # FIXME - ideally this needs to be provided by some abstraction lib
  # but we don't have that yet
  BEGIN {
    #
    # Note - both get_subname and set_subname are only called by one block
    # which is compiled away unless CV_RENAME is true ( the 5.8.9 ~ 5.12 range ).
    # Hence we compile/provide the definitions here only when needed
    #
    DEBUGGER_NEEDS_CV_RENAME and ( eval <<'EOS' or die $@ );
  {
    my( $sub_name_loaded, $sub_util_loaded );

    sub _namer_load_error {
      return '' if $sub_util_loaded or $sub_name_loaded;

      # if S::N is loaded first *and* so is B - then go with that, otherwise
      # prefer Sub::Util as S::U will provide a faster get_subname and will
      # not need further require() calls
      # this is rather arbitrary but remember this code exists only perls
      # between 5.8.9 ~ 5.13.5

      # when changing version also change in Makefile.PL
      my $sn_ver = 0.04;

      local $@;
      my $err = '';

      (
        ! (
          $INC{"B.pm"}
            and
          $INC{"Sub/Name.pm"}
            and
          eval { Sub::Name->VERSION($sn_ver) }
        )
          and
        eval { require Sub::Util }
          and
        # see https://github.com/moose/Moo/commit/dafa5118
        defined &Sub::Util::set_subname
          and
        $sub_util_loaded = 1
      )
        or
      (
        eval { require Sub::Name and Sub::Name->VERSION($sn_ver) }
          and
        $sub_name_loaded = 1
      )
        or
      $err = "When running under -d on this perl $], namespace::clean requires either Sub::Name $sn_ver or Sub::Util to be installed"
      ;

      $err;
    }

    sub set_subname {
      if( my $err = _namer_load_error() ) {
        die $err;
      }
      elsif( $sub_name_loaded ) {
        &Sub::Name::subname;
      }
      elsif( $sub_util_loaded ) {
        &Sub::Util::set_subname;
      }
      else {
        die "How the fuck did we get here? Read source and debug please!";
      }
    }

    sub get_subname {
      if(
        _namer_load_error()
          or
        ! $sub_util_loaded
      ) {
        require B;
        my $gv = B::svref_2object( $_[0] )->GV;
        join '::', $gv->STASH->NAME, $gv->NAME;
      }
      else {
        &Sub::Util::subname;
      }
    }
  }
  1;
  EOS

  }

  1;
NAMESPACE_CLEAN__UTIL

$fatpacked{"oo.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'OO';
  package oo;

  use Moo::_strictures;
  use Moo::_Utils qw(_load_module);

  sub moo {
    print <<'EOMOO';
   ______
  < Moo! >
   ------
          \   ^__^
           \  (oo)\_______
              (__)\       )\/\
                  ||----w |
                  ||     ||
  EOMOO
    exit 0;
  }

  BEGIN {
      my $package;
      sub import {
          moo() if $0 eq '-';
          $package = $_[1] || 'Class';
          if ($package =~ /^\+/) {
              $package =~ s/^\+//;
              _load_module($package);
          }
      }
      use Filter::Simple sub { s/^/package $package;\nuse Moo;\n/; }
  }

  1;
  __END__

  =head1 NAME

  oo - syntactic sugar for Moo oneliners

  =head1 SYNOPSIS

    perl -Moo=Foo -e 'has bar => ( is => q[ro], default => q[baz] ); print Foo->new->bar'

    # loads an existing class and re-"opens" the package definition
    perl -Moo=+My::Class -e 'print __PACKAGE__->new->bar'

  =head1 DESCRIPTION

  oo.pm is a simple source filter that adds C<package $name; use Moo;> to the
  beginning of your script, intended for use on the command line via the -M
  option.

  =head1 SUPPORT

  See L<Moo> for support and contact information.

  =head1 AUTHORS

  See L<Moo> for authors.

  =head1 COPYRIGHT AND LICENSE

  See L<Moo> for the copyright and license.

  =cut
OO

s/^  //mg for values %fatpacked;

my $class = 'FatPacked::'.(0+\%fatpacked);
no strict 'refs';
*{"${class}::files"} = sub { keys %{$_[0]} };

if ($] < 5.008) {
  *{"${class}::INC"} = sub {
    if (my $fat = $_[0]{$_[1]}) {
      my $pos = 0;
      my $last = length $fat;
      return (sub {
        return 0 if $pos == $last;
        my $next = (1 + index $fat, "\n", $pos) || $last;
        $_ .= substr $fat, $pos, $next - $pos;
        $pos = $next;
        return 1;
      });
    }
  };
}

else {
  *{"${class}::INC"} = sub {
    if (my $fat = $_[0]{$_[1]}) {
      open my $fh, '<', \$fat
        or die "FatPacker error loading $_[1] (could be a perl installation issue?)";
      return $fh;
    }
    return;
  };
}

unshift @INC, bless \%fatpacked, $class;
  } # END OF FATPACK CODE

use warnings;
use strict;
use Getopt::Std;
use Bio::Cigar;  # Cpan this if you want to run this script !!
use List::Util qw(max);

use vars qw/ %opt /;

# this program is subsequently packed via App::FatPacker
# see http://perltricks.com/article/58/2014/1/5/The-easy-way-to-build-stand-alone-Perl-apps/
# install fatpack via cpan App::FatPacker
# fatpack pack hapture.pl > hapture
# either perl hapture or -run as executable by chmod 755


sub init(){
	getopts( "hv:s:i:g:", \%opt ) or usage();
	usage() if $opt{h};
	print STDERR "Require path specification for VCF file: -v\n" and exit if not defined $opt{v};
	print STDERR "Require path specification for SAM file: -s\n" and exit if not defined $opt{s};
	print STDERR "Require individual ID: -i\n" and exit if not defined $opt{i};
	print STDERR "Require group ID: -g \n" and exit if not defined $opt{g};
}


sub usage(){
print STDERR << "EOF";
    This program gathers variant haplotype sites from SAM alignment file, and reports a summary file for those variant sites

    usage: $0 [-h] -v vcf_file -s sam_file -i int

     -h        : this (help) message
     -v file   : variant caller file - VCF format (!! assumed the position is sorted)
     -s file   : sequence alignment file - SAM format
     -i int    : individual ID (integer value or unbroken string)
     -g str    : group ID (unbroken string)

    example: $0 -v s1.vcf -s s1.sam -i 0 -g sebastes

EOF
        exit;
}

#----- get user's input parameters ------

init();

#---------------------------------------


#----- read vcf file -------------

# Objective: keeps variants' info into memory so that
# I can tell whether there are any variant sites for
# the alignment read entry from the SAM file

my $vcf; # a hash reference that keeps track of essential vcf info: reference variant, derived variants, pos
my $hap;

open VCF, $opt{v};
while (<VCF>) {
	next if /^#/;
	my @line = split "\t";
	# for now, we only concern SNP site, (exclude indel and any other complex events)

	# reference allele
	next if length($line[3]) > 1;
	# derived allele
	my $max_len = 0;
	my @snp = split ",", $line[4];
	for my $deriv (@snp) {
		$max_len = length($deriv) if length($deriv) > $max_len;
	}
	next if $max_len > 1;

	#print $line[0], "\t", $line[3], "\t", $line[4], "\n";
	push @{$vcf->{$line[0]}}, $line[1];
	push @{$vcf->{"ref_".$line[0]}}, $line[3];
	push @{$vcf->{"der_".$line[0]}}, $snp[0];
}
close VCF;

#----------------------------------------


open SAM, $opt{s};
while(<SAM>) {
	next if /^\@/;
	my @lines = split "\t";
	my $id = $lines[2];
    next if $lines[1] >= 256; # skip entries that are secondary alignment or to multiple sites
	my $st_qpos = $lines[3]; # starting query position
	#my $mapq = $lines[4]; # mapping quality score
	#skip if the alignment id is not found in the vcf hash ref
	next if not defined $vcf->{$id};

  next if $lines[5] eq "*";
	my $cigar = Bio::Cigar->new($lines[5]);
	my @qseq = split "", $lines[9];
	my @qseq_qual = split "", $lines[10];

	next if $#qseq < 1;
	#print "Query length is ", $cigar->query_length, "\n";
	#print "Reference length is ", $cigar->reference_length, "\n";
	my $hapRead={};
	$hapRead->{"seq"} = "";
	my $ct=0;
	for my $rpos (@{$vcf->{$id}}) {
		my $rpos_adj = $rpos - $st_qpos +1;
		$ct++;

		if ($cigar->reference_length < $rpos_adj || $rpos_adj < 1) {
			$hapRead->{"seq"} .= "N"; # marked as unknown
			push @{$hapRead->{"qual"}}, "_";
			next;
		}
		my ($qpos, $op) = $cigar->rpos_to_qpos($rpos_adj);

		if (not defined $qpos) {
			$hapRead->{"seq"} .= "X"; # marked as deletion site
			push @{$hapRead->{"qual"}}, "_";
 		}
		else {
			$hapRead->{"seq"} .= $qseq[$qpos-1];
			push @{$hapRead->{"qual"}}, $qseq_qual[$qpos-1];
		}

		#print $qpos-1, "\t", $#qseq, "\t", $lines[0], "\t", $id, "\n";
		#print join "\t", $id, $rpos, $qseq[$qpos-1], $qseq_qual[$qpos-1], "\n" if $qpos != -1;
	}

	$hap->{$id}->{$hapRead->{"seq"}}->{"ct"}++;
	for my $i (0..$#{$vcf->{$id}}) {

	  if(! defined ${$hap->{$id}->{$hapRead->{"seq"}}->{"maxC"}}[$i]) {
	 	${$hap->{$id}->{$hapRead->{"seq"}}->{"maxC"}}[$i] = 0;
	 	${$hap->{$id}->{$hapRead->{"seq"}}->{"sC"}}[$i] = 0;
	 	}

		my $q = 10**(-(ord(${$hapRead->{"qual"}}[$i])-33)/10);
		#${$hap->{$id}->{$hapRead->{"seq"}}->{"logC"}}[$i]+= log(1-$q) ;
	 	#${$hap->{$id}->{$hapRead->{"seq"}}->{"logW"}}[$i]+= log($q);
	 	${$hap->{$id}->{$hapRead->{"seq"}}->{"sC"}}[$i]+= 1-$q; # collecting the sum of prob phred site score for future use
	 	${$hap->{$id}->{$hapRead->{"seq"}}->{"maxC"}}[$i] = max(1-$q, ${$hap->{$id}->{$hapRead->{"seq"}}->{"maxC"}}[$i]);

	}
	#${$hap->{$id}->{$hapRead->{"seq"}}->{"mapq"}->{$mapq}}++; # collecting the MapQ alignment score

}


#--- output a haplotype summary file -----

for my $id (keys %{$hap}){
	for my $h (keys %{$hap->{$id}}){

		print join "\t", $opt{g}, # group label
				 $opt{i}, # individual id label
				$id, #locus id
				$h, # haplotype sequence
				$hap->{$id}->{$h}->{"ct"},  # number of occurence observed for this haplotype or read depth
				#(join ",", @{$hap->{$id}->{$h}->{"logC"}}), # log scale phred stat for being a correct base
				#(join ",", @{$hap->{$id}->{$h}->{"logW"}}), # log scale phred stat for being a miscalled base
				#(join ",", @{$vcf->{$id}}); # variant position
				(join ",", @{$hap->{$id}->{$h}->{"sC"}}), # sum of prob for calling correct base
				(join ",", @{$hap->{$id}->{$h}->{"maxC"}})."\n";# max phred score

		#print "\t";

    #print join ",", map {$_, ${$hap->{$id}->{$h}->{"mapq"}->{$_}}} (keys %{$hap->{$id}->{$h}->{"mapq"}});
	  #print "\n";
	}
}

#----------------------------------------
